Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/fs.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);
Expand DownExpand Up@@ -722,6 +720,7 @@ function openAsBlob(path, options = kEmptyObject) {
// To give ourselves flexibility to maybe return the Blob asynchronously,
// this API returns a Promise.
path = getValidatedPath(path);
const { createBlobFromFilePath } = require('internal/blob');
return PromiseResolve(createBlobFromFilePath(path, { type }));
}

Expand Down
23 changes: 18 additions & 5 deletions lib/internal/bootstrap/switches/is_main_thread.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() {

// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/loader');
require('internal/modules/esm/utils');
if (isBuildingSnapshot()) {
// Preloaded so that they are part of the snapshot, where they cost nothing
// at startup. When bootstrapping WITHOUT a snapshot (worker threads,
// embedders that create their own isolate, --no-node-snapshot) they are
// loaded on first use instead: the ESM loader (with its translators,
// resolver and their dependencies) by run_main/import(), the public util
// and url modules by whoever requires them, data: URL and TypeScript
// support by the module loaders, internal/blob by fs.openAsBlob(), and the
// DNS helpers by node:dns or an explicit --dns-result-order (see
// pre_execution).
require('util');
require('url'); // eslint-disable-line no-restricted-modules
require('internal/modules/esm/loader');
require('internal/data_url');
require('internal/modules/typescript');
require('internal/blob');
require('internal/dns/utils');
}

// Needed to refresh the time origin.
require('internal/perf/utils');
Expand All@@ -311,8 +326,6 @@ internalBinding('wasm_web_api');
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/dns/utils.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,15 +214,15 @@ class ResolverBase {
}

let defaultResolver;
let dnsOrder;
// May already hold a value chosen by the snapshotted application; a
// --dns-result-order flag given at runtime overrides it in initializeDns().
let dnsOrder = 'verbatim';
const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first'];
const validFamilies = [0, 4, 6];

function initializeDns() {
const orderFromCLI = getOptionValue('--dns-result-order');
if (!orderFromCLI) {
dnsOrder ??= 'verbatim';
} else {
if (orderFromCLI) {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders);
dnsOrder = orderFromCLI;
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ const {
resolveWithHooks,
validateLoadStrict,
} = require('internal/modules/customization_hooks');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);
Expand DownExpand Up@@ -1888,7 +1888,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
Module.prototype._compile = function(content, filename, format) {
if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
this[kURL] ??= convertCJSFilenameToURL(filename);
content = stripTypeScriptModuleTypes(content, filename, this[kURL]);
content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
switch (format) {
case 'commonjs-typescript': {
format = 'commonjs';
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/modules/esm/load.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,9 +20,6 @@ const {
ERR_UNSUPPORTED_ESM_URL_SCHEME,
} = require('internal/errors').codes;

const {
dataURLProcessor,
} = require('internal/data_url');

/**
* @param {URL} url URL to the module
Expand All@@ -40,6 +37,7 @@ function getSourceSync(url, context) {
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
source = fs.readFileSync(url);
} else if (protocol === 'data:') {
const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs.
const result = dataURLProcessor(url);
if (result === 'failure') {
throw new ERR_INVALID_URL(responseURL);
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/modules/esm/translators.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,10 @@ const {
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, url) {
// Only needed for TypeScript sources; keep it out of the loader's startup path.
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url);
}
const {
kIsCachedByESMLoader,
Module: CJSModule,
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/process/execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,9 @@ const {
kSourcePhase,
kEvaluationPhase,
} = internalBinding('module_wrap');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, filename) {
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename);
}

const {
executionAsyncId,
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/process/pre_execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -139,7 +139,12 @@ function prepareExecution(options) {

initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
// internal/dns/utils (and internal/net behind it) is only needed up front
// to validate an explicit --dns-result-order or to register the resolver's
// snapshot serialization; otherwise it is loaded with node:dns.
if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) {
require('internal/dns/utils').initializeDns();
}

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down
10 changes: 7 additions & 3 deletions lib/internal/url.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,11 @@ const {
kValidateObjectAllowObjects,
} = require('internal/validators');

const { percentDecode } = require('internal/data_url');
let percentDecode;
function lazyPercentDecode(input) {
percentDecode ??= require('internal/data_url').percentDecode;
return percentDecode(input);
}

const querystring = require('querystring');

Expand DownExpand Up@@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) {
// percent encoded characters and we take the string as is. Any invalid
// percent encodings, e.g. `%ZZ` are ignored and are passed through
// literally.
const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8'));
const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8),
TypedArrayPrototypeGetByteOffset(decodedu8),
TypedArrayPrototypeGetByteLength(decodedu8));
Expand DownExpand Up@@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) {
// won't scan for the slashes at all, and instead will decode the bytes
// literally into the returned Buffer. We're going to do the best we can and
// just interpret the input url as a sequence of bytes.
const u8 = percentDecode(Buffer.from(pathname, 'utf8'));
const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
return Buffer.from(TypedArrayPrototypeGetBuffer(u8),
TypedArrayPrototypeGetByteOffset(u8),
TypedArrayPrototypeGetByteLength(u8));
Expand Down
7 changes: 2 additions & 5 deletions lib/internal/worker.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,6 @@ const {
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const {
internalEventLoopUtilization,
} = require('internal/perf/event_loop_utilization');

const errorCodes = require('internal/errors').codes;
const {
ERR_WORKER_NOT_RUNNING,
Expand All@@ -60,7 +56,6 @@ const {
WritableWorkerStdio,
} = workerIo;
const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging');
const { deserializeError } = require('internal/error_serdes');
const { fileURLToPath, isURL, pathToFileURL } = require('internal/url');
const {
constructSharedArrayBuffer,
Expand DownExpand Up@@ -417,6 +412,7 @@ class Worker extends EventEmitter {

[kOnErrorMessage](serialized) {
// This is what is called for uncaught exceptions.
const { deserializeError } = require('internal/error_serdes');
const error = deserializeError(serialized);
this.emit('error', error);
}
Expand DownExpand Up@@ -699,6 +695,7 @@ function makeResourceLimits(float64arr) {
}

function eventLoopUtilization(util1, util2) {
const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization');
// TODO(trevnorris): Works to solve the thread-safe read/write issue of
// loopTime, but has the drawback that it can't be set until the event loop
// has had a chance to turn. So it will be impossible to read the ELU of
Expand Down
12 changes: 9 additions & 3 deletions lib/worker_threads.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
'use strict';

const { defineLazyProperties } = require('internal/util');

const {
isInternalThread,
isMainThread,
Expand DownExpand Up@@ -30,8 +32,6 @@ const {
isMarkedAsUntransferable,
} = require('internal/buffer');

const { locks } = require('internal/locks');

module.exports = {
isInternalThread,
isMainThread,
Expand All@@ -53,5 +53,11 @@ module.exports = {
BroadcastChannel,
setEnvironmentData,
getEnvironmentData,
locks,
};

// The Web Locks API implementation is only needed once `locks` is used.
defineLazyProperties(
module.exports,
'internal/locks',
['locks'],
);
37 changes: 21 additions & 16 deletions test/parallel/test-bootstrap-modules.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,10 +20,10 @@ const actual = {
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};
const getFormatNativeModule = 'NativeModule internal/modules/esm/get_format';

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
'Internal Binding errors',
'Internal Binding util',
Expand DownExpand Up@@ -88,10 +88,6 @@ expected.beforePreExec = new Set([
'NativeModule internal/v8/startup_snapshot',
'NativeModule internal/process/signal',
'Internal Binding fs',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/blob',
'NativeModule internal/fs/utils',
'NativeModule fs',
'Internal Binding options',
Expand All@@ -109,15 +105,10 @@ expected.beforePreExec = new Set([
'Internal Binding diagnostics_channel',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
'NativeModule internal/modules/typescript',
'NativeModule internal/data_url',
'NativeModule internal/mime',
'NativeModule internal/modules/esm/utils',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/modules/esm/get_format',
getFormatNativeModule,
'NativeModule internal/trace_events',
]);

Expand All@@ -126,8 +117,13 @@ expected.atRunTime = new Set([
]);

const { isMainThread } = require('worker_threads');
// Binaries built without the snapshot (e.g. cross-compiled) and
// --no-node-snapshot bootstrap the main context from scratch, like a worker.
const mainContextFromSnapshot = isMainThread &&
process.config.variables.node_use_node_snapshot &&
!process.execArgv.includes('--no-node-snapshot');

if (isMainThread) {
if (mainContextFromSnapshot) {
[
'Internal Binding cjs_lexer',
'NativeModule internal/modules/esm/assert',
Expand All@@ -138,15 +134,24 @@ if (isMainThread) {
'NativeModule internal/modules/esm/module_job',
'NativeModule internal/modules/esm/module_map',
'NativeModule url',
'Internal Binding encoding_binding',
'NativeModule internal/blob',
'NativeModule internal/data_url',
'NativeModule internal/dns/utils',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/mime',
'NativeModule internal/modules/typescript',
'NativeModule internal/net',
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else if (isMainThread) {
expected.beforePreExec.delete(getFormatNativeModule);
expected.atRunTime.add(getFormatNativeModule);
} else { // Worker.
[
'Internal Binding locks',
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
'NativeModule internal/error_serdes',
'NativeModule internal/locks',
'NativeModule internal/perf/event_loop_utilization',
'NativeModule internal/process/worker_thread_only',
'NativeModule internal/streams/add-abort-signal',
'NativeModule internal/streams/compose',
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/fs.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);
Expand DownExpand Up@@ -722,6 +720,7 @@ function openAsBlob(path, options = kEmptyObject) {
// To give ourselves flexibility to maybe return the Blob asynchronously,
// this API returns a Promise.
path = getValidatedPath(path);
const { createBlobFromFilePath } = require('internal/blob');
return PromiseResolve(createBlobFromFilePath(path, { type }));
}

Expand Down
23 changes: 18 additions & 5 deletions lib/internal/bootstrap/switches/is_main_thread.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() {

// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/loader');
require('internal/modules/esm/utils');
if (isBuildingSnapshot()) {
// Preloaded so that they are part of the snapshot, where they cost nothing
// at startup. When bootstrapping WITHOUT a snapshot (worker threads,
// embedders that create their own isolate, --no-node-snapshot) they are
// loaded on first use instead: the ESM loader (with its translators,
// resolver and their dependencies) by run_main/import(), the public util
// and url modules by whoever requires them, data: URL and TypeScript
// support by the module loaders, internal/blob by fs.openAsBlob(), and the
// DNS helpers by node:dns or an explicit --dns-result-order (see
// pre_execution).
require('util');
require('url'); // eslint-disable-line no-restricted-modules
require('internal/modules/esm/loader');
require('internal/data_url');
require('internal/modules/typescript');
require('internal/blob');
require('internal/dns/utils');
}

// Needed to refresh the time origin.
require('internal/perf/utils');
Expand All@@ -311,8 +326,6 @@ internalBinding('wasm_web_api');
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/dns/utils.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,15 +214,15 @@ class ResolverBase {
}

let defaultResolver;
let dnsOrder;
// May already hold a value chosen by the snapshotted application; a
// --dns-result-order flag given at runtime overrides it in initializeDns().
let dnsOrder = 'verbatim';
const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first'];
const validFamilies = [0, 4, 6];

function initializeDns() {
const orderFromCLI = getOptionValue('--dns-result-order');
if (!orderFromCLI) {
dnsOrder ??= 'verbatim';
} else {
if (orderFromCLI) {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders);
dnsOrder = orderFromCLI;
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ const {
resolveWithHooks,
validateLoadStrict,
} = require('internal/modules/customization_hooks');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);
Expand DownExpand Up@@ -1888,7 +1888,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
Module.prototype._compile = function(content, filename, format) {
if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
this[kURL] ??= convertCJSFilenameToURL(filename);
content = stripTypeScriptModuleTypes(content, filename, this[kURL]);
content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
switch (format) {
case 'commonjs-typescript': {
format = 'commonjs';
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/modules/esm/load.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,9 +20,6 @@ const {
ERR_UNSUPPORTED_ESM_URL_SCHEME,
} = require('internal/errors').codes;

const {
dataURLProcessor,
} = require('internal/data_url');

/**
* @param {URL} url URL to the module
Expand All@@ -40,6 +37,7 @@ function getSourceSync(url, context) {
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
source = fs.readFileSync(url);
} else if (protocol === 'data:') {
const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs.
const result = dataURLProcessor(url);
if (result === 'failure') {
throw new ERR_INVALID_URL(responseURL);
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/modules/esm/translators.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,10 @@ const {
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, url) {
// Only needed for TypeScript sources; keep it out of the loader's startup path.
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url);
}
const {
kIsCachedByESMLoader,
Module: CJSModule,
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/process/execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,9 @@ const {
kSourcePhase,
kEvaluationPhase,
} = internalBinding('module_wrap');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, filename) {
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename);
}

const {
executionAsyncId,
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/process/pre_execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -139,7 +139,12 @@ function prepareExecution(options) {

initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
// internal/dns/utils (and internal/net behind it) is only needed up front
// to validate an explicit --dns-result-order or to register the resolver's
// snapshot serialization; otherwise it is loaded with node:dns.
if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) {
require('internal/dns/utils').initializeDns();
}

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down
10 changes: 7 additions & 3 deletions lib/internal/url.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,11 @@ const {
kValidateObjectAllowObjects,
} = require('internal/validators');

const { percentDecode } = require('internal/data_url');
let percentDecode;
function lazyPercentDecode(input) {
percentDecode ??= require('internal/data_url').percentDecode;
return percentDecode(input);
}

const querystring = require('querystring');

Expand DownExpand Up@@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) {
// percent encoded characters and we take the string as is. Any invalid
// percent encodings, e.g. `%ZZ` are ignored and are passed through
// literally.
const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8'));
const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8),
TypedArrayPrototypeGetByteOffset(decodedu8),
TypedArrayPrototypeGetByteLength(decodedu8));
Expand DownExpand Up@@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) {
// won't scan for the slashes at all, and instead will decode the bytes
// literally into the returned Buffer. We're going to do the best we can and
// just interpret the input url as a sequence of bytes.
const u8 = percentDecode(Buffer.from(pathname, 'utf8'));
const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
return Buffer.from(TypedArrayPrototypeGetBuffer(u8),
TypedArrayPrototypeGetByteOffset(u8),
TypedArrayPrototypeGetByteLength(u8));
Expand Down
7 changes: 2 additions & 5 deletions lib/internal/worker.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,6 @@ const {
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const {
internalEventLoopUtilization,
} = require('internal/perf/event_loop_utilization');

const errorCodes = require('internal/errors').codes;
const {
ERR_WORKER_NOT_RUNNING,
Expand All@@ -60,7 +56,6 @@ const {
WritableWorkerStdio,
} = workerIo;
const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging');
const { deserializeError } = require('internal/error_serdes');
const { fileURLToPath, isURL, pathToFileURL } = require('internal/url');
const {
constructSharedArrayBuffer,
Expand DownExpand Up@@ -417,6 +412,7 @@ class Worker extends EventEmitter {

[kOnErrorMessage](serialized) {
// This is what is called for uncaught exceptions.
const { deserializeError } = require('internal/error_serdes');
const error = deserializeError(serialized);
this.emit('error', error);
}
Expand DownExpand Up@@ -699,6 +695,7 @@ function makeResourceLimits(float64arr) {
}

function eventLoopUtilization(util1, util2) {
const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization');
// TODO(trevnorris): Works to solve the thread-safe read/write issue of
// loopTime, but has the drawback that it can't be set until the event loop
// has had a chance to turn. So it will be impossible to read the ELU of
Expand Down
12 changes: 9 additions & 3 deletions lib/worker_threads.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
'use strict';

const { defineLazyProperties } = require('internal/util');

const {
isInternalThread,
isMainThread,
Expand DownExpand Up@@ -30,8 +32,6 @@ const {
isMarkedAsUntransferable,
} = require('internal/buffer');

const { locks } = require('internal/locks');

module.exports = {
isInternalThread,
isMainThread,
Expand All@@ -53,5 +53,11 @@ module.exports = {
BroadcastChannel,
setEnvironmentData,
getEnvironmentData,
locks,
};

// The Web Locks API implementation is only needed once `locks` is used.
defineLazyProperties(
module.exports,
'internal/locks',
['locks'],
);
37 changes: 21 additions & 16 deletions test/parallel/test-bootstrap-modules.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,10 +20,10 @@ const actual = {
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};
const getFormatNativeModule = 'NativeModule internal/modules/esm/get_format';

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
'Internal Binding errors',
'Internal Binding util',
Expand DownExpand Up@@ -88,10 +88,6 @@ expected.beforePreExec = new Set([
'NativeModule internal/v8/startup_snapshot',
'NativeModule internal/process/signal',
'Internal Binding fs',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/blob',
'NativeModule internal/fs/utils',
'NativeModule fs',
'Internal Binding options',
Expand All@@ -109,15 +105,10 @@ expected.beforePreExec = new Set([
'Internal Binding diagnostics_channel',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
'NativeModule internal/modules/typescript',
'NativeModule internal/data_url',
'NativeModule internal/mime',
'NativeModule internal/modules/esm/utils',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/modules/esm/get_format',
getFormatNativeModule,
'NativeModule internal/trace_events',
]);

Expand All@@ -126,8 +117,13 @@ expected.atRunTime = new Set([
]);

const { isMainThread } = require('worker_threads');
// Binaries built without the snapshot (e.g. cross-compiled) and
// --no-node-snapshot bootstrap the main context from scratch, like a worker.
const mainContextFromSnapshot = isMainThread &&
process.config.variables.node_use_node_snapshot &&
!process.execArgv.includes('--no-node-snapshot');

if (isMainThread) {
if (mainContextFromSnapshot) {
[
'Internal Binding cjs_lexer',
'NativeModule internal/modules/esm/assert',
Expand All@@ -138,15 +134,24 @@ if (isMainThread) {
'NativeModule internal/modules/esm/module_job',
'NativeModule internal/modules/esm/module_map',
'NativeModule url',
'Internal Binding encoding_binding',
'NativeModule internal/blob',
'NativeModule internal/data_url',
'NativeModule internal/dns/utils',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/mime',
'NativeModule internal/modules/typescript',
'NativeModule internal/net',
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else if (isMainThread) {
expected.beforePreExec.delete(getFormatNativeModule);
expected.atRunTime.add(getFormatNativeModule);
} else { // Worker.
[
'Internal Binding locks',
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
'NativeModule internal/error_serdes',
'NativeModule internal/locks',
'NativeModule internal/perf/event_loop_utilization',
'NativeModule internal/process/worker_thread_only',
'NativeModule internal/streams/add-abort-signal',
'NativeModule internal/streams/compose',
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/fs.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);
Expand DownExpand Up@@ -722,6 +720,7 @@ function openAsBlob(path, options = kEmptyObject) {
// To give ourselves flexibility to maybe return the Blob asynchronously,
// this API returns a Promise.
path = getValidatedPath(path);
const { createBlobFromFilePath } = require('internal/blob');
return PromiseResolve(createBlobFromFilePath(path, { type }));
}

Expand Down
23 changes: 18 additions & 5 deletions lib/internal/bootstrap/switches/is_main_thread.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() {

// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/loader');
require('internal/modules/esm/utils');
if (isBuildingSnapshot()) {
// Preloaded so that they are part of the snapshot, where they cost nothing
// at startup. When bootstrapping WITHOUT a snapshot (worker threads,
// embedders that create their own isolate, --no-node-snapshot) they are
// loaded on first use instead: the ESM loader (with its translators,
// resolver and their dependencies) by run_main/import(), the public util
// and url modules by whoever requires them, data: URL and TypeScript
// support by the module loaders, internal/blob by fs.openAsBlob(), and the
// DNS helpers by node:dns or an explicit --dns-result-order (see
// pre_execution).
require('util');
require('url'); // eslint-disable-line no-restricted-modules
require('internal/modules/esm/loader');
require('internal/data_url');
require('internal/modules/typescript');
require('internal/blob');
require('internal/dns/utils');
}

// Needed to refresh the time origin.
require('internal/perf/utils');
Expand All@@ -311,8 +326,6 @@ internalBinding('wasm_web_api');
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/dns/utils.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,15 +214,15 @@ class ResolverBase {
}

let defaultResolver;
let dnsOrder;
// May already hold a value chosen by the snapshotted application; a
// --dns-result-order flag given at runtime overrides it in initializeDns().
let dnsOrder = 'verbatim';
const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first'];
const validFamilies = [0, 4, 6];

function initializeDns() {
const orderFromCLI = getOptionValue('--dns-result-order');
if (!orderFromCLI) {
dnsOrder ??= 'verbatim';
} else {
if (orderFromCLI) {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders);
dnsOrder = orderFromCLI;
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ const {
resolveWithHooks,
validateLoadStrict,
} = require('internal/modules/customization_hooks');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);
Expand DownExpand Up@@ -1888,7 +1888,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
Module.prototype._compile = function(content, filename, format) {
if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
this[kURL] ??= convertCJSFilenameToURL(filename);
content = stripTypeScriptModuleTypes(content, filename, this[kURL]);
content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
switch (format) {
case 'commonjs-typescript': {
format = 'commonjs';
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/modules/esm/load.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,9 +20,6 @@ const {
ERR_UNSUPPORTED_ESM_URL_SCHEME,
} = require('internal/errors').codes;

const {
dataURLProcessor,
} = require('internal/data_url');

/**
* @param {URL} url URL to the module
Expand All@@ -40,6 +37,7 @@ function getSourceSync(url, context) {
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
source = fs.readFileSync(url);
} else if (protocol === 'data:') {
const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs.
const result = dataURLProcessor(url);
if (result === 'failure') {
throw new ERR_INVALID_URL(responseURL);
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/modules/esm/translators.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,10 @@ const {
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, url) {
// Only needed for TypeScript sources; keep it out of the loader's startup path.
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url);
}
const {
kIsCachedByESMLoader,
Module: CJSModule,
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/process/execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,9 @@ const {
kSourcePhase,
kEvaluationPhase,
} = internalBinding('module_wrap');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, filename) {
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename);
}

const {
executionAsyncId,
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/process/pre_execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -139,7 +139,12 @@ function prepareExecution(options) {

initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
// internal/dns/utils (and internal/net behind it) is only needed up front
// to validate an explicit --dns-result-order or to register the resolver's
// snapshot serialization; otherwise it is loaded with node:dns.
if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) {
require('internal/dns/utils').initializeDns();
}

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down
10 changes: 7 additions & 3 deletions lib/internal/url.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,11 @@ const {
kValidateObjectAllowObjects,
} = require('internal/validators');

const { percentDecode } = require('internal/data_url');
let percentDecode;
function lazyPercentDecode(input) {
percentDecode ??= require('internal/data_url').percentDecode;
return percentDecode(input);
}

const querystring = require('querystring');

Expand DownExpand Up@@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) {
// percent encoded characters and we take the string as is. Any invalid
// percent encodings, e.g. `%ZZ` are ignored and are passed through
// literally.
const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8'));
const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8),
TypedArrayPrototypeGetByteOffset(decodedu8),
TypedArrayPrototypeGetByteLength(decodedu8));
Expand DownExpand Up@@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) {
// won't scan for the slashes at all, and instead will decode the bytes
// literally into the returned Buffer. We're going to do the best we can and
// just interpret the input url as a sequence of bytes.
const u8 = percentDecode(Buffer.from(pathname, 'utf8'));
const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
return Buffer.from(TypedArrayPrototypeGetBuffer(u8),
TypedArrayPrototypeGetByteOffset(u8),
TypedArrayPrototypeGetByteLength(u8));
Expand Down
7 changes: 2 additions & 5 deletions lib/internal/worker.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,6 @@ const {
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const {
internalEventLoopUtilization,
} = require('internal/perf/event_loop_utilization');

const errorCodes = require('internal/errors').codes;
const {
ERR_WORKER_NOT_RUNNING,
Expand All@@ -60,7 +56,6 @@ const {
WritableWorkerStdio,
} = workerIo;
const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging');
const { deserializeError } = require('internal/error_serdes');
const { fileURLToPath, isURL, pathToFileURL } = require('internal/url');
const {
constructSharedArrayBuffer,
Expand DownExpand Up@@ -417,6 +412,7 @@ class Worker extends EventEmitter {

[kOnErrorMessage](serialized) {
// This is what is called for uncaught exceptions.
const { deserializeError } = require('internal/error_serdes');
const error = deserializeError(serialized);
this.emit('error', error);
}
Expand DownExpand Up@@ -699,6 +695,7 @@ function makeResourceLimits(float64arr) {
}

function eventLoopUtilization(util1, util2) {
const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization');
// TODO(trevnorris): Works to solve the thread-safe read/write issue of
// loopTime, but has the drawback that it can't be set until the event loop
// has had a chance to turn. So it will be impossible to read the ELU of
Expand Down
12 changes: 9 additions & 3 deletions lib/worker_threads.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
'use strict';

const { defineLazyProperties } = require('internal/util');

const {
isInternalThread,
isMainThread,
Expand DownExpand Up@@ -30,8 +32,6 @@ const {
isMarkedAsUntransferable,
} = require('internal/buffer');

const { locks } = require('internal/locks');

module.exports = {
isInternalThread,
isMainThread,
Expand All@@ -53,5 +53,11 @@ module.exports = {
BroadcastChannel,
setEnvironmentData,
getEnvironmentData,
locks,
};

// The Web Locks API implementation is only needed once `locks` is used.
defineLazyProperties(
module.exports,
'internal/locks',
['locks'],
);
37 changes: 21 additions & 16 deletions test/parallel/test-bootstrap-modules.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,10 +20,10 @@ const actual = {
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};
const getFormatNativeModule = 'NativeModule internal/modules/esm/get_format';

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
'Internal Binding errors',
'Internal Binding util',
Expand DownExpand Up@@ -88,10 +88,6 @@ expected.beforePreExec = new Set([
'NativeModule internal/v8/startup_snapshot',
'NativeModule internal/process/signal',
'Internal Binding fs',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/blob',
'NativeModule internal/fs/utils',
'NativeModule fs',
'Internal Binding options',
Expand All@@ -109,15 +105,10 @@ expected.beforePreExec = new Set([
'Internal Binding diagnostics_channel',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
'NativeModule internal/modules/typescript',
'NativeModule internal/data_url',
'NativeModule internal/mime',
'NativeModule internal/modules/esm/utils',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/modules/esm/get_format',
getFormatNativeModule,
'NativeModule internal/trace_events',
]);

Expand All@@ -126,8 +117,13 @@ expected.atRunTime = new Set([
]);

const { isMainThread } = require('worker_threads');
// Binaries built without the snapshot (e.g. cross-compiled) and
// --no-node-snapshot bootstrap the main context from scratch, like a worker.
const mainContextFromSnapshot = isMainThread &&
process.config.variables.node_use_node_snapshot &&
!process.execArgv.includes('--no-node-snapshot');

if (isMainThread) {
if (mainContextFromSnapshot) {
[
'Internal Binding cjs_lexer',
'NativeModule internal/modules/esm/assert',
Expand All@@ -138,15 +134,24 @@ if (isMainThread) {
'NativeModule internal/modules/esm/module_job',
'NativeModule internal/modules/esm/module_map',
'NativeModule url',
'Internal Binding encoding_binding',
'NativeModule internal/blob',
'NativeModule internal/data_url',
'NativeModule internal/dns/utils',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/mime',
'NativeModule internal/modules/typescript',
'NativeModule internal/net',
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else if (isMainThread) {
expected.beforePreExec.delete(getFormatNativeModule);
expected.atRunTime.add(getFormatNativeModule);
} else { // Worker.
[
'Internal Binding locks',
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
'NativeModule internal/error_serdes',
'NativeModule internal/locks',
'NativeModule internal/perf/event_loop_utilization',
'NativeModule internal/process/worker_thread_only',
'NativeModule internal/streams/add-abort-signal',
'NativeModule internal/streams/compose',
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/fs.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);
Expand DownExpand Up@@ -722,6 +720,7 @@ function openAsBlob(path, options = kEmptyObject) {
// To give ourselves flexibility to maybe return the Blob asynchronously,
// this API returns a Promise.
path = getValidatedPath(path);
const { createBlobFromFilePath } = require('internal/blob');
return PromiseResolve(createBlobFromFilePath(path, { type }));
}

Expand Down
23 changes: 18 additions & 5 deletions lib/internal/bootstrap/switches/is_main_thread.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() {

// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/loader');
require('internal/modules/esm/utils');
if (isBuildingSnapshot()) {
// Preloaded so that they are part of the snapshot, where they cost nothing
// at startup. When bootstrapping WITHOUT a snapshot (worker threads,
// embedders that create their own isolate, --no-node-snapshot) they are
// loaded on first use instead: the ESM loader (with its translators,
// resolver and their dependencies) by run_main/import(), the public util
// and url modules by whoever requires them, data: URL and TypeScript
// support by the module loaders, internal/blob by fs.openAsBlob(), and the
// DNS helpers by node:dns or an explicit --dns-result-order (see
// pre_execution).
require('util');
require('url'); // eslint-disable-line no-restricted-modules
require('internal/modules/esm/loader');
require('internal/data_url');
require('internal/modules/typescript');
require('internal/blob');
require('internal/dns/utils');
}

// Needed to refresh the time origin.
require('internal/perf/utils');
Expand All@@ -311,8 +326,6 @@ internalBinding('wasm_web_api');
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/dns/utils.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,15 +214,15 @@ class ResolverBase {
}

let defaultResolver;
let dnsOrder;
// May already hold a value chosen by the snapshotted application; a
// --dns-result-order flag given at runtime overrides it in initializeDns().
let dnsOrder = 'verbatim';
const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first'];
const validFamilies = [0, 4, 6];

function initializeDns() {
const orderFromCLI = getOptionValue('--dns-result-order');
if (!orderFromCLI) {
dnsOrder ??= 'verbatim';
} else {
if (orderFromCLI) {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders);
dnsOrder = orderFromCLI;
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ const {
resolveWithHooks,
validateLoadStrict,
} = require('internal/modules/customization_hooks');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);
Expand DownExpand Up@@ -1888,7 +1888,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
Module.prototype._compile = function(content, filename, format) {
if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
this[kURL] ??= convertCJSFilenameToURL(filename);
content = stripTypeScriptModuleTypes(content, filename, this[kURL]);
content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
switch (format) {
case 'commonjs-typescript': {
format = 'commonjs';
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/modules/esm/load.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,9 +20,6 @@ const {
ERR_UNSUPPORTED_ESM_URL_SCHEME,
} = require('internal/errors').codes;

const {
dataURLProcessor,
} = require('internal/data_url');

/**
* @param {URL} url URL to the module
Expand All@@ -40,6 +37,7 @@ function getSourceSync(url, context) {
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
source = fs.readFileSync(url);
} else if (protocol === 'data:') {
const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs.
const result = dataURLProcessor(url);
if (result === 'failure') {
throw new ERR_INVALID_URL(responseURL);
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/modules/esm/translators.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,10 @@ const {
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, url) {
// Only needed for TypeScript sources; keep it out of the loader's startup path.
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url);
}
const {
kIsCachedByESMLoader,
Module: CJSModule,
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/process/execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,9 @@ const {
kSourcePhase,
kEvaluationPhase,
} = internalBinding('module_wrap');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, filename) {
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename);
}

const {
executionAsyncId,
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/process/pre_execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -139,7 +139,12 @@ function prepareExecution(options) {

initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
// internal/dns/utils (and internal/net behind it) is only needed up front
// to validate an explicit --dns-result-order or to register the resolver's
// snapshot serialization; otherwise it is loaded with node:dns.
if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) {
require('internal/dns/utils').initializeDns();
}

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down
10 changes: 7 additions & 3 deletions lib/internal/url.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,11 @@ const {
kValidateObjectAllowObjects,
} = require('internal/validators');

const { percentDecode } = require('internal/data_url');
let percentDecode;
function lazyPercentDecode(input) {
percentDecode ??= require('internal/data_url').percentDecode;
return percentDecode(input);
}

const querystring = require('querystring');

Expand DownExpand Up@@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) {
// percent encoded characters and we take the string as is. Any invalid
// percent encodings, e.g. `%ZZ` are ignored and are passed through
// literally.
const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8'));
const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8),
TypedArrayPrototypeGetByteOffset(decodedu8),
TypedArrayPrototypeGetByteLength(decodedu8));
Expand DownExpand Up@@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) {
// won't scan for the slashes at all, and instead will decode the bytes
// literally into the returned Buffer. We're going to do the best we can and
// just interpret the input url as a sequence of bytes.
const u8 = percentDecode(Buffer.from(pathname, 'utf8'));
const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
return Buffer.from(TypedArrayPrototypeGetBuffer(u8),
TypedArrayPrototypeGetByteOffset(u8),
TypedArrayPrototypeGetByteLength(u8));
Expand Down
7 changes: 2 additions & 5 deletions lib/internal/worker.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,6 @@ const {
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const {
internalEventLoopUtilization,
} = require('internal/perf/event_loop_utilization');

const errorCodes = require('internal/errors').codes;
const {
ERR_WORKER_NOT_RUNNING,
Expand All@@ -60,7 +56,6 @@ const {
WritableWorkerStdio,
} = workerIo;
const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging');
const { deserializeError } = require('internal/error_serdes');
const { fileURLToPath, isURL, pathToFileURL } = require('internal/url');
const {
constructSharedArrayBuffer,
Expand DownExpand Up@@ -417,6 +412,7 @@ class Worker extends EventEmitter {

[kOnErrorMessage](serialized) {
// This is what is called for uncaught exceptions.
const { deserializeError } = require('internal/error_serdes');
const error = deserializeError(serialized);
this.emit('error', error);
}
Expand DownExpand Up@@ -699,6 +695,7 @@ function makeResourceLimits(float64arr) {
}

function eventLoopUtilization(util1, util2) {
const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization');
// TODO(trevnorris): Works to solve the thread-safe read/write issue of
// loopTime, but has the drawback that it can't be set until the event loop
// has had a chance to turn. So it will be impossible to read the ELU of
Expand Down
12 changes: 9 additions & 3 deletions lib/worker_threads.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
'use strict';

const { defineLazyProperties } = require('internal/util');

const {
isInternalThread,
isMainThread,
Expand DownExpand Up@@ -30,8 +32,6 @@ const {
isMarkedAsUntransferable,
} = require('internal/buffer');

const { locks } = require('internal/locks');

module.exports = {
isInternalThread,
isMainThread,
Expand All@@ -53,5 +53,11 @@ module.exports = {
BroadcastChannel,
setEnvironmentData,
getEnvironmentData,
locks,
};

// The Web Locks API implementation is only needed once `locks` is used.
defineLazyProperties(
module.exports,
'internal/locks',
['locks'],
);
37 changes: 21 additions & 16 deletions test/parallel/test-bootstrap-modules.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,10 +20,10 @@ const actual = {
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};
const getFormatNativeModule = 'NativeModule internal/modules/esm/get_format';

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
'Internal Binding errors',
'Internal Binding util',
Expand DownExpand Up@@ -88,10 +88,6 @@ expected.beforePreExec = new Set([
'NativeModule internal/v8/startup_snapshot',
'NativeModule internal/process/signal',
'Internal Binding fs',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/blob',
'NativeModule internal/fs/utils',
'NativeModule fs',
'Internal Binding options',
Expand All@@ -109,15 +105,10 @@ expected.beforePreExec = new Set([
'Internal Binding diagnostics_channel',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
'NativeModule internal/modules/typescript',
'NativeModule internal/data_url',
'NativeModule internal/mime',
'NativeModule internal/modules/esm/utils',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/modules/esm/get_format',
getFormatNativeModule,
'NativeModule internal/trace_events',
]);

Expand All@@ -126,8 +117,13 @@ expected.atRunTime = new Set([
]);

const { isMainThread } = require('worker_threads');
// Binaries built without the snapshot (e.g. cross-compiled) and
// --no-node-snapshot bootstrap the main context from scratch, like a worker.
const mainContextFromSnapshot = isMainThread &&
process.config.variables.node_use_node_snapshot &&
!process.execArgv.includes('--no-node-snapshot');

if (isMainThread) {
if (mainContextFromSnapshot) {
[
'Internal Binding cjs_lexer',
'NativeModule internal/modules/esm/assert',
Expand All@@ -138,15 +134,24 @@ if (isMainThread) {
'NativeModule internal/modules/esm/module_job',
'NativeModule internal/modules/esm/module_map',
'NativeModule url',
'Internal Binding encoding_binding',
'NativeModule internal/blob',
'NativeModule internal/data_url',
'NativeModule internal/dns/utils',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/mime',
'NativeModule internal/modules/typescript',
'NativeModule internal/net',
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else if (isMainThread) {
expected.beforePreExec.delete(getFormatNativeModule);
expected.atRunTime.add(getFormatNativeModule);
} else { // Worker.
[
'Internal Binding locks',
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
'NativeModule internal/error_serdes',
'NativeModule internal/locks',
'NativeModule internal/perf/event_loop_utilization',
'NativeModule internal/process/worker_thread_only',
'NativeModule internal/streams/add-abort-signal',
'NativeModule internal/streams/compose',
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/fs.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);
Expand DownExpand Up@@ -722,6 +720,7 @@ function openAsBlob(path, options = kEmptyObject) {
// To give ourselves flexibility to maybe return the Blob asynchronously,
// this API returns a Promise.
path = getValidatedPath(path);
const { createBlobFromFilePath } = require('internal/blob');
return PromiseResolve(createBlobFromFilePath(path, { type }));
}

Expand Down
23 changes: 18 additions & 5 deletions lib/internal/bootstrap/switches/is_main_thread.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() {

// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/loader');
require('internal/modules/esm/utils');
if (isBuildingSnapshot()) {
// Preloaded so that they are part of the snapshot, where they cost nothing
// at startup. When bootstrapping WITHOUT a snapshot (worker threads,
// embedders that create their own isolate, --no-node-snapshot) they are
// loaded on first use instead: the ESM loader (with its translators,
// resolver and their dependencies) by run_main/import(), the public util
// and url modules by whoever requires them, data: URL and TypeScript
// support by the module loaders, internal/blob by fs.openAsBlob(), and the
// DNS helpers by node:dns or an explicit --dns-result-order (see
// pre_execution).
require('util');
require('url'); // eslint-disable-line no-restricted-modules
require('internal/modules/esm/loader');
require('internal/data_url');
require('internal/modules/typescript');
require('internal/blob');
require('internal/dns/utils');
}

// Needed to refresh the time origin.
require('internal/perf/utils');
Expand All@@ -311,8 +326,6 @@ internalBinding('wasm_web_api');
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/dns/utils.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,15 +214,15 @@ class ResolverBase {
}

let defaultResolver;
let dnsOrder;
// May already hold a value chosen by the snapshotted application; a
// --dns-result-order flag given at runtime overrides it in initializeDns().
let dnsOrder = 'verbatim';
const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first'];
const validFamilies = [0, 4, 6];

function initializeDns() {
const orderFromCLI = getOptionValue('--dns-result-order');
if (!orderFromCLI) {
dnsOrder ??= 'verbatim';
} else {
if (orderFromCLI) {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders);
dnsOrder = orderFromCLI;
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ const {
resolveWithHooks,
validateLoadStrict,
} = require('internal/modules/customization_hooks');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);
Expand DownExpand Up@@ -1888,7 +1888,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
Module.prototype._compile = function(content, filename, format) {
if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
this[kURL] ??= convertCJSFilenameToURL(filename);
content = stripTypeScriptModuleTypes(content, filename, this[kURL]);
content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
switch (format) {
case 'commonjs-typescript': {
format = 'commonjs';
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/modules/esm/load.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,9 +20,6 @@ const {
ERR_UNSUPPORTED_ESM_URL_SCHEME,
} = require('internal/errors').codes;

const {
dataURLProcessor,
} = require('internal/data_url');

/**
* @param {URL} url URL to the module
Expand All@@ -40,6 +37,7 @@ function getSourceSync(url, context) {
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
source = fs.readFileSync(url);
} else if (protocol === 'data:') {
const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs.
const result = dataURLProcessor(url);
if (result === 'failure') {
throw new ERR_INVALID_URL(responseURL);
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/modules/esm/translators.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,10 @@ const {
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, url) {
// Only needed for TypeScript sources; keep it out of the loader's startup path.
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url);
}
const {
kIsCachedByESMLoader,
Module: CJSModule,
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/process/execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,9 @@ const {
kSourcePhase,
kEvaluationPhase,
} = internalBinding('module_wrap');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, filename) {
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename);
}

const {
executionAsyncId,
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/process/pre_execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -139,7 +139,12 @@ function prepareExecution(options) {

initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
// internal/dns/utils (and internal/net behind it) is only needed up front
// to validate an explicit --dns-result-order or to register the resolver's
// snapshot serialization; otherwise it is loaded with node:dns.
if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) {
require('internal/dns/utils').initializeDns();
}

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down
10 changes: 7 additions & 3 deletions lib/internal/url.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,11 @@ const {
kValidateObjectAllowObjects,
} = require('internal/validators');

const { percentDecode } = require('internal/data_url');
let percentDecode;
function lazyPercentDecode(input) {
percentDecode ??= require('internal/data_url').percentDecode;
return percentDecode(input);
}

const querystring = require('querystring');

Expand DownExpand Up@@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) {
// percent encoded characters and we take the string as is. Any invalid
// percent encodings, e.g. `%ZZ` are ignored and are passed through
// literally.
const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8'));
const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8),
TypedArrayPrototypeGetByteOffset(decodedu8),
TypedArrayPrototypeGetByteLength(decodedu8));
Expand DownExpand Up@@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) {
// won't scan for the slashes at all, and instead will decode the bytes
// literally into the returned Buffer. We're going to do the best we can and
// just interpret the input url as a sequence of bytes.
const u8 = percentDecode(Buffer.from(pathname, 'utf8'));
const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
return Buffer.from(TypedArrayPrototypeGetBuffer(u8),
TypedArrayPrototypeGetByteOffset(u8),
TypedArrayPrototypeGetByteLength(u8));
Expand Down
7 changes: 2 additions & 5 deletions lib/internal/worker.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,6 @@ const {
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const {
internalEventLoopUtilization,
} = require('internal/perf/event_loop_utilization');

const errorCodes = require('internal/errors').codes;
const {
ERR_WORKER_NOT_RUNNING,
Expand All@@ -60,7 +56,6 @@ const {
WritableWorkerStdio,
} = workerIo;
const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging');
const { deserializeError } = require('internal/error_serdes');
const { fileURLToPath, isURL, pathToFileURL } = require('internal/url');
const {
constructSharedArrayBuffer,
Expand DownExpand Up@@ -417,6 +412,7 @@ class Worker extends EventEmitter {

[kOnErrorMessage](serialized) {
// This is what is called for uncaught exceptions.
const { deserializeError } = require('internal/error_serdes');
const error = deserializeError(serialized);
this.emit('error', error);
}
Expand DownExpand Up@@ -699,6 +695,7 @@ function makeResourceLimits(float64arr) {
}

function eventLoopUtilization(util1, util2) {
const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization');
// TODO(trevnorris): Works to solve the thread-safe read/write issue of
// loopTime, but has the drawback that it can't be set until the event loop
// has had a chance to turn. So it will be impossible to read the ELU of
Expand Down
12 changes: 9 additions & 3 deletions lib/worker_threads.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
'use strict';

const { defineLazyProperties } = require('internal/util');

const {
isInternalThread,
isMainThread,
Expand DownExpand Up@@ -30,8 +32,6 @@ const {
isMarkedAsUntransferable,
} = require('internal/buffer');

const { locks } = require('internal/locks');

module.exports = {
isInternalThread,
isMainThread,
Expand All@@ -53,5 +53,11 @@ module.exports = {
BroadcastChannel,
setEnvironmentData,
getEnvironmentData,
locks,
};

// The Web Locks API implementation is only needed once `locks` is used.
defineLazyProperties(
module.exports,
'internal/locks',
['locks'],
);
37 changes: 21 additions & 16 deletions test/parallel/test-bootstrap-modules.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,10 +20,10 @@ const actual = {
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};
const getFormatNativeModule = 'NativeModule internal/modules/esm/get_format';

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
'Internal Binding errors',
'Internal Binding util',
Expand DownExpand Up@@ -88,10 +88,6 @@ expected.beforePreExec = new Set([
'NativeModule internal/v8/startup_snapshot',
'NativeModule internal/process/signal',
'Internal Binding fs',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/blob',
'NativeModule internal/fs/utils',
'NativeModule fs',
'Internal Binding options',
Expand All@@ -109,15 +105,10 @@ expected.beforePreExec = new Set([
'Internal Binding diagnostics_channel',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
'NativeModule internal/modules/typescript',
'NativeModule internal/data_url',
'NativeModule internal/mime',
'NativeModule internal/modules/esm/utils',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/modules/esm/get_format',
getFormatNativeModule,
'NativeModule internal/trace_events',
]);

Expand All@@ -126,8 +117,13 @@ expected.atRunTime = new Set([
]);

const { isMainThread } = require('worker_threads');
// Binaries built without the snapshot (e.g. cross-compiled) and
// --no-node-snapshot bootstrap the main context from scratch, like a worker.
const mainContextFromSnapshot = isMainThread &&
process.config.variables.node_use_node_snapshot &&
!process.execArgv.includes('--no-node-snapshot');

if (isMainThread) {
if (mainContextFromSnapshot) {
[
'Internal Binding cjs_lexer',
'NativeModule internal/modules/esm/assert',
Expand All@@ -138,15 +134,24 @@ if (isMainThread) {
'NativeModule internal/modules/esm/module_job',
'NativeModule internal/modules/esm/module_map',
'NativeModule url',
'Internal Binding encoding_binding',
'NativeModule internal/blob',
'NativeModule internal/data_url',
'NativeModule internal/dns/utils',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/mime',
'NativeModule internal/modules/typescript',
'NativeModule internal/net',
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else if (isMainThread) {
expected.beforePreExec.delete(getFormatNativeModule);
expected.atRunTime.add(getFormatNativeModule);
} else { // Worker.
[
'Internal Binding locks',
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
'NativeModule internal/error_serdes',
'NativeModule internal/locks',
'NativeModule internal/perf/event_loop_utilization',
'NativeModule internal/process/worker_thread_only',
'NativeModule internal/streams/add-abort-signal',
'NativeModule internal/streams/compose',
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/fs.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);
Expand DownExpand Up@@ -722,6 +720,7 @@ function openAsBlob(path, options = kEmptyObject) {
// To give ourselves flexibility to maybe return the Blob asynchronously,
// this API returns a Promise.
path = getValidatedPath(path);
const { createBlobFromFilePath } = require('internal/blob');
return PromiseResolve(createBlobFromFilePath(path, { type }));
}

Expand Down
23 changes: 18 additions & 5 deletions lib/internal/bootstrap/switches/is_main_thread.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() {

// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/loader');
require('internal/modules/esm/utils');
if (isBuildingSnapshot()) {
// Preloaded so that they are part of the snapshot, where they cost nothing
// at startup. When bootstrapping WITHOUT a snapshot (worker threads,
// embedders that create their own isolate, --no-node-snapshot) they are
// loaded on first use instead: the ESM loader (with its translators,
// resolver and their dependencies) by run_main/import(), the public util
// and url modules by whoever requires them, data: URL and TypeScript
// support by the module loaders, internal/blob by fs.openAsBlob(), and the
// DNS helpers by node:dns or an explicit --dns-result-order (see
// pre_execution).
require('util');
require('url'); // eslint-disable-line no-restricted-modules
require('internal/modules/esm/loader');
require('internal/data_url');
require('internal/modules/typescript');
require('internal/blob');
require('internal/dns/utils');
}

// Needed to refresh the time origin.
require('internal/perf/utils');
Expand All@@ -311,8 +326,6 @@ internalBinding('wasm_web_api');
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/dns/utils.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,15 +214,15 @@ class ResolverBase {
}

let defaultResolver;
let dnsOrder;
// May already hold a value chosen by the snapshotted application; a
// --dns-result-order flag given at runtime overrides it in initializeDns().
let dnsOrder = 'verbatim';
const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first'];
const validFamilies = [0, 4, 6];

function initializeDns() {
const orderFromCLI = getOptionValue('--dns-result-order');
if (!orderFromCLI) {
dnsOrder ??= 'verbatim';
} else {
if (orderFromCLI) {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders);
dnsOrder = orderFromCLI;
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ const {
resolveWithHooks,
validateLoadStrict,
} = require('internal/modules/customization_hooks');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);
Expand DownExpand Up@@ -1888,7 +1888,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
Module.prototype._compile = function(content, filename, format) {
if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
this[kURL] ??= convertCJSFilenameToURL(filename);
content = stripTypeScriptModuleTypes(content, filename, this[kURL]);
content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
switch (format) {
case 'commonjs-typescript': {
format = 'commonjs';
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/modules/esm/load.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,9 +20,6 @@ const {
ERR_UNSUPPORTED_ESM_URL_SCHEME,
} = require('internal/errors').codes;

const {
dataURLProcessor,
} = require('internal/data_url');

/**
* @param {URL} url URL to the module
Expand All@@ -40,6 +37,7 @@ function getSourceSync(url, context) {
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
source = fs.readFileSync(url);
} else if (protocol === 'data:') {
const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs.
const result = dataURLProcessor(url);
if (result === 'failure') {
throw new ERR_INVALID_URL(responseURL);
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/modules/esm/translators.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,10 @@ const {
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, url) {
// Only needed for TypeScript sources; keep it out of the loader's startup path.
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url);
}
const {
kIsCachedByESMLoader,
Module: CJSModule,
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/process/execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,9 @@ const {
kSourcePhase,
kEvaluationPhase,
} = internalBinding('module_wrap');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, filename) {
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename);
}

const {
executionAsyncId,
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/process/pre_execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -139,7 +139,12 @@ function prepareExecution(options) {

initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
// internal/dns/utils (and internal/net behind it) is only needed up front
// to validate an explicit --dns-result-order or to register the resolver's
// snapshot serialization; otherwise it is loaded with node:dns.
if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) {
require('internal/dns/utils').initializeDns();
}

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down
10 changes: 7 additions & 3 deletions lib/internal/url.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,11 @@ const {
kValidateObjectAllowObjects,
} = require('internal/validators');

const { percentDecode } = require('internal/data_url');
let percentDecode;
function lazyPercentDecode(input) {
percentDecode ??= require('internal/data_url').percentDecode;
return percentDecode(input);
}

const querystring = require('querystring');

Expand DownExpand Up@@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) {
// percent encoded characters and we take the string as is. Any invalid
// percent encodings, e.g. `%ZZ` are ignored and are passed through
// literally.
const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8'));
const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8),
TypedArrayPrototypeGetByteOffset(decodedu8),
TypedArrayPrototypeGetByteLength(decodedu8));
Expand DownExpand Up@@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) {
// won't scan for the slashes at all, and instead will decode the bytes
// literally into the returned Buffer. We're going to do the best we can and
// just interpret the input url as a sequence of bytes.
const u8 = percentDecode(Buffer.from(pathname, 'utf8'));
const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
return Buffer.from(TypedArrayPrototypeGetBuffer(u8),
TypedArrayPrototypeGetByteOffset(u8),
TypedArrayPrototypeGetByteLength(u8));
Expand Down
7 changes: 2 additions & 5 deletions lib/internal/worker.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,6 @@ const {
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const {
internalEventLoopUtilization,
} = require('internal/perf/event_loop_utilization');

const errorCodes = require('internal/errors').codes;
const {
ERR_WORKER_NOT_RUNNING,
Expand All@@ -60,7 +56,6 @@ const {
WritableWorkerStdio,
} = workerIo;
const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging');
const { deserializeError } = require('internal/error_serdes');
const { fileURLToPath, isURL, pathToFileURL } = require('internal/url');
const {
constructSharedArrayBuffer,
Expand DownExpand Up@@ -417,6 +412,7 @@ class Worker extends EventEmitter {

[kOnErrorMessage](serialized) {
// This is what is called for uncaught exceptions.
const { deserializeError } = require('internal/error_serdes');
const error = deserializeError(serialized);
this.emit('error', error);
}
Expand DownExpand Up@@ -699,6 +695,7 @@ function makeResourceLimits(float64arr) {
}

function eventLoopUtilization(util1, util2) {
const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization');
// TODO(trevnorris): Works to solve the thread-safe read/write issue of
// loopTime, but has the drawback that it can't be set until the event loop
// has had a chance to turn. So it will be impossible to read the ELU of
Expand Down
12 changes: 9 additions & 3 deletions lib/worker_threads.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
'use strict';

const { defineLazyProperties } = require('internal/util');

const {
isInternalThread,
isMainThread,
Expand DownExpand Up@@ -30,8 +32,6 @@ const {
isMarkedAsUntransferable,
} = require('internal/buffer');

const { locks } = require('internal/locks');

module.exports = {
isInternalThread,
isMainThread,
Expand All@@ -53,5 +53,11 @@ module.exports = {
BroadcastChannel,
setEnvironmentData,
getEnvironmentData,
locks,
};

// The Web Locks API implementation is only needed once `locks` is used.
defineLazyProperties(
module.exports,
'internal/locks',
['locks'],
);
37 changes: 21 additions & 16 deletions test/parallel/test-bootstrap-modules.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,10 +20,10 @@ const actual = {
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};
const getFormatNativeModule = 'NativeModule internal/modules/esm/get_format';

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
'Internal Binding errors',
'Internal Binding util',
Expand DownExpand Up@@ -88,10 +88,6 @@ expected.beforePreExec = new Set([
'NativeModule internal/v8/startup_snapshot',
'NativeModule internal/process/signal',
'Internal Binding fs',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/blob',
'NativeModule internal/fs/utils',
'NativeModule fs',
'Internal Binding options',
Expand All@@ -109,15 +105,10 @@ expected.beforePreExec = new Set([
'Internal Binding diagnostics_channel',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
'NativeModule internal/modules/typescript',
'NativeModule internal/data_url',
'NativeModule internal/mime',
'NativeModule internal/modules/esm/utils',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/modules/esm/get_format',
getFormatNativeModule,
'NativeModule internal/trace_events',
]);

Expand All@@ -126,8 +117,13 @@ expected.atRunTime = new Set([
]);

const { isMainThread } = require('worker_threads');
// Binaries built without the snapshot (e.g. cross-compiled) and
// --no-node-snapshot bootstrap the main context from scratch, like a worker.
const mainContextFromSnapshot = isMainThread &&
process.config.variables.node_use_node_snapshot &&
!process.execArgv.includes('--no-node-snapshot');

if (isMainThread) {
if (mainContextFromSnapshot) {
[
'Internal Binding cjs_lexer',
'NativeModule internal/modules/esm/assert',
Expand All@@ -138,15 +134,24 @@ if (isMainThread) {
'NativeModule internal/modules/esm/module_job',
'NativeModule internal/modules/esm/module_map',
'NativeModule url',
'Internal Binding encoding_binding',
'NativeModule internal/blob',
'NativeModule internal/data_url',
'NativeModule internal/dns/utils',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/mime',
'NativeModule internal/modules/typescript',
'NativeModule internal/net',
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else if (isMainThread) {
expected.beforePreExec.delete(getFormatNativeModule);
expected.atRunTime.add(getFormatNativeModule);
} else { // Worker.
[
'Internal Binding locks',
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
'NativeModule internal/error_serdes',
'NativeModule internal/locks',
'NativeModule internal/perf/event_loop_utilization',
'NativeModule internal/process/worker_thread_only',
'NativeModule internal/streams/add-abort-signal',
'NativeModule internal/streams/compose',
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/fs.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);
Expand DownExpand Up@@ -722,6 +720,7 @@ function openAsBlob(path, options = kEmptyObject) {
// To give ourselves flexibility to maybe return the Blob asynchronously,
// this API returns a Promise.
path = getValidatedPath(path);
const { createBlobFromFilePath } = require('internal/blob');
return PromiseResolve(createBlobFromFilePath(path, { type }));
}

Expand Down
23 changes: 18 additions & 5 deletions lib/internal/bootstrap/switches/is_main_thread.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() {

// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/loader');
require('internal/modules/esm/utils');
if (isBuildingSnapshot()) {
// Preloaded so that they are part of the snapshot, where they cost nothing
// at startup. When bootstrapping WITHOUT a snapshot (worker threads,
// embedders that create their own isolate, --no-node-snapshot) they are
// loaded on first use instead: the ESM loader (with its translators,
// resolver and their dependencies) by run_main/import(), the public util
// and url modules by whoever requires them, data: URL and TypeScript
// support by the module loaders, internal/blob by fs.openAsBlob(), and the
// DNS helpers by node:dns or an explicit --dns-result-order (see
// pre_execution).
require('util');
require('url'); // eslint-disable-line no-restricted-modules
require('internal/modules/esm/loader');
require('internal/data_url');
require('internal/modules/typescript');
require('internal/blob');
require('internal/dns/utils');
}

// Needed to refresh the time origin.
require('internal/perf/utils');
Expand All@@ -311,8 +326,6 @@ internalBinding('wasm_web_api');
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/dns/utils.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,15 +214,15 @@ class ResolverBase {
}

let defaultResolver;
let dnsOrder;
// May already hold a value chosen by the snapshotted application; a
// --dns-result-order flag given at runtime overrides it in initializeDns().
let dnsOrder = 'verbatim';
const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first'];
const validFamilies = [0, 4, 6];

function initializeDns() {
const orderFromCLI = getOptionValue('--dns-result-order');
if (!orderFromCLI) {
dnsOrder ??= 'verbatim';
} else {
if (orderFromCLI) {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders);
dnsOrder = orderFromCLI;
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ const {
resolveWithHooks,
validateLoadStrict,
} = require('internal/modules/customization_hooks');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);
Expand DownExpand Up@@ -1888,7 +1888,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
Module.prototype._compile = function(content, filename, format) {
if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
this[kURL] ??= convertCJSFilenameToURL(filename);
content = stripTypeScriptModuleTypes(content, filename, this[kURL]);
content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
switch (format) {
case 'commonjs-typescript': {
format = 'commonjs';
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/modules/esm/load.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,9 +20,6 @@ const {
ERR_UNSUPPORTED_ESM_URL_SCHEME,
} = require('internal/errors').codes;

const {
dataURLProcessor,
} = require('internal/data_url');

/**
* @param {URL} url URL to the module
Expand All@@ -40,6 +37,7 @@ function getSourceSync(url, context) {
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
source = fs.readFileSync(url);
} else if (protocol === 'data:') {
const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs.
const result = dataURLProcessor(url);
if (result === 'failure') {
throw new ERR_INVALID_URL(responseURL);
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/modules/esm/translators.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,10 @@ const {
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, url) {
// Only needed for TypeScript sources; keep it out of the loader's startup path.
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url);
}
const {
kIsCachedByESMLoader,
Module: CJSModule,
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/process/execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,9 @@ const {
kSourcePhase,
kEvaluationPhase,
} = internalBinding('module_wrap');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, filename) {
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename);
}

const {
executionAsyncId,
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/process/pre_execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -139,7 +139,12 @@ function prepareExecution(options) {

initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
// internal/dns/utils (and internal/net behind it) is only needed up front
// to validate an explicit --dns-result-order or to register the resolver's
// snapshot serialization; otherwise it is loaded with node:dns.
if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) {
require('internal/dns/utils').initializeDns();
}

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down
10 changes: 7 additions & 3 deletions lib/internal/url.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,11 @@ const {
kValidateObjectAllowObjects,
} = require('internal/validators');

const { percentDecode } = require('internal/data_url');
let percentDecode;
function lazyPercentDecode(input) {
percentDecode ??= require('internal/data_url').percentDecode;
return percentDecode(input);
}

const querystring = require('querystring');

Expand DownExpand Up@@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) {
// percent encoded characters and we take the string as is. Any invalid
// percent encodings, e.g. `%ZZ` are ignored and are passed through
// literally.
const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8'));
const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8),
TypedArrayPrototypeGetByteOffset(decodedu8),
TypedArrayPrototypeGetByteLength(decodedu8));
Expand DownExpand Up@@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) {
// won't scan for the slashes at all, and instead will decode the bytes
// literally into the returned Buffer. We're going to do the best we can and
// just interpret the input url as a sequence of bytes.
const u8 = percentDecode(Buffer.from(pathname, 'utf8'));
const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
return Buffer.from(TypedArrayPrototypeGetBuffer(u8),
TypedArrayPrototypeGetByteOffset(u8),
TypedArrayPrototypeGetByteLength(u8));
Expand Down
7 changes: 2 additions & 5 deletions lib/internal/worker.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,6 @@ const {
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const {
internalEventLoopUtilization,
} = require('internal/perf/event_loop_utilization');

const errorCodes = require('internal/errors').codes;
const {
ERR_WORKER_NOT_RUNNING,
Expand All@@ -60,7 +56,6 @@ const {
WritableWorkerStdio,
} = workerIo;
const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging');
const { deserializeError } = require('internal/error_serdes');
const { fileURLToPath, isURL, pathToFileURL } = require('internal/url');
const {
constructSharedArrayBuffer,
Expand DownExpand Up@@ -417,6 +412,7 @@ class Worker extends EventEmitter {

[kOnErrorMessage](serialized) {
// This is what is called for uncaught exceptions.
const { deserializeError } = require('internal/error_serdes');
const error = deserializeError(serialized);
this.emit('error', error);
}
Expand DownExpand Up@@ -699,6 +695,7 @@ function makeResourceLimits(float64arr) {
}

function eventLoopUtilization(util1, util2) {
const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization');
// TODO(trevnorris): Works to solve the thread-safe read/write issue of
// loopTime, but has the drawback that it can't be set until the event loop
// has had a chance to turn. So it will be impossible to read the ELU of
Expand Down
12 changes: 9 additions & 3 deletions lib/worker_threads.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
'use strict';

const { defineLazyProperties } = require('internal/util');

const {
isInternalThread,
isMainThread,
Expand DownExpand Up@@ -30,8 +32,6 @@ const {
isMarkedAsUntransferable,
} = require('internal/buffer');

const { locks } = require('internal/locks');

module.exports = {
isInternalThread,
isMainThread,
Expand All@@ -53,5 +53,11 @@ module.exports = {
BroadcastChannel,
setEnvironmentData,
getEnvironmentData,
locks,
};

// The Web Locks API implementation is only needed once `locks` is used.
defineLazyProperties(
module.exports,
'internal/locks',
['locks'],
);
37 changes: 21 additions & 16 deletions test/parallel/test-bootstrap-modules.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,10 +20,10 @@ const actual = {
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};
const getFormatNativeModule = 'NativeModule internal/modules/esm/get_format';

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
'Internal Binding errors',
'Internal Binding util',
Expand DownExpand Up@@ -88,10 +88,6 @@ expected.beforePreExec = new Set([
'NativeModule internal/v8/startup_snapshot',
'NativeModule internal/process/signal',
'Internal Binding fs',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/blob',
'NativeModule internal/fs/utils',
'NativeModule fs',
'Internal Binding options',
Expand All@@ -109,15 +105,10 @@ expected.beforePreExec = new Set([
'Internal Binding diagnostics_channel',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
'NativeModule internal/modules/typescript',
'NativeModule internal/data_url',
'NativeModule internal/mime',
'NativeModule internal/modules/esm/utils',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/modules/esm/get_format',
getFormatNativeModule,
'NativeModule internal/trace_events',
]);

Expand All@@ -126,8 +117,13 @@ expected.atRunTime = new Set([
]);

const { isMainThread } = require('worker_threads');
// Binaries built without the snapshot (e.g. cross-compiled) and
// --no-node-snapshot bootstrap the main context from scratch, like a worker.
const mainContextFromSnapshot = isMainThread &&
process.config.variables.node_use_node_snapshot &&
!process.execArgv.includes('--no-node-snapshot');

if (isMainThread) {
if (mainContextFromSnapshot) {
[
'Internal Binding cjs_lexer',
'NativeModule internal/modules/esm/assert',
Expand All@@ -138,15 +134,24 @@ if (isMainThread) {
'NativeModule internal/modules/esm/module_job',
'NativeModule internal/modules/esm/module_map',
'NativeModule url',
'Internal Binding encoding_binding',
'NativeModule internal/blob',
'NativeModule internal/data_url',
'NativeModule internal/dns/utils',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/mime',
'NativeModule internal/modules/typescript',
'NativeModule internal/net',
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else if (isMainThread) {
expected.beforePreExec.delete(getFormatNativeModule);
expected.atRunTime.add(getFormatNativeModule);
} else { // Worker.
[
'Internal Binding locks',
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
'NativeModule internal/error_serdes',
'NativeModule internal/locks',
'NativeModule internal/perf/event_loop_utilization',
'NativeModule internal/process/worker_thread_only',
'NativeModule internal/streams/add-abort-signal',
'NativeModule internal/streams/compose',
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/fs.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types');

const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
const BufferToString = uncurryThis(Buffer.prototype.toString);
Expand DownExpand Up@@ -722,6 +720,7 @@ function openAsBlob(path, options = kEmptyObject) {
// To give ourselves flexibility to maybe return the Blob asynchronously,
// this API returns a Promise.
path = getValidatedPath(path);
const { createBlobFromFilePath } = require('internal/blob');
return PromiseResolve(createBlobFromFilePath(path, { type }));
}

Expand Down
23 changes: 18 additions & 5 deletions lib/internal/bootstrap/switches/is_main_thread.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() {

// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/loader');
require('internal/modules/esm/utils');
if (isBuildingSnapshot()) {
// Preloaded so that they are part of the snapshot, where they cost nothing
// at startup. When bootstrapping WITHOUT a snapshot (worker threads,
// embedders that create their own isolate, --no-node-snapshot) they are
// loaded on first use instead: the ESM loader (with its translators,
// resolver and their dependencies) by run_main/import(), the public util
// and url modules by whoever requires them, data: URL and TypeScript
// support by the module loaders, internal/blob by fs.openAsBlob(), and the
// DNS helpers by node:dns or an explicit --dns-result-order (see
// pre_execution).
require('util');
require('url'); // eslint-disable-line no-restricted-modules
require('internal/modules/esm/loader');
require('internal/data_url');
require('internal/modules/typescript');
require('internal/blob');
require('internal/dns/utils');
}

// Needed to refresh the time origin.
require('internal/perf/utils');
Expand All@@ -311,8 +326,6 @@ internalBinding('wasm_web_api');
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/dns/utils.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -214,15 +214,15 @@ class ResolverBase {
}

let defaultResolver;
let dnsOrder;
// May already hold a value chosen by the snapshotted application; a
// --dns-result-order flag given at runtime overrides it in initializeDns().
let dnsOrder = 'verbatim';
const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first'];
const validFamilies = [0, 4, 6];

function initializeDns() {
const orderFromCLI = getOptionValue('--dns-result-order');
if (!orderFromCLI) {
dnsOrder ??= 'verbatim';
} else {
if (orderFromCLI) {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders);
dnsOrder = orderFromCLI;
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ const {
resolveWithHooks,
validateLoadStrict,
} = require('internal/modules/customization_hooks');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);
Expand DownExpand Up@@ -1888,7 +1888,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) {
Module.prototype._compile = function(content, filename, format) {
if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
this[kURL] ??= convertCJSFilenameToURL(filename);
content = stripTypeScriptModuleTypes(content, filename, this[kURL]);
content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
switch (format) {
case 'commonjs-typescript': {
format = 'commonjs';
Expand Down
4 changes: 1 addition & 3 deletions lib/internal/modules/esm/load.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,9 +20,6 @@ const {
ERR_UNSUPPORTED_ESM_URL_SCHEME,
} = require('internal/errors').codes;

const {
dataURLProcessor,
} = require('internal/data_url');

/**
* @param {URL} url URL to the module
Expand All@@ -40,6 +37,7 @@ function getSourceSync(url, context) {
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
source = fs.readFileSync(url);
} else if (protocol === 'data:') {
const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs.
const result = dataURLProcessor(url);
if (result === 'failure') {
throw new ERR_INVALID_URL(responseURL);
Expand Down
5 changes: 4 additions & 1 deletion lib/internal/modules/esm/translators.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,10 @@ const {
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, url) {
// Only needed for TypeScript sources; keep it out of the loader's startup path.
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url);
}
const {
kIsCachedByESMLoader,
Module: CJSModule,
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/process/execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,7 +25,9 @@ const {
kSourcePhase,
kEvaluationPhase,
} = internalBinding('module_wrap');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
function stripTypeScriptModuleTypes(source, filename) {
return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename);
}

const {
executionAsyncId,
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/process/pre_execution.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -139,7 +139,12 @@ function prepareExecution(options) {

initializeConfigFileSupport();

require('internal/dns/utils').initializeDns();
// internal/dns/utils (and internal/net behind it) is only needed up front
// to validate an explicit --dns-result-order or to register the resolver's
// snapshot serialization; otherwise it is loaded with node:dns.
if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) {
require('internal/dns/utils').initializeDns();
}

if (isMainThread) {
assert(internalBinding('worker').isMainThread);
Expand Down
10 changes: 7 additions & 3 deletions lib/internal/url.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,11 @@ const {
kValidateObjectAllowObjects,
} = require('internal/validators');

const { percentDecode } = require('internal/data_url');
let percentDecode;
function lazyPercentDecode(input) {
percentDecode ??= require('internal/data_url').percentDecode;
return percentDecode(input);
}

const querystring = require('querystring');

Expand DownExpand Up@@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) {
// percent encoded characters and we take the string as is. Any invalid
// percent encodings, e.g. `%ZZ` are ignored and are passed through
// literally.
const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8'));
const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8),
TypedArrayPrototypeGetByteOffset(decodedu8),
TypedArrayPrototypeGetByteLength(decodedu8));
Expand DownExpand Up@@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) {
// won't scan for the slashes at all, and instead will decode the bytes
// literally into the returned Buffer. We're going to do the best we can and
// just interpret the input url as a sequence of bytes.
const u8 = percentDecode(Buffer.from(pathname, 'utf8'));
const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8'));
return Buffer.from(TypedArrayPrototypeGetBuffer(u8),
TypedArrayPrototypeGetByteOffset(u8),
TypedArrayPrototypeGetByteLength(u8));
Expand Down
7 changes: 2 additions & 5 deletions lib/internal/worker.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,10 +30,6 @@ const {
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const {
internalEventLoopUtilization,
} = require('internal/perf/event_loop_utilization');

const errorCodes = require('internal/errors').codes;
const {
ERR_WORKER_NOT_RUNNING,
Expand All@@ -60,7 +56,6 @@ const {
WritableWorkerStdio,
} = workerIo;
const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging');
const { deserializeError } = require('internal/error_serdes');
const { fileURLToPath, isURL, pathToFileURL } = require('internal/url');
const {
constructSharedArrayBuffer,
Expand DownExpand Up@@ -417,6 +412,7 @@ class Worker extends EventEmitter {

[kOnErrorMessage](serialized) {
// This is what is called for uncaught exceptions.
const { deserializeError } = require('internal/error_serdes');
const error = deserializeError(serialized);
this.emit('error', error);
}
Expand DownExpand Up@@ -699,6 +695,7 @@ function makeResourceLimits(float64arr) {
}

function eventLoopUtilization(util1, util2) {
const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization');
// TODO(trevnorris): Works to solve the thread-safe read/write issue of
// loopTime, but has the drawback that it can't be set until the event loop
// has had a chance to turn. So it will be impossible to read the ELU of
Expand Down
12 changes: 9 additions & 3 deletions lib/worker_threads.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
'use strict';

const { defineLazyProperties } = require('internal/util');

const {
isInternalThread,
isMainThread,
Expand DownExpand Up@@ -30,8 +32,6 @@ const {
isMarkedAsUntransferable,
} = require('internal/buffer');

const { locks } = require('internal/locks');

module.exports = {
isInternalThread,
isMainThread,
Expand All@@ -53,5 +53,11 @@ module.exports = {
BroadcastChannel,
setEnvironmentData,
getEnvironmentData,
locks,
};

// The Web Locks API implementation is only needed once `locks` is used.
defineLazyProperties(
module.exports,
'internal/locks',
['locks'],
);
37 changes: 21 additions & 16 deletions test/parallel/test-bootstrap-modules.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,10 +20,10 @@ const actual = {
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};
const getFormatNativeModule = 'NativeModule internal/modules/esm/get_format';

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
'Internal Binding errors',
'Internal Binding util',
Expand DownExpand Up@@ -88,10 +88,6 @@ expected.beforePreExec = new Set([
'NativeModule internal/v8/startup_snapshot',
'NativeModule internal/process/signal',
'Internal Binding fs',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/blob',
'NativeModule internal/fs/utils',
'NativeModule fs',
'Internal Binding options',
Expand All@@ -109,15 +105,10 @@ expected.beforePreExec = new Set([
'Internal Binding diagnostics_channel',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
'NativeModule internal/modules/typescript',
'NativeModule internal/data_url',
'NativeModule internal/mime',
'NativeModule internal/modules/esm/utils',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/modules/esm/get_format',
getFormatNativeModule,
'NativeModule internal/trace_events',
]);

Expand All@@ -126,8 +117,13 @@ expected.atRunTime = new Set([
]);

const { isMainThread } = require('worker_threads');
// Binaries built without the snapshot (e.g. cross-compiled) and
// --no-node-snapshot bootstrap the main context from scratch, like a worker.
const mainContextFromSnapshot = isMainThread &&
process.config.variables.node_use_node_snapshot &&
!process.execArgv.includes('--no-node-snapshot');

if (isMainThread) {
if (mainContextFromSnapshot) {
[
'Internal Binding cjs_lexer',
'NativeModule internal/modules/esm/assert',
Expand All@@ -138,15 +134,24 @@ if (isMainThread) {
'NativeModule internal/modules/esm/module_job',
'NativeModule internal/modules/esm/module_map',
'NativeModule url',
'Internal Binding encoding_binding',
'NativeModule internal/blob',
'NativeModule internal/data_url',
'NativeModule internal/dns/utils',
'NativeModule internal/encoding',
'NativeModule internal/encoding/single-byte',
'NativeModule internal/encoding/util',
'NativeModule internal/mime',
'NativeModule internal/modules/typescript',
'NativeModule internal/net',
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else if (isMainThread) {
expected.beforePreExec.delete(getFormatNativeModule);
expected.atRunTime.add(getFormatNativeModule);
} else { // Worker.
[
'Internal Binding locks',
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
'NativeModule internal/error_serdes',
'NativeModule internal/locks',
'NativeModule internal/perf/event_loop_utilization',
'NativeModule internal/process/worker_thread_only',
'NativeModule internal/streams/add-abort-signal',
'NativeModule internal/streams/compose',
Expand Down
Loading