Skip to content

Commit

Permalink
util: expose toUSVString
Browse files Browse the repository at this point in the history
Expose toUSVString so it can be used by user libraries.

PR-URL: #39814
Refs: nodejs/undici#986
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Luigi Pinca <[email protected]>
  • Loading branch information
ronag authored and targos committed Aug 22, 2021
1 parent 79079ea commit 6640037
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 16 deletions.
12 changes: 12 additions & 0 deletions doc/api/util.md
Original file line number Diff line number Diff line change
Expand Up @@ -2490,6 +2490,18 @@ const util = require('util');
util.log('Timestamped message.');
```


### `util.toUSVString(string)`
<!-- YAML
added: REPLACEME
-->

* `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
Expand Down
21 changes: 6 additions & 15 deletions lib/internal/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const {
ReflectApply,
ReflectGetOwnPropertyDescriptor,
ReflectOwnKeys,
RegExpPrototypeExec,
String,
StringPrototypeCharCodeAt,
StringPrototypeIncludes,
Expand All @@ -40,7 +39,12 @@ const {
isHexTable
} = require('internal/querystring');

const { getConstructorOf, removeColors } = require('internal/util');
const {
getConstructorOf,
removeColors,
toUSVString,
} = require('internal/util');

const {
codes: {
ERR_ARG_NOT_ITERABLE,
Expand Down Expand Up @@ -82,7 +86,6 @@ const {
domainToASCII: _domainToASCII,
domainToUnicode: _domainToUnicode,
encodeAuth,
toUSVString: _toUSVString,
parse,
setURLConstructor,
URL_FLAGS_CANNOT_BE_BASE,
Expand Down Expand Up @@ -139,18 +142,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';

Expand Down
18 changes: 18 additions & 0 deletions lib/internal/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const {
Promise,
ReflectApply,
ReflectConstruct,
RegExpPrototypeExec,
RegExpPrototypeTest,
SafeMap,
SafeSet,
Expand All @@ -27,6 +28,10 @@ const {
SymbolFor,
} = primordials;

const {
toUSVString: _toUSVString,
} = internalBinding('url');

const {
hideStackFrames,
codes: {
Expand All @@ -52,6 +57,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() {
Expand Down Expand Up @@ -497,6 +514,7 @@ module.exports = {
sleep,
spliceOne,
structuredClone,
toUSVString,
removeColors,

// Symbol used to customize promisify conversion
Expand Down
4 changes: 3 additions & 1 deletion lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ const {
deprecate,
getSystemErrorMap,
getSystemErrorName: internalErrorName,
promisify
promisify,
toUSVString,
} = require('internal/util');

let internalDeepEqual;
Expand Down Expand Up @@ -368,6 +369,7 @@ module.exports = {
isPrimitive,
log,
promisify,
toUSVString,
TextDecoder,
TextEncoder,
types
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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\ud801'), 'string\ufffd');

{
assert.strictEqual(util.types.isNativeError(new Error()), true);
assert.strictEqual(util.types.isNativeError(new TypeError()), true);
Expand Down

0 comments on commit 6640037

Please sign in to comment.