From 27be963343cd1804b7ced0e243de5a92332a2f23 Mon Sep 17 00:00:00 2001 From: Mathias Bynens Date: Thu, 26 Aug 2021 08:01:44 +0200 Subject: [PATCH 1/2] util: simplify util.toUSVString Refs: https://github.com/nodejs/node/pull/39814 --- lib/internal/util.js | 3 +-- test/parallel/test-util.js | 12 +++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/internal/util.js b/lib/internal/util.js index 34c210f27d7f7a..b4b27cefb98a3c 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -57,8 +57,7 @@ const experimentalWarnings = new SafeSet(); const colorRegExp = /\u001b\[\d\d?m/g; // eslint-disable-line no-control-regex -const unpairedSurrogateRe = - /(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/; +const unpairedSurrogateRe = /\p{Surrogate}/u; function toUSVString(val) { const str = `${val}`; // As of V8 5.5, `str.search()` (and `unpairedSurrogateRe[@@search]()`) are diff --git a/test/parallel/test-util.js b/test/parallel/test-util.js index 42218be8581579..739bd5d238583c 100644 --- a/test/parallel/test-util.js +++ b/test/parallel/test-util.js @@ -148,7 +148,17 @@ assert.strictEqual(util.isFunction(function() {}), true); assert.strictEqual(util.isFunction(), false); assert.strictEqual(util.isFunction('string'), false); -assert.strictEqual(util.toUSVString('string\ud801'), 'string\ufffd'); +// Lead surrogates: D800..DBFF +assert.strictEqual(util.toUSVString('string\ud800'), 'string\ufffd'); +assert.strictEqual(util.toUSVString('string\udabc'), 'string\ufffd'); +assert.strictEqual(util.toUSVString('string\udbff'), 'string\ufffd'); +// Trail surrogates: DC00..DFFF +assert.strictEqual(util.toUSVString('string\udc00'), 'string\ufffd'); +assert.strictEqual(util.toUSVString('string\ude12'), 'string\ufffd'); +assert.strictEqual(util.toUSVString('string\udfff'), 'string\ufffd'); +// Verify surrogate pairs are unaffected. +assert.strictEqual(util.toUSVString('string\ud800\udc00'), + 'string\ud800\udc00'); { assert.strictEqual(util.types.isNativeError(new Error()), true); From 4d54445a454dd3998587a53b5df4e93b33824a72 Mon Sep 17 00:00:00 2001 From: Mathias Bynens Date: Fri, 27 Aug 2021 11:16:47 +0200 Subject: [PATCH 2/2] util: improve `toUSVString` performance --- lib/internal/util.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/internal/util.js b/lib/internal/util.js index b4b27cefb98a3c..a3ecfb8837d1d3 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -17,10 +17,10 @@ const { Promise, ReflectApply, ReflectConstruct, - RegExpPrototypeExec, RegExpPrototypeTest, SafeMap, SafeSet, + StringPrototypeSearch, StringPrototypeReplace, StringPrototypeToLowerCase, StringPrototypeToUpperCase, @@ -60,12 +60,10 @@ const colorRegExp = /\u001b\[\d\d?m/g; // eslint-disable-line no-control-regex const unpairedSurrogateRe = /\p{Surrogate}/u; function toUSVString(val) { const str = `${val}`; - // As of V8 5.5, `str.search()` (and `unpairedSurrogateRe[@@search]()`) are - // slower than `unpairedSurrogateRe.exec()`. - const match = RegExpPrototypeExec(unpairedSurrogateRe, str); - if (!match) + const index = StringPrototypeSearch(str, unpairedSurrogateRe); + if (index === -1) return str; - return _toUSVString(str, match.index); + return _toUSVString(str, index); } let uvBinding;