url: refactor to use more primordials
PR-URL: https://github.com/nodejs/node/pull/45966 Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
d15a6ba1b5
commit
e487638406
30
benchmark/url/whatwgurl-to-and-from-path.js
Normal file
30
benchmark/url/whatwgurl-to-and-from-path.js
Normal file
@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
const common = require('../common.js');
|
||||
const { fileURLToPath, pathToFileURL } = require('node:url');
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
const bench = common.createBenchmark(main, {
|
||||
input: isWindows ? [
|
||||
'file:///c/',
|
||||
] : [
|
||||
'file:///dev/null',
|
||||
'file:///dev/null?key=param&bool',
|
||||
'file:///dev/null?key=param&bool#hash',
|
||||
],
|
||||
method: isWindows ? [
|
||||
'fileURLToPath',
|
||||
] : [
|
||||
'fileURLToPath',
|
||||
'pathToFileURL',
|
||||
],
|
||||
n: [5e6],
|
||||
});
|
||||
|
||||
function main({ n, input, method }) {
|
||||
method = method === 'fileURLOrPath' ? fileURLToPath : pathToFileURL;
|
||||
bench.start();
|
||||
for (let i = 0; i < n; i++) {
|
||||
method(input);
|
||||
}
|
||||
bench.end(n);
|
||||
}
|
@ -61,6 +61,7 @@ const {
|
||||
Int32ArrayPrototype,
|
||||
Int8Array,
|
||||
Int8ArrayPrototype,
|
||||
IteratorPrototype,
|
||||
Map,
|
||||
MapPrototype,
|
||||
Number,
|
||||
@ -211,7 +212,7 @@ module.exports = function() {
|
||||
|
||||
// 27 Control Abstraction Objects
|
||||
// 27.1 Iteration
|
||||
ObjectGetPrototypeOf(ArrayIteratorPrototype), // 27.1.2 IteratorPrototype
|
||||
IteratorPrototype, // 27.1.2 IteratorPrototype
|
||||
// 27.1.3 AsyncIteratorPrototype
|
||||
ObjectGetPrototypeOf(ObjectGetPrototypeOf(ObjectGetPrototypeOf(
|
||||
(async function*() {})()
|
||||
|
@ -260,6 +260,8 @@ function copyPrototype(src, dest, prefix) {
|
||||
copyPrototype(original.prototype, primordials, `${name}Prototype`);
|
||||
});
|
||||
|
||||
primordials.IteratorPrototype = Reflect.getPrototypeOf(primordials.ArrayIteratorPrototype);
|
||||
|
||||
/* eslint-enable node-core/prefer-primordials */
|
||||
|
||||
const {
|
||||
|
@ -9,6 +9,7 @@ const {
|
||||
ArrayPrototypeSlice,
|
||||
FunctionPrototypeBind,
|
||||
Int8Array,
|
||||
IteratorPrototype,
|
||||
Number,
|
||||
ObjectDefineProperties,
|
||||
ObjectDefineProperty,
|
||||
@ -18,11 +19,13 @@ const {
|
||||
ReflectApply,
|
||||
ReflectGetOwnPropertyDescriptor,
|
||||
ReflectOwnKeys,
|
||||
RegExpPrototypeSymbolReplace,
|
||||
String,
|
||||
StringPrototypeCharAt,
|
||||
StringPrototypeCharCodeAt,
|
||||
StringPrototypeCodePointAt,
|
||||
StringPrototypeIncludes,
|
||||
StringPrototypeReplace,
|
||||
StringPrototypeReplaceAll,
|
||||
StringPrototypeIndexOf,
|
||||
StringPrototypeSlice,
|
||||
StringPrototypeSplit,
|
||||
StringPrototypeStartsWith,
|
||||
@ -44,6 +47,7 @@ const {
|
||||
removeColors,
|
||||
toUSVString,
|
||||
kEnumerableProperty,
|
||||
SideEffectFreeRegExpPrototypeSymbolReplace,
|
||||
} = require('internal/util');
|
||||
|
||||
const {
|
||||
@ -112,6 +116,8 @@ const {
|
||||
revokeDataObject,
|
||||
} = internalBinding('blob');
|
||||
|
||||
const FORWARD_SLASH = /\//g;
|
||||
|
||||
const context = Symbol('context');
|
||||
const cannotBeBase = Symbol('cannot-be-base');
|
||||
const cannotHaveUsernamePasswordPort =
|
||||
@ -138,11 +144,6 @@ function lazyCryptoRandom() {
|
||||
return cryptoRandom;
|
||||
}
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object
|
||||
const IteratorPrototype = ObjectGetPrototypeOf(
|
||||
ObjectGetPrototypeOf([][SymbolIterator]())
|
||||
);
|
||||
|
||||
// Refs: https://html.spec.whatwg.org/multipage/browsers.html#concept-origin-opaque
|
||||
const kOpaqueOrigin = 'null';
|
||||
|
||||
@ -1376,7 +1377,7 @@ defineIDLClass(URLSearchParamsIteratorPrototype, 'URLSearchParams Iterator', {
|
||||
},
|
||||
[]
|
||||
);
|
||||
const breakLn = inspect(output, innerOpts).includes('\n');
|
||||
const breakLn = StringPrototypeIncludes(inspect(output, innerOpts), '\n');
|
||||
const outputStrs = ArrayPrototypeMap(output, (p) => inspect(p, innerOpts));
|
||||
let outputStr;
|
||||
if (breakLn) {
|
||||
@ -1434,7 +1435,7 @@ function getPathFromURLWin32(url) {
|
||||
let pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === '%') {
|
||||
const third = pathname.codePointAt(n + 2) | 0x20;
|
||||
const third = StringPrototypeCodePointAt(pathname, n + 2) | 0x20;
|
||||
if ((pathname[n + 1] === '2' && third === 102) || // 2f 2F /
|
||||
(pathname[n + 1] === '5' && third === 99)) { // 5c 5C \
|
||||
throw new ERR_INVALID_FILE_URL_PATH(
|
||||
@ -1443,7 +1444,7 @@ function getPathFromURLWin32(url) {
|
||||
}
|
||||
}
|
||||
}
|
||||
pathname = StringPrototypeReplaceAll(pathname, '/', '\\');
|
||||
pathname = SideEffectFreeRegExpPrototypeSymbolReplace(FORWARD_SLASH, pathname, '\\');
|
||||
pathname = decodeURIComponent(pathname);
|
||||
if (hostname !== '') {
|
||||
// If hostname is set, then we have a UNC path
|
||||
@ -1455,13 +1456,13 @@ function getPathFromURLWin32(url) {
|
||||
return `\\\\${domainToUnicode(hostname)}${pathname}`;
|
||||
}
|
||||
// Otherwise, it's a local path that requires a drive letter
|
||||
const letter = pathname.codePointAt(1) | 0x20;
|
||||
const sep = pathname[2];
|
||||
const letter = StringPrototypeCodePointAt(pathname, 1) | 0x20;
|
||||
const sep = StringPrototypeCharAt(pathname, 2);
|
||||
if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z || // a..z A..Z
|
||||
(sep !== ':')) {
|
||||
throw new ERR_INVALID_FILE_URL_PATH('must be absolute');
|
||||
}
|
||||
return pathname.slice(1);
|
||||
return StringPrototypeSlice(pathname, 1);
|
||||
}
|
||||
|
||||
function getPathFromURLPosix(url) {
|
||||
@ -1471,7 +1472,7 @@ function getPathFromURLPosix(url) {
|
||||
const pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === '%') {
|
||||
const third = pathname.codePointAt(n + 2) | 0x20;
|
||||
const third = StringPrototypeCodePointAt(pathname, n + 2) | 0x20;
|
||||
if (pathname[n + 1] === '2' && third === 102) {
|
||||
throw new ERR_INVALID_FILE_URL_PATH(
|
||||
'must not include encoded / characters'
|
||||
@ -1511,16 +1512,16 @@ const tabRegEx = /\t/g;
|
||||
|
||||
function encodePathChars(filepath) {
|
||||
if (StringPrototypeIncludes(filepath, '%'))
|
||||
filepath = StringPrototypeReplace(filepath, percentRegEx, '%25');
|
||||
filepath = RegExpPrototypeSymbolReplace(percentRegEx, filepath, '%25');
|
||||
// In posix, backslash is a valid character in paths:
|
||||
if (!isWindows && StringPrototypeIncludes(filepath, '\\'))
|
||||
filepath = StringPrototypeReplace(filepath, backslashRegEx, '%5C');
|
||||
filepath = RegExpPrototypeSymbolReplace(backslashRegEx, filepath, '%5C');
|
||||
if (StringPrototypeIncludes(filepath, '\n'))
|
||||
filepath = StringPrototypeReplace(filepath, newlineRegEx, '%0A');
|
||||
filepath = RegExpPrototypeSymbolReplace(newlineRegEx, filepath, '%0A');
|
||||
if (StringPrototypeIncludes(filepath, '\r'))
|
||||
filepath = StringPrototypeReplace(filepath, carriageReturnRegEx, '%0D');
|
||||
filepath = RegExpPrototypeSymbolReplace(carriageReturnRegEx, filepath, '%0D');
|
||||
if (StringPrototypeIncludes(filepath, '\t'))
|
||||
filepath = StringPrototypeReplace(filepath, tabRegEx, '%09');
|
||||
filepath = RegExpPrototypeSymbolReplace(tabRegEx, filepath, '%09');
|
||||
return filepath;
|
||||
}
|
||||
|
||||
@ -1528,25 +1529,25 @@ function pathToFileURL(filepath) {
|
||||
const outURL = new URL('file://');
|
||||
if (isWindows && StringPrototypeStartsWith(filepath, '\\\\')) {
|
||||
// UNC path format: \\server\share\resource
|
||||
const paths = StringPrototypeSplit(filepath, '\\');
|
||||
if (paths.length <= 3) {
|
||||
const hostnameEndIndex = StringPrototypeIndexOf(filepath, '\\', 2);
|
||||
if (hostnameEndIndex === -1) {
|
||||
throw new ERR_INVALID_ARG_VALUE(
|
||||
'filepath',
|
||||
filepath,
|
||||
'Missing UNC resource path'
|
||||
);
|
||||
}
|
||||
const hostname = paths[2];
|
||||
if (hostname.length === 0) {
|
||||
if (hostnameEndIndex === 2) {
|
||||
throw new ERR_INVALID_ARG_VALUE(
|
||||
'filepath',
|
||||
filepath,
|
||||
'Empty UNC servername'
|
||||
);
|
||||
}
|
||||
const hostname = StringPrototypeSlice(filepath, 2, hostnameEndIndex);
|
||||
outURL.hostname = domainToASCII(hostname);
|
||||
outURL.pathname = encodePathChars(
|
||||
ArrayPrototypeJoin(ArrayPrototypeSlice(paths, 3), '/'));
|
||||
RegExpPrototypeSymbolReplace(backslashRegEx, StringPrototypeSlice(filepath, hostnameEndIndex), '/'));
|
||||
} else {
|
||||
let resolved = path.resolve(filepath);
|
||||
// path.resolve strips trailing slashes so we must add them back
|
||||
|
Loading…
x
Reference in New Issue
Block a user