Skip to content

Commit e2caf7c

Browse files
joyeecheungtargos
authored andcommitted
bootstrap: lazy load non-essential modules
It turns out that even with startup snapshots, there is a non-trivial overhead for loading internal modules. This patch makes the loading of the non-essential modules lazy again. Caveat: we have to make some of the globals lazily-loaded too, so the WPT runner is updated to test what the state of the global scope is after the globals are accessed (and replaced with the loaded value). PR-URL: #45659 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com> Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com> Reviewed-By: Tierney Cyren <hello@bnb.im>
1 parent 75dbce9 commit e2caf7c

26 files changed

+321
-367
lines changed

lib/buffer.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ const {
7878
isInsideNodeModules,
7979
lazyDOMException,
8080
normalizeEncoding,
81-
kIsEncodingSymbol
81+
kIsEncodingSymbol,
82+
defineLazyProperties,
8283
} = require('internal/util');
8384
const {
8485
isAnyArrayBuffer,
@@ -121,15 +122,6 @@ const {
121122
createUnsafeBuffer
122123
} = require('internal/buffer');
123124

124-
const {
125-
Blob,
126-
resolveObjectURL,
127-
} = require('internal/blob');
128-
129-
const {
130-
File,
131-
} = require('internal/file');
132-
133125
FastBuffer.prototype.constructor = Buffer;
134126
Buffer.prototype = FastBuffer.prototype;
135127
addBufferPrototypeMethods(Buffer.prototype);
@@ -1323,9 +1315,6 @@ function atob(input) {
13231315
}
13241316

13251317
module.exports = {
1326-
Blob,
1327-
File,
1328-
resolveObjectURL,
13291318
Buffer,
13301319
SlowBuffer,
13311320
transcode,
@@ -1352,3 +1341,14 @@ ObjectDefineProperties(module.exports, {
13521341
set(val) { INSPECT_MAX_BYTES = val; }
13531342
}
13541343
});
1344+
1345+
defineLazyProperties(
1346+
module.exports,
1347+
'internal/blob',
1348+
['Blob', 'resolveObjectURL']
1349+
);
1350+
defineLazyProperties(
1351+
module.exports,
1352+
'internal/file',
1353+
['File']
1354+
);

lib/fs.js

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ const {
5757

5858
const pathModule = require('path');
5959
const { isArrayBufferView } = require('internal/util/types');
60-
const nonNativeWatcher = require('internal/fs/recursive_watch');
6160

6261
// We need to get the statValues from the binding at the callsite since
6362
// it's re-initialized after deserialization.
@@ -84,6 +83,7 @@ const {
8483
custom: kCustomPromisifiedSymbol,
8584
},
8685
SideEffectFreeRegExpPrototypeExec,
86+
defineLazyProperties,
8787
} = require('internal/util');
8888
const {
8989
constants: {
@@ -119,11 +119,6 @@ const {
119119
validateStringAfterArrayBufferView,
120120
warnOnNonPortableTemplate
121121
} = require('internal/fs/utils');
122-
const {
123-
Dir,
124-
opendir,
125-
opendirSync
126-
} = require('internal/fs/dir');
127122
const {
128123
CHAR_FORWARD_SLASH,
129124
CHAR_BACKWARD_SLASH,
@@ -140,9 +135,6 @@ const {
140135
validateString,
141136
} = require('internal/validators');
142137

143-
const watchers = require('internal/fs/watchers');
144-
const ReadFileContext = require('internal/fs/read_file_context');
145-
146138
let truncateWarn = true;
147139
let fs;
148140

@@ -379,6 +371,7 @@ function checkAborted(signal, callback) {
379371
function readFile(path, options, callback) {
380372
callback = maybeCallback(callback || options);
381373
options = getOptions(options, { flag: 'r' });
374+
const ReadFileContext = require('internal/fs/read_file_context');
382375
const context = new ReadFileContext(callback, options.encoding);
383376
context.isUserFd = isFd(path); // File descriptor ownership
384377

@@ -2298,11 +2291,12 @@ function watch(filename, options, listener) {
22982291
if (options.recursive === undefined) options.recursive = false;
22992292

23002293
let watcher;
2301-
2294+
const watchers = require('internal/fs/watchers');
23022295
// TODO(anonrig): Remove non-native watcher when/if libuv supports recursive.
23032296
// As of November 2022, libuv does not support recursive file watch on all platforms,
23042297
// e.g. Linux due to the limitations of inotify.
23052298
if (options.recursive && !isOSX && !isWindows) {
2299+
const nonNativeWatcher = require('internal/fs/recursive_watch');
23062300
watcher = new nonNativeWatcher.FSWatcher(options);
23072301
watcher[watchers.kFSWatchStart](filename);
23082302
} else {
@@ -2370,7 +2364,7 @@ function watchFile(filename, options, listener) {
23702364
validateFunction(listener, 'listener');
23712365

23722366
stat = statWatchers.get(filename);
2373-
2367+
const watchers = require('internal/fs/watchers');
23742368
if (stat === undefined) {
23752369
stat = new watchers.StatWatcher(options.bigint);
23762370
stat[watchers.kFSStatWatcherStart](filename,
@@ -2396,7 +2390,7 @@ function unwatchFile(filename, listener) {
23962390
const stat = statWatchers.get(filename);
23972391

23982392
if (stat === undefined) return;
2399-
2393+
const watchers = require('internal/fs/watchers');
24002394
if (typeof listener === 'function') {
24012395
const beforeListenerCount = stat.listenerCount('change');
24022396
stat.removeListener('change', listener);
@@ -3000,8 +2994,6 @@ module.exports = fs = {
30002994
mkdtempSync,
30012995
open,
30022996
openSync,
3003-
opendir,
3004-
opendirSync,
30052997
readdir,
30062998
readdirSync,
30072999
read,
@@ -3039,7 +3031,6 @@ module.exports = fs = {
30393031
writeSync,
30403032
writev,
30413033
writevSync,
3042-
Dir,
30433034
Dirent,
30443035
Stats,
30453036

@@ -3085,6 +3076,12 @@ module.exports = fs = {
30853076
_toUnixTimestamp: toUnixTimestamp
30863077
};
30873078

3079+
defineLazyProperties(
3080+
fs,
3081+
'internal/fs/dir',
3082+
['Dir', 'opendir', 'opendirSync']
3083+
);
3084+
30883085
ObjectDefineProperties(fs, {
30893086
F_OK: { __proto__: null, enumerable: true, value: F_OK || 0 },
30903087
R_OK: { __proto__: null, enumerable: true, value: R_OK || 0 },

lib/internal/async_hooks.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ const {
1010

1111
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
1212

13-
const promiseHooks = require('internal/promise_hooks');
14-
1513
const async_wrap = internalBinding('async_wrap');
1614
const { setCallbackTrampoline } = async_wrap;
1715
/* async_hook_fields is a Uint32Array wrapping the uint32_t array of
@@ -384,6 +382,7 @@ function updatePromiseHookMode() {
384382
initHook = destroyTracking;
385383
}
386384
if (stopPromiseHook) stopPromiseHook();
385+
const promiseHooks = require('internal/promise_hooks');
387386
stopPromiseHook = promiseHooks.createHook({
388387
init: initHook,
389388
before: promiseBeforeHook,

lib/internal/bootstrap/browser.js

Lines changed: 62 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ const {
99
defineOperation,
1010
exposeInterface,
1111
lazyDOMExceptionClass,
12+
defineLazyProperties,
13+
defineReplaceableLazyAttribute,
14+
exposeLazyInterfaces,
1215
} = require('internal/util');
1316
const config = internalBinding('config');
1417

@@ -28,61 +31,39 @@ exposeGetterAndSetter(globalThis,
2831
exposeInterface(globalThis, 'DOMException', value);
2932
});
3033

31-
const {
32-
TextEncoder, TextDecoder
33-
} = require('internal/encoding');
34-
// https://encoding.spec.whatwg.org/#textencoder
35-
exposeInterface(globalThis, 'TextEncoder', TextEncoder);
36-
// https://encoding.spec.whatwg.org/#textdecoder
37-
exposeInterface(globalThis, 'TextDecoder', TextDecoder);
38-
39-
const {
40-
AbortController,
41-
AbortSignal,
42-
} = require('internal/abort_controller');
43-
exposeInterface(globalThis, 'AbortController', AbortController);
44-
exposeInterface(globalThis, 'AbortSignal', AbortSignal);
45-
46-
const {
47-
EventTarget,
48-
Event,
49-
} = require('internal/event_target');
50-
exposeInterface(globalThis, 'EventTarget', EventTarget);
51-
exposeInterface(globalThis, 'Event', Event);
52-
const {
53-
MessageChannel,
54-
MessagePort,
55-
MessageEvent,
56-
} = require('internal/worker/io');
57-
exposeInterface(globalThis, 'MessageChannel', MessageChannel);
58-
exposeInterface(globalThis, 'MessagePort', MessagePort);
59-
exposeInterface(globalThis, 'MessageEvent', MessageEvent);
60-
6134
// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope
6235
const timers = require('timers');
6336
defineOperation(globalThis, 'clearInterval', timers.clearInterval);
6437
defineOperation(globalThis, 'clearTimeout', timers.clearTimeout);
6538
defineOperation(globalThis, 'setInterval', timers.setInterval);
6639
defineOperation(globalThis, 'setTimeout', timers.setTimeout);
6740

68-
const buffer = require('buffer');
69-
defineOperation(globalThis, 'atob', buffer.atob);
70-
defineOperation(globalThis, 'btoa', buffer.btoa);
71-
41+
// Lazy ones.
42+
exposeLazyInterfaces(globalThis, 'internal/abort_controller', [
43+
'AbortController', 'AbortSignal',
44+
]);
45+
exposeLazyInterfaces(globalThis, 'internal/event_target', [
46+
'EventTarget', 'Event',
47+
]);
48+
exposeLazyInterfaces(globalThis, 'internal/worker/io', [
49+
'MessageChannel', 'MessagePort', 'MessageEvent',
50+
]);
51+
defineLazyProperties(globalThis, 'buffer', ['atob', 'btoa']);
7252
// https://www.w3.org/TR/FileAPI/#dfn-Blob
73-
exposeInterface(globalThis, 'Blob', buffer.Blob);
74-
53+
exposeLazyInterfaces(globalThis, 'internal/blob', ['Blob']);
7554
// https://www.w3.org/TR/hr-time-2/#the-performance-attribute
76-
const perf_hooks = require('perf_hooks');
77-
exposeInterface(globalThis, 'Performance', perf_hooks.Performance);
78-
exposeInterface(globalThis, 'PerformanceEntry', perf_hooks.PerformanceEntry);
79-
exposeInterface(globalThis, 'PerformanceMark', perf_hooks.PerformanceMark);
80-
exposeInterface(globalThis, 'PerformanceMeasure', perf_hooks.PerformanceMeasure);
81-
exposeInterface(globalThis, 'PerformanceObserver', perf_hooks.PerformanceObserver);
82-
exposeInterface(globalThis, 'PerformanceObserverEntryList', perf_hooks.PerformanceObserverEntryList);
83-
exposeInterface(globalThis, 'PerformanceResourceTiming', perf_hooks.PerformanceResourceTiming);
84-
defineReplaceableAttribute(globalThis, 'performance',
85-
perf_hooks.performance);
55+
exposeLazyInterfaces(globalThis, 'perf_hooks', [
56+
'Performance', 'PerformanceEntry', 'PerformanceMark', 'PerformanceMeasure',
57+
'PerformanceObserver', 'PerformanceObserverEntryList', 'PerformanceResourceTiming',
58+
]);
59+
60+
defineReplaceableLazyAttribute(globalThis, 'perf_hooks', ['performance']);
61+
62+
// https://encoding.spec.whatwg.org/#textencoder
63+
// https://encoding.spec.whatwg.org/#textdecoder
64+
exposeLazyInterfaces(globalThis,
65+
'internal/encoding',
66+
['TextEncoder', 'TextDecoder']);
8667

8768
function createGlobalConsole() {
8869
const consoleFromNode =
@@ -120,86 +101,43 @@ function exposeGetterAndSetter(target, name, getter, setter = undefined) {
120101
});
121102
}
122103

123-
// https://webidl.spec.whatwg.org/#Replaceable
124-
function defineReplaceableAttribute(target, name, value) {
125-
let slot = value;
126-
127-
// https://webidl.spec.whatwg.org/#dfn-attribute-getter
128-
function get() {
129-
return slot;
130-
}
131-
ObjectDefineProperty(get, 'name', {
132-
__proto__: null,
133-
value: `get ${name}`,
134-
});
135-
136-
function set(value) {
137-
slot = value;
138-
}
139-
ObjectDefineProperty(set, 'name', {
140-
__proto__: null,
141-
value: `set ${name}`,
142-
});
143-
144-
ObjectDefineProperty(target, name, {
145-
__proto__: null,
146-
enumerable: true,
147-
configurable: true,
148-
get,
149-
set,
150-
});
151-
}
152-
153104
// Web Streams API
154-
const {
155-
TransformStream,
156-
TransformStreamDefaultController,
157-
} = require('internal/webstreams/transformstream');
158-
159-
const {
160-
WritableStream,
161-
WritableStreamDefaultController,
162-
WritableStreamDefaultWriter,
163-
} = require('internal/webstreams/writablestream');
105+
exposeLazyInterfaces(
106+
globalThis,
107+
'internal/webstreams/transformstream',
108+
['TransformStream', 'TransformStreamDefaultController']);
164109

165-
const {
166-
ReadableStream,
167-
ReadableStreamDefaultReader,
168-
ReadableStreamBYOBReader,
169-
ReadableStreamBYOBRequest,
170-
ReadableByteStreamController,
171-
ReadableStreamDefaultController,
172-
} = require('internal/webstreams/readablestream');
110+
exposeLazyInterfaces(
111+
globalThis,
112+
'internal/webstreams/writablestream',
113+
['WritableStream', 'WritableStreamDefaultController', 'WritableStreamDefaultWriter']);
173114

174-
const {
175-
ByteLengthQueuingStrategy,
176-
CountQueuingStrategy,
177-
} = require('internal/webstreams/queuingstrategies');
115+
exposeLazyInterfaces(
116+
globalThis,
117+
'internal/webstreams/readablestream',
118+
[
119+
'ReadableStream', 'ReadableStreamDefaultReader',
120+
'ReadableStreamBYOBReader', 'ReadableStreamBYOBRequest',
121+
'ReadableByteStreamController', 'ReadableStreamDefaultController',
122+
]);
123+
124+
exposeLazyInterfaces(
125+
globalThis,
126+
'internal/webstreams/queuingstrategies',
127+
[
128+
'ByteLengthQueuingStrategy', 'CountQueuingStrategy',
129+
]);
178130

179-
const {
180-
TextEncoderStream,
181-
TextDecoderStream,
182-
} = require('internal/webstreams/encoding');
131+
exposeLazyInterfaces(
132+
globalThis,
133+
'internal/webstreams/encoding',
134+
[
135+
'TextEncoderStream', 'TextDecoderStream',
136+
]);
183137

184-
const {
185-
CompressionStream,
186-
DecompressionStream,
187-
} = require('internal/webstreams/compression');
188-
189-
exposeInterface(globalThis, 'ReadableStream', ReadableStream);
190-
exposeInterface(globalThis, 'ReadableStreamDefaultReader', ReadableStreamDefaultReader);
191-
exposeInterface(globalThis, 'ReadableStreamBYOBReader', ReadableStreamBYOBReader);
192-
exposeInterface(globalThis, 'ReadableStreamBYOBRequest', ReadableStreamBYOBRequest);
193-
exposeInterface(globalThis, 'ReadableByteStreamController', ReadableByteStreamController);
194-
exposeInterface(globalThis, 'ReadableStreamDefaultController', ReadableStreamDefaultController);
195-
exposeInterface(globalThis, 'TransformStream', TransformStream);
196-
exposeInterface(globalThis, 'TransformStreamDefaultController', TransformStreamDefaultController);
197-
exposeInterface(globalThis, 'WritableStream', WritableStream);
198-
exposeInterface(globalThis, 'WritableStreamDefaultWriter', WritableStreamDefaultWriter);
199-
exposeInterface(globalThis, 'WritableStreamDefaultController', WritableStreamDefaultController);
200-
exposeInterface(globalThis, 'ByteLengthQueuingStrategy', ByteLengthQueuingStrategy);
201-
exposeInterface(globalThis, 'CountQueuingStrategy', CountQueuingStrategy);
202-
exposeInterface(globalThis, 'TextEncoderStream', TextEncoderStream);
203-
exposeInterface(globalThis, 'TextDecoderStream', TextDecoderStream);
204-
exposeInterface(globalThis, 'CompressionStream', CompressionStream);
205-
exposeInterface(globalThis, 'DecompressionStream', DecompressionStream);
138+
exposeLazyInterfaces(
139+
globalThis,
140+
'internal/webstreams/compression',
141+
[
142+
'CompressionStream', 'DecompressionStream',
143+
]);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy