From ba3c7ae1b2f72dbb02ed421e4574d8fe57165aac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Newton/m=C2=B2?= <27069811+newtondividedbysqm@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:48:50 +0200 Subject: [PATCH 1/6] fix assertString to throw TypeErrors on objects with custom constructor property --- src/lib/util/assertString.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/util/assertString.js b/src/lib/util/assertString.js index 3baa4452f..e62e1a624 100644 --- a/src/lib/util/assertString.js +++ b/src/lib/util/assertString.js @@ -1,4 +1,4 @@ export default function assertString(input) { if (input === undefined || input === null) throw new TypeError(`Expected a string but received a ${input}`); - if (input.constructor.name !== 'String') throw new TypeError(`Expected a string but received a ${input.constructor.name}`); + if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`) } From 5dc7d99b3641194d25e957ec33df4fe438b9152f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Newton/m=C2=B2?= <27069811+newtondividedbysqm@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:57:14 +0200 Subject: [PATCH 2/6] Add tests for boxed strings and Objects pretending to be a string --- test/util.test.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/util.test.js b/test/util.test.js index 0146a4e2c..5edbf0441 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -54,11 +54,23 @@ describe('assertString', () => { assert.throws(() => { assertString([]); }, TypeError); }); + it('Should throw an error if argument provided is an Object pretending to be a \'string\'', () => { + assert.throws(() => { assertString({constructor: {name: "string"}}); }, TypeError); + }); + + it('Should throw an error if argument provided is an Object pretending to be a \'String\'', () => { + assert.throws(() => { assertString({constructor: {name: "String"}}); }, TypeError); + }); + it('Should not throw an error if the argument is an empty string', () => { assert.doesNotThrow(() => { assertString(''); }); }); - + it('Should not throw an error if the argument is a String', () => { assert.doesNotThrow(() => { assertString('antidisestablishmentarianism'); }); }); + + it('Should not throw an error if the argument is a boxed string', () => { + assert.doesNotThrow(() => { assertString(new String('antidisestablishmentarianism')); }); + }); }); From e17853b73292a9d7224871573db7e2bb92490253 Mon Sep 17 00:00:00 2001 From: Pascal <27069811+newtondividedbysqm@users.noreply.github.com> Date: Thu, 16 Apr 2026 14:39:23 +0200 Subject: [PATCH 3/6] fix linters --- src/lib/util/assertString.js | 2 +- test/util.test.js | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/util/assertString.js b/src/lib/util/assertString.js index e62e1a624..d9e9f3ec5 100644 --- a/src/lib/util/assertString.js +++ b/src/lib/util/assertString.js @@ -1,4 +1,4 @@ export default function assertString(input) { if (input === undefined || input === null) throw new TypeError(`Expected a string but received a ${input}`); - if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`) + if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`); } diff --git a/test/util.test.js b/test/util.test.js index 5edbf0441..169789ad8 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -55,22 +55,23 @@ describe('assertString', () => { }); it('Should throw an error if argument provided is an Object pretending to be a \'string\'', () => { - assert.throws(() => { assertString({constructor: {name: "string"}}); }, TypeError); + assert.throws(() => { assertString({ constructor: { name: 'string' } }); }, TypeError); }); it('Should throw an error if argument provided is an Object pretending to be a \'String\'', () => { - assert.throws(() => { assertString({constructor: {name: "String"}}); }, TypeError); + assert.throws(() => { assertString({ constructor: { name: 'String' } }); }, TypeError); }); it('Should not throw an error if the argument is an empty string', () => { assert.doesNotThrow(() => { assertString(''); }); }); - + it('Should not throw an error if the argument is a String', () => { assert.doesNotThrow(() => { assertString('antidisestablishmentarianism'); }); }); it('Should not throw an error if the argument is a boxed string', () => { + // eslint-disable-next-line no-new-wrappers assert.doesNotThrow(() => { assertString(new String('antidisestablishmentarianism')); }); }); }); From 872f4189e759365c7ba286ad26af171a5aef314f Mon Sep 17 00:00:00 2001 From: Pascal <27069811+newtondividedbysqm@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:11:06 +0200 Subject: [PATCH 4/6] fix unreachable nullish-coalescing from within TypeErrorConstructor --- src/lib/util/assertString.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/util/assertString.js b/src/lib/util/assertString.js index d9e9f3ec5..14dba23a8 100644 --- a/src/lib/util/assertString.js +++ b/src/lib/util/assertString.js @@ -1,4 +1,7 @@ export default function assertString(input) { if (input === undefined || input === null) throw new TypeError(`Expected a string but received a ${input}`); - if (typeof input !== 'string' && !(input instanceof String)) throw new TypeError(`Expected a string but received a ${input?.constructor?.name ?? typeof input}`); + if (typeof input !== 'string' && !(input instanceof String)) { + let inputConstructorName = input?.constructor?.name ? input.constructor.name : typeof input; + throw new TypeError(`Expected a string but received a ${inputConstructorName}`); + } } From faf79661f739b3a36de6d8537aef634646da22bf Mon Sep 17 00:00:00 2001 From: Pascal <27069811+newtondividedbysqm@users.noreply.github.com> Date: Thu, 16 Apr 2026 19:18:04 +0200 Subject: [PATCH 5/6] fix using ObjectToString over instanceof to prevent the check to fail when executed in a different context --- src/lib/util/assertString.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/util/assertString.js b/src/lib/util/assertString.js index 14dba23a8..475537806 100644 --- a/src/lib/util/assertString.js +++ b/src/lib/util/assertString.js @@ -1,6 +1,6 @@ export default function assertString(input) { if (input === undefined || input === null) throw new TypeError(`Expected a string but received a ${input}`); - if (typeof input !== 'string' && !(input instanceof String)) { + if (typeof input !== 'string' && Object.prototype.toString.call(input) !== '[object String]') { let inputConstructorName = input?.constructor?.name ? input.constructor.name : typeof input; throw new TypeError(`Expected a string but received a ${inputConstructorName}`); } From 36b9a1161879499dbaf662d6a55935e81b6c4fb8 Mon Sep 17 00:00:00 2001 From: Pascal <27069811+newtondividedbysqm@users.noreply.github.com> Date: Thu, 16 Apr 2026 19:43:36 +0200 Subject: [PATCH 6/6] add test case for objects without constructor name --- test/util.test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/util.test.js b/test/util.test.js index 169789ad8..b73b7a254 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -74,4 +74,8 @@ describe('assertString', () => { // eslint-disable-next-line no-new-wrappers assert.doesNotThrow(() => { assertString(new String('antidisestablishmentarianism')); }); }); + + it('Should use typeof as fallback in error message when input has no constructor name', () => { + assert.throws(() => { assertString(Object.create(null)); }, /^TypeError: Expected a string but received a object$/); + }); });