From 8b6f1f10a6231e23f1f155ab7d05e8ef44d4acab Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Tue, 14 Apr 2026 11:54:45 -0700 Subject: [PATCH 1/2] Escape < in strings --- src/function.ts | 1 - src/index.spec.ts | 6 +++++- src/index.ts | 2 +- src/quote.ts | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/function.ts b/src/function.ts index 5319549..97a8929 100644 --- a/src/function.ts +++ b/src/function.ts @@ -4,7 +4,6 @@ import { quoteKey, isValidVariableName } from "./quote"; /** * Used in function stringification. */ -/* istanbul ignore next */ const METHOD_NAMES_ARE_QUOTED = { " "() { diff --git a/src/index.spec.ts b/src/index.spec.ts index e03d411..eb07234 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -82,6 +82,8 @@ describe("javascript-stringify", () => { "should escape certain unicode sequences", test("\u0602", "'\\u0602'"), ); + + it("should escape < for safety", test("", "'\\u003c/script>'")); }); describe("numbers", () => { @@ -89,7 +91,7 @@ describe("javascript-stringify", () => { it("should stringify floats", test(10.5, "10.5")); - it('should stringify "NaN"', test(10.5, "10.5")); + it('should stringify "NaN"', test(NaN, "NaN")); it('should stringify "Infinity"', test(Infinity, "Infinity")); @@ -220,6 +222,8 @@ describe("javascript-stringify", () => { describe("RegExp", () => { it("should stringify as shorthand", test(/[abc]/gi, "/[abc]/gi")); + + it("should escape slashes", test(new RegExp("a/b"), "/a\\/b/")); }); describe("Number", () => { diff --git a/src/index.ts b/src/index.ts index 5ac8bd6..e7871bb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -66,7 +66,7 @@ export function stringify( // Track nodes to restore later. if (tracking.has(value)) { unpack.set(path.slice(1), tracking.get(value)!); - // Use `undefined` as temporaray stand-in for referenced nodes + // Use `undefined` as temporary stand-in for referenced nodes. return valueToString(undefined, space, onNext, key); } diff --git a/src/quote.ts b/src/quote.ts index 225b158..951b69c 100644 --- a/src/quote.ts +++ b/src/quote.ts @@ -7,7 +7,7 @@ import { Next } from "./types"; * Source: https://github.com/douglascrockford/JSON-js/blob/master/json2.js */ const ESCAPABLE = - /[\\\'\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + /[\\'<\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; /** * Map of characters to escape characters. From 03959c3ea93fc334e98c2cec7e49507542e9ef94 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Tue, 14 Apr 2026 12:06:06 -0700 Subject: [PATCH 2/2] Escape in regexp --- src/index.spec.ts | 15 +++++++++++++-- src/object.ts | 5 ++++- src/stringify.ts | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/index.spec.ts b/src/index.spec.ts index eb07234..67fe28d 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -221,9 +221,20 @@ describe("javascript-stringify", () => { }); describe("RegExp", () => { - it("should stringify as shorthand", test(/[abc]/gi, "/[abc]/gi")); + it( + "should stringify as shorthand", + test(/[abc]/gi, "new RegExp('[abc]', 'gi')"), + ); - it("should escape slashes", test(new RegExp("a/b"), "/a\\/b/")); + it( + "should escape slashes", + test(new RegExp("a/b"), "new RegExp('a\\\\/b')"), + ); + + it( + "should escape html characters", + test(new RegExp("