From 5633bc4b9db0becd5bb935c33fec3ad221308032 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Tue, 3 Dec 2024 16:22:49 -0500 Subject: [PATCH] fix: Unescape JSON5 identifier values (#165) fixes #164 --- js/src/parse.js | 17 +++++++++++++++-- js/tests/parse.test.js | 7 +++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/js/src/parse.js b/js/src/parse.js index e62cdc6..f02cf60 100644 --- a/js/src/parse.js +++ b/js/src/parse.js @@ -50,6 +50,20 @@ const DEFAULT_OPTIONS = { allowTrailingCommas: false }; +const UNICODE_SEQUENCE = /\\u[\da-z]{4}/gu; + +/** + * Normalizes a JSON5 identifier by converting Unicode escape sequences into + * their corresponding characters. + * @param {string} identifier The identifier to normalize. + * @returns {string} The normalized identifier. + */ +function normalizeIdentifier(identifier) { + return identifier.replace(UNICODE_SEQUENCE, unicodeEscape => { + return String.fromCharCode(parseInt(unicodeEscape.slice(2), 16)); + }); +} + /** * Converts a JSON-encoded string into a JavaScript string, interpreting each * escape sequence. @@ -358,8 +372,7 @@ export function parse(text, options) { // check if the token is NaN or Infinity return t[identifier.includes("NaN") ? "nan" : "infinity"](/** @type {Sign} */ (sign), parts); } - - return t.identifier(identifier, parts); + return t.identifier(normalizeIdentifier(identifier), parts); } /** diff --git a/js/tests/parse.test.js b/js/tests/parse.test.js index d99d1a9..b853f6e 100644 --- a/js/tests/parse.test.js +++ b/js/tests/parse.test.js @@ -245,6 +245,13 @@ describe("parse()", () => { const result = parse(text, { mode: "json5" }); expect(result.body.value).to.equal(1); }); + + it("should unescape unquoted property names", () => { + const text = "{ f\\u006fo: 1 }"; + const expected = json5.parse(text); + const result = parse(text, { mode: "json5" }); + expect(result.body.members[0].name.name).to.equal(Object.keys(expected)[0]); + }); }); describe("fixtures", () => {