diff --git a/lib/internal/util.js b/lib/internal/util.js index 34c210f27d7f7a..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, @@ -57,16 +57,13 @@ 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 - // 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; 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);