GeezerVison is showing github.com — lib: load fewer builtins when bootstrapping without a snapshot · nodejs/node@e8e2abc
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/fs.js +1-2Lines changed: 1 addition & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -64,8 +64,6 @@ const { isArrayBufferView } = require('internal/util/types'); | 64 | 64 |
| 65 | 65 | const binding = internalBinding('fs'); | 66 | 66 |
| 67 | | -const { createBlobFromFilePath } = require('internal/blob'); | 68 | | - | 69 | 67 | const { Buffer } = require('buffer'); | 70 | 68 | const { isBuffer: BufferIsBuffer } = Buffer; | 71 | 69 | const BufferToString = uncurryThis(Buffer.prototype.toString); | @@ -784,6 +782,7 @@ function openAsBlob(path, options = kEmptyObject) { | 784 | 782 | // To give ourselves flexibility to maybe return the Blob asynchronously, | 785 | 783 | // this API returns a Promise. | 786 | 784 | path = getValidatedPath(path); | | 785 | + const { createBlobFromFilePath } = require('internal/blob'); | 787 | 786 | return PromiseResolve(createBlobFromFilePath(path, { type })); | 788 | 787 | } | 789 | 788 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/bootstrap/switches/is_main_thread.js +18-5Lines changed: 18 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -292,12 +292,27 @@ rawMethods.resetStdioForTesting = function() { | 292 | 292 |
| 293 | 293 | // Needed by the module loader and generally needed everywhere. | 294 | 294 | require('fs'); | 295 | | -require('util'); | 296 | | -require('url'); // eslint-disable-line no-restricted-modules | 297 | 295 | internalBinding('module_wrap'); | 298 | 296 | require('internal/modules/cjs/loader'); | 299 | | -require('internal/modules/esm/loader'); | 300 | 297 | require('internal/modules/esm/utils'); | | 298 | +if (isBuildingSnapshot()) { | | 299 | + // Preloaded so that they are part of the snapshot, where they cost nothing | | 300 | + // at startup. When bootstrapping WITHOUT a snapshot (worker threads, | | 301 | + // embedders that create their own isolate, --no-node-snapshot) they are | | 302 | + // loaded on first use instead: the ESM loader (with its translators, | | 303 | + // resolver and their dependencies) by run_main/import(), the public util | | 304 | + // and url modules by whoever requires them, data: URL and TypeScript | | 305 | + // support by the module loaders, internal/blob by fs.openAsBlob(), and the | | 306 | + // DNS helpers by node:dns or an explicit --dns-result-order (see | | 307 | + // pre_execution). | | 308 | + require('util'); | | 309 | + require('url'); // eslint-disable-line no-restricted-modules | | 310 | + require('internal/modules/esm/loader'); | | 311 | + require('internal/data_url'); | | 312 | + require('internal/modules/typescript'); | | 313 | + require('internal/blob'); | | 314 | + require('internal/dns/utils'); | | 315 | +} | 301 | 316 |
| 302 | 317 | // Needed to refresh the time origin. | 303 | 318 | require('internal/perf/utils'); | @@ -311,8 +326,6 @@ internalBinding('wasm_web_api'); | 311 | 326 | internalBinding('worker'); | 312 | 327 | // Needed by most execution modes. | 313 | 328 | require('internal/modules/run_main'); | 314 | | -// Needed to refresh DNS configurations. | 315 | | -require('internal/dns/utils'); | 316 | 329 | // Needed by almost all execution modes. It's fine to | 317 | 330 | // load them into the snapshot as long as we don't run | 318 | 331 | // any of the initialization. | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/dns/utils.js +4-4Lines changed: 4 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -214,15 +214,15 @@ class ResolverBase { | 214 | 214 | } | 215 | 215 |
| 216 | 216 | let defaultResolver; | 217 | | -let dnsOrder; | | 217 | +// May already hold a value chosen by the snapshotted application; a | | 218 | +// --dns-result-order flag given at runtime overrides it in initializeDns(). | | 219 | +let dnsOrder = 'verbatim'; | 218 | 220 | const validDnsOrders = ['verbatim', 'ipv4first', 'ipv6first']; | 219 | 221 | const validFamilies = [0, 4, 6]; | 220 | 222 |
| 221 | 223 | function initializeDns() { | 222 | 224 | const orderFromCLI = getOptionValue('--dns-result-order'); | 223 | | - if (!orderFromCLI) { | 224 | | - dnsOrder ??= 'verbatim'; | 225 | | - } else { | | 225 | + if (orderFromCLI) { | 226 | 226 | // Allow the deserialized application to override order from CLI. | 227 | 227 | validateOneOf(orderFromCLI, '--dns-result-order', validDnsOrders); | 228 | 228 | dnsOrder = orderFromCLI; | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -180,7 +180,7 @@ const { | 180 | 180 | resolveWithHooks, | 181 | 181 | validateLoadStrict, | 182 | 182 | } = require('internal/modules/customization_hooks'); | 183 | | -const { stripTypeScriptModuleTypes } = require('internal/modules/typescript'); | | 183 | +const lazyTypeScript = getLazy(() => require('internal/modules/typescript')); | 184 | 184 | const packageJsonReader = require('internal/modules/package_json_reader'); | 185 | 185 | const { getOptionValue, getEmbedderOptions } = require('internal/options'); | 186 | 186 | const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES); | @@ -1885,7 +1885,7 @@ function wrapSafe(filename, content, cjsModuleInstance, format) { | 1885 | 1885 | Module.prototype._compile = function(content, filename, format) { | 1886 | 1886 | if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') { | 1887 | 1887 | this[kURL] ??= convertCJSFilenameToURL(filename); | 1888 | | - content = stripTypeScriptModuleTypes(content, filename, this[kURL]); | | 1888 | + content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]); | 1889 | 1889 | switch (format) { | 1890 | 1890 | case 'commonjs-typescript': { | 1891 | 1891 | format = 'commonjs'; | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/load.js +1-3Lines changed: 1 addition & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -20,9 +20,6 @@ const { | 20 | 20 | ERR_UNSUPPORTED_ESM_URL_SCHEME, | 21 | 21 | } = require('internal/errors').codes; | 22 | 22 |
| 23 | | -const { | 24 | | - dataURLProcessor, | 25 | | -} = require('internal/data_url'); | 26 | 23 |
| 27 | 24 | /** | 28 | 25 | * @param {URL} url URL to the module | @@ -40,6 +37,7 @@ function getSourceSync(url, context) { | 40 | 37 | // Prefer module.registerHooks() or other more formal fs hooks released in the future. | 41 | 38 | source = fs.readFileSync(url); | 42 | 39 | } else if (protocol === 'data:') { | | 40 | + const { dataURLProcessor } = require('internal/data_url'); // Only for data: URLs. | 43 | 41 | const result = dataURLProcessor(url); | 44 | 42 | if (result === 'failure') { | 45 | 43 | throw new ERR_INVALID_URL(responseURL); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/translators.js +4-1Lines changed: 4 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -30,7 +30,10 @@ const { | 30 | 30 | stripBOM, | 31 | 31 | urlToFilename, | 32 | 32 | } = require('internal/modules/helpers'); | 33 | | -const { stripTypeScriptModuleTypes } = require('internal/modules/typescript'); | | 33 | +function stripTypeScriptModuleTypes(source, url) { | | 34 | + // Only needed for TypeScript sources; keep it out of the loader's startup path. | | 35 | + return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, url); | | 36 | +} | 34 | 37 | const { | 35 | 38 | kIsCachedByESMLoader, | 36 | 39 | Module: CJSModule, | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/process/execution.js +3-1Lines changed: 3 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -25,7 +25,9 @@ const { | 25 | 25 | kSourcePhase, | 26 | 26 | kEvaluationPhase, | 27 | 27 | } = internalBinding('module_wrap'); | 28 | | -const { stripTypeScriptModuleTypes } = require('internal/modules/typescript'); | | 28 | +function stripTypeScriptModuleTypes(source, filename) { | | 29 | + return require('internal/modules/typescript').stripTypeScriptModuleTypes(source, filename); | | 30 | +} | 29 | 31 |
| 30 | 32 | const { | 31 | 33 | executionAsyncId, | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/process/pre_execution.js +6-1Lines changed: 6 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -137,7 +137,12 @@ function prepareExecution(options) { | 137 | 137 |
| 138 | 138 | initializeConfigFileSupport(); | 139 | 139 |
| 140 | | - require('internal/dns/utils').initializeDns(); | | 140 | + // internal/dns/utils (and internal/net behind it) is only needed up front | | 141 | + // to validate an explicit --dns-result-order or to register the resolver's | | 142 | + // snapshot serialization; otherwise it is loaded with node:dns. | | 143 | + if (getOptionValue('--dns-result-order') || isBuildingSnapshot()) { | | 144 | + require('internal/dns/utils').initializeDns(); | | 145 | + } | 141 | 146 |
| 142 | 147 | if (isMainThread) { | 143 | 148 | assert(internalBinding('worker').isMainThread); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/url.js +7-3Lines changed: 7 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -93,7 +93,11 @@ const { | 93 | 93 | kValidateObjectAllowObjects, | 94 | 94 | } = require('internal/validators'); | 95 | 95 |
| 96 | | -const { percentDecode } = require('internal/data_url'); | | 96 | +let percentDecode; | | 97 | +function lazyPercentDecode(input) { | | 98 | + percentDecode ??= require('internal/data_url').percentDecode; | | 99 | + return percentDecode(input); | | 100 | +} | 97 | 101 |
| 98 | 102 | const querystring = require('querystring'); | 99 | 103 |
| @@ -1560,7 +1564,7 @@ function getPathBufferFromURLWin32(url) { | 1560 | 1564 | // percent encoded characters and we take the string as is. Any invalid | 1561 | 1565 | // percent encodings, e.g. `%ZZ` are ignored and are passed through | 1562 | 1566 | // literally. | 1563 | | - const decodedu8 = percentDecode(Buffer.from(pathname, 'utf8')); | | 1567 | + const decodedu8 = lazyPercentDecode(Buffer.from(pathname, 'utf8')); | 1564 | 1568 | const decodedPathname = Buffer.from(TypedArrayPrototypeGetBuffer(decodedu8), | 1565 | 1569 | TypedArrayPrototypeGetByteOffset(decodedu8), | 1566 | 1570 | TypedArrayPrototypeGetByteLength(decodedu8)); | @@ -1635,7 +1639,7 @@ function getPathBufferFromURLPosix(url) { | 1635 | 1639 | // won't scan for the slashes at all, and instead will decode the bytes | 1636 | 1640 | // literally into the returned Buffer. We're going to do the best we can and | 1637 | 1641 | // just interpret the input url as a sequence of bytes. | 1638 | | - const u8 = percentDecode(Buffer.from(pathname, 'utf8')); | | 1642 | + const u8 = lazyPercentDecode(Buffer.from(pathname, 'utf8')); | 1639 | 1643 | return Buffer.from(TypedArrayPrototypeGetBuffer(u8), | 1640 | 1644 | TypedArrayPrototypeGetByteOffset(u8), | 1641 | 1645 | TypedArrayPrototypeGetByteLength(u8)); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/worker.js +2-5Lines changed: 2 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -30,10 +30,6 @@ const { | 30 | 30 | const EventEmitter = require('events'); | 31 | 31 | const assert = require('internal/assert'); | 32 | 32 | const path = require('path'); | 33 | | -const { | 34 | | - internalEventLoopUtilization, | 35 | | -} = require('internal/perf/event_loop_utilization'); | 36 | | - | 37 | 33 | const errorCodes = require('internal/errors').codes; | 38 | 34 | const { | 39 | 35 | ERR_WORKER_NOT_RUNNING, | @@ -60,7 +56,6 @@ const { | 60 | 56 | WritableWorkerStdio, | 61 | 57 | } = workerIo; | 62 | 58 | const { createMainThreadPort, destroyMainThreadPort } = require('internal/worker/messaging'); | 63 | | -const { deserializeError } = require('internal/error_serdes'); | 64 | 59 | const { fileURLToPath, isURL, pathToFileURL } = require('internal/url'); | 65 | 60 | const { | 66 | 61 | constructSharedArrayBuffer, | @@ -415,6 +410,7 @@ class Worker extends EventEmitter { | 415 | 410 |
| 416 | 411 | [kOnErrorMessage](serialized) { | 417 | 412 | // This is what is called for uncaught exceptions. | | 413 | + const { deserializeError } = require('internal/error_serdes'); | 418 | 414 | const error = deserializeError(serialized); | 419 | 415 | this.emit('error', error); | 420 | 416 | } | @@ -697,6 +693,7 @@ function makeResourceLimits(float64arr) { | 697 | 693 | } | 698 | 694 |
| 699 | 695 | function eventLoopUtilization(util1, util2) { | | 696 | + const { internalEventLoopUtilization } = require('internal/perf/event_loop_utilization'); | 700 | 697 | // TODO(trevnorris): Works to solve the thread-safe read/write issue of | 701 | 698 | // loopTime, but has the drawback that it can't be set until the event loop | 702 | 699 | // has had a chance to turn. So it will be impossible to read the ELU of | |
|