From e04a10b11356ad3a0d351f4bfab30c8ee5a33db9 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Thu, 19 Aug 2021 21:40:18 +0200 Subject: [PATCH 1/4] util: expose toUSVString Expose toUSVString to it can be used by user libraries. Refs: https://github.com/nodejs/undici/pull/986 --- lib/internal/url.js | 21 ++++++--------------- lib/internal/util.js | 18 ++++++++++++++++++ lib/util.js | 4 +++- test/parallel/test-util.js | 2 ++ 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/internal/url.js b/lib/internal/url.js index 0749e07d6e7677..9f2beab9ca20c4 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -19,7 +19,6 @@ const { ReflectApply, ReflectGetOwnPropertyDescriptor, ReflectOwnKeys, - RegExpPrototypeExec, String, StringPrototypeCharCodeAt, StringPrototypeIncludes, @@ -40,7 +39,12 @@ const { isHexTable } = require('internal/querystring'); -const { getConstructorOf, removeColors } = require('internal/util'); +const { + getConstructorOf, + removeColors, + toUSVString +} = require('internal/util'); + const { ERR_ARG_NOT_ITERABLE, ERR_INVALID_ARG_TYPE, @@ -79,7 +83,6 @@ const { domainToASCII: _domainToASCII, domainToUnicode: _domainToUnicode, encodeAuth, - toUSVString: _toUSVString, parse, setURLConstructor, URL_FLAGS_CANNOT_BE_BASE, @@ -113,18 +116,6 @@ const IteratorPrototype = ObjectGetPrototypeOf( ObjectGetPrototypeOf([][SymbolIterator]()) ); -const unpairedSurrogateRe = - /(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/; -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) - return str; - return _toUSVString(str, match.index); -} - // Refs: https://html.spec.whatwg.org/multipage/browsers.html#concept-origin-opaque const kOpaqueOrigin = 'null'; diff --git a/lib/internal/util.js b/lib/internal/util.js index 9158fc8e52431e..126ba41aa4f0d3 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -17,6 +17,7 @@ const { Promise, ReflectApply, ReflectConstruct, + RegExpPrototypeExec, RegExpPrototypeTest, SafeMap, SafeSet, @@ -27,6 +28,10 @@ const { SymbolFor, } = primordials; +const { + toUSVString: _toUSVString, +} = internalBinding('url'); + const { hideStackFrames, codes: { @@ -53,6 +58,18 @@ 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])/; +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) + return str; + return _toUSVString(str, match.index); +} + let uvBinding; function lazyUv() { @@ -487,6 +504,7 @@ module.exports = { sleep, spliceOne, structuredClone, + toUSVString, removeColors, // Symbol used to customize promisify conversion diff --git a/lib/util.js b/lib/util.js index a8d9a356480a35..7f1f1981ac1e01 100644 --- a/lib/util.js +++ b/lib/util.js @@ -72,7 +72,8 @@ const { deprecate, getSystemErrorMap, getSystemErrorName: internalErrorName, - promisify + promisify, + toUSVString } = require('internal/util'); let internalDeepEqual; @@ -368,6 +369,7 @@ module.exports = { isPrimitive, log, promisify, + toUSVString, TextDecoder, TextEncoder, types diff --git a/test/parallel/test-util.js b/test/parallel/test-util.js index 204b2bca5b9f3b..06b0347de1f36f 100644 --- a/test/parallel/test-util.js +++ b/test/parallel/test-util.js @@ -148,6 +148,8 @@ assert.strictEqual(util.isFunction(function() {}), true); assert.strictEqual(util.isFunction(), false); assert.strictEqual(util.isFunction('string'), false); +assert.strictEqual(util.toUSVString('string'), 'string'); + { assert.strictEqual(util.types.isNativeError(new Error()), true); assert.strictEqual(util.types.isNativeError(new TypeError()), true); From f2ca87d3fd5c987205b7c9219c6f35e91fce5eb4 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Fri, 20 Aug 2021 08:37:04 +0200 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: Antoine du Hamel --- lib/internal/url.js | 2 +- lib/util.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/url.js b/lib/internal/url.js index 9f2beab9ca20c4..a0fca22d135ef9 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -42,7 +42,7 @@ const { const { getConstructorOf, removeColors, - toUSVString + toUSVString, } = require('internal/util'); const { diff --git a/lib/util.js b/lib/util.js index 7f1f1981ac1e01..e3f151541ee2fb 100644 --- a/lib/util.js +++ b/lib/util.js @@ -73,7 +73,7 @@ const { getSystemErrorMap, getSystemErrorName: internalErrorName, promisify, - toUSVString + toUSVString, } = require('internal/util'); let internalDeepEqual; From 918491e39c78c5b38e524fcd729689678dbe4a3b Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Fri, 20 Aug 2021 08:58:43 +0200 Subject: [PATCH 3/4] fixup --- doc/api/util.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/api/util.md b/doc/api/util.md index 4cdba522744615..dc47704e0b74f7 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -2492,6 +2492,18 @@ const util = require('util'); util.log('Timestamped message.'); ``` + +### `util.toUSVString(string)` + + +* `string` {string} + +Returns the `string` after replacing any surrogate code points +(or equivalently, any unpaired surrogate code units) with the +Unicode "replacement character" U+FFFD. + [Common System Errors]: errors.md#errors_common_system_errors [Custom inspection functions on objects]: #util_custom_inspection_functions_on_objects [Custom promisified functions]: #util_custom_promisified_functions From 62c026f9cbec66528332a6a5200201b90e8cf352 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sat, 21 Aug 2021 14:15:30 +0200 Subject: [PATCH 4/4] fixup --- test/parallel/test-util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-util.js b/test/parallel/test-util.js index 06b0347de1f36f..42218be8581579 100644 --- a/test/parallel/test-util.js +++ b/test/parallel/test-util.js @@ -148,7 +148,7 @@ assert.strictEqual(util.isFunction(function() {}), true); assert.strictEqual(util.isFunction(), false); assert.strictEqual(util.isFunction('string'), false); -assert.strictEqual(util.toUSVString('string'), 'string'); +assert.strictEqual(util.toUSVString('string\ud801'), 'string\ufffd'); { assert.strictEqual(util.types.isNativeError(new Error()), true);