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:
Antoine du Hamel 2023-01-22 14:13:24 +01:00 committed by GitHub
parent d15a6ba1b5
commit e487638406
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 25 deletions

View 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);
}

View File

@ -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*() {})()

View File

@ -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 {

View File

@ -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