-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
Expand file tree
/
Copy pathtranslators.js
More file actions
648 lines (583 loc) Β· 24.6 KB
/
translators.js
File metadata and controls
648 lines (583 loc) Β· 24.6 KB
Edit and raw actions
OlderNewer
Β
1
'use strict';
2
3
const {
4
ArrayPrototypePush,
5
FunctionPrototypeCall,
6
JSONParse,
7
ObjectAssign,
8
ObjectPrototypeHasOwnProperty,
9
SafeMap,
10
SafeSet,
11
SafeWeakMap,
12
StringPrototypeIncludes,
13
StringPrototypeReplaceAll,
14
StringPrototypeSlice,
15
StringPrototypeStartsWith,
16
globalThis,
17
} = primordials;
18
19
const {
20
compileFunctionForCJSLoader,
21
} = internalBinding('contextify');
22
23
const { BuiltinModule } = require('internal/bootstrap/realm');
24
const assert = require('internal/assert');
25
const fs = require('fs');
26
const { dirname, extname } = require('path');
27
const {
28
assertBufferSource,
29
loadBuiltinModule,
30
stringify,
31
stripBOM,
32
urlToFilename,
33
} = require('internal/modules/helpers');
34
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
35
const {
36
kIsCachedByESMLoader,
37
Module: CJSModule,
38
wrapModuleLoad,
39
kModuleSource,
40
kModuleExport,
41
kModuleExportNames,
42
findLongestRegisteredExtension,
43
resolveForCJSWithHooks,
44
loadSourceForCJSWithHooks,
45
populateCJSExportsFromESM,
46
} = require('internal/modules/cjs/loader');
47
const { fileURLToPath, pathToFileURL, URL } = require('internal/url');
48
let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {
49
debug = fn;
50
});
51
const { emitExperimentalWarning, kEmptyObject, setOwnProperty, isWindows } = require('internal/util');
52
const {
53
ERR_INVALID_RETURN_PROPERTY_VALUE,
54
ERR_UNKNOWN_BUILTIN_MODULE,
55
} = require('internal/errors').codes;
56
const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache');
57
const moduleWrap = internalBinding('module_wrap');
58
const { ModuleWrap, kEvaluationPhase } = moduleWrap;
59
60
const { getSourceSync } = require('internal/modules/esm/load');
61
62
const { parse: cjsParse } = internalBinding('cjs_lexer');
63
64
const translators = new SafeMap();
65
exports.translators = translators;
66
67
/**
68
* Converts a URL to a file path if the URL protocol is 'file:'.
69
* @param {string} url - The URL to convert.
70
* @returns {string|URL}
71
*/
72
function errPath(url) {
73
const parsed = new URL(url);
74
if (parsed.protocol === 'file:') {
75
return fileURLToPath(parsed);
76
}
77
return url;
78
}
79
80
// Strategy for loading a standard JavaScript module.
81
translators.set('module', function moduleStrategy(url, translateContext, parentURL) {
82
let { source } = translateContext;
83
const isMain = (parentURL === undefined);
84
assertBufferSource(source, true, 'load');
85
source = stringify(source);
86
debug(`Translating StandardModule ${url}`, translateContext);
87
const {
88
compileSourceTextModule, SourceTextModuleTypes: { kUser },
89
} = require('internal/modules/esm/utils');
90
const context = isMain ? { isMain } : undefined;
91
const module = compileSourceTextModule(url, source, kUser, context);
92
return module;
93
});
94
95
const { requestTypes: { kRequireInImportedCJS } } = require('internal/modules/esm/utils');
96
const kShouldSkipModuleHooks = { __proto__: null, shouldSkipModuleHooks: true };
97
const kShouldNotSkipModuleHooks = { __proto__: null, shouldSkipModuleHooks: false };
98
99
/**
100
* Loads a CommonJS module via the ESM Loader sync CommonJS translator.
101
* This translator creates its own version of the `require` function passed into CommonJS modules.
102
* Any monkey patches applied to the CommonJS Loader will not affect this module.
103
* Any `require` calls in this module will load all children in the same way.
104
* @param {import('internal/modules/cjs/loader').Module} module - The module to load.
105
* @param {string} source - The source code of the module.
106
* @param {string} url - The URL of the module.
107
* @param {string} filename - The filename of the module.
108
* @param {boolean} isMain - Whether the module is the entrypoint
109
*/
110
function loadCJSModule(module, source, url, filename, isMain) {
111
// Use the full URL as the V8 resource name so that any search params
112
// (e.g. ?node-test-mock) are preserved in coverage reports.
113
const compileResult = compileFunctionForCJSLoader(source, url, false /* is_sea_main */, false);
114
115
const { function: compiledWrapper, sourceMapURL, sourceURL } = compileResult;
116
// Cache the source map for the cjs module if present.
117
if (sourceMapURL) {
118
maybeCacheSourceMap(url, source, module, false, sourceURL, sourceMapURL);
119
}
120
const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
121
const __dirname = dirname(filename);
122
// eslint-disable-next-line func-name-matching,func-style
123
const requireFn = function require(specifier) {
124
let importAttributes = kEmptyObject;
125
if (!StringPrototypeStartsWith(specifier, 'node:') && !BuiltinModule.normalizeRequirableId(specifier)) {
126
// TODO: do not depend on the monkey-patchable CJS loader here.
127
const path = CJSModule._resolveFilename(specifier, module);
128
switch (extname(path)) {
129
case '.json':
130
importAttributes = { __proto__: null, type: 'json' };
131
break;
132
case '.node':
133
// If it gets here in the translators, the hooks must have already been invoked
134
// in the loader. Skip them in the synthetic module evaluation step.
135
return wrapModuleLoad(specifier, module, false, kShouldSkipModuleHooks);
136
default:
137
// fall through
138
}
139
specifier = `${pathToFileURL(path)}`;
140
}
141
142
// NOTE: This re-invented require() is only used on the loader-hook worker thread.
143
// On the main thread, the authentic require() is used instead (fixed by #60380).
144
const request = { specifier, attributes: importAttributes, phase: kEvaluationPhase, __proto__: null };
145
const job = cascadedLoader.getOrCreateModuleJob(url, request, kRequireInImportedCJS);
146
job.runSync();
147
let mod = cjsCache.get(job.url);
148
assert(job.module, `Imported CJS module ${url} failed to load module ${job.url} using require() due to race condition`);
149
150
if (job.module.synthetic) {
151
assert(mod, `Imported CJS module ${url} failed to load module ${job.url} using require() due to missed cache`);
152
return mod.exports;
153
}
154
155
// The module being required is a source text module.
156
if (!mod) {
157
mod = cjsEmplaceModuleCacheEntry(job.url);
158
cjsCache.set(job.url, mod);
159
}
160
// The module has been cached by the re-invented require. Update the exports object
161
// from the namespace object and return the evaluated exports.
162
if (!mod.loaded) {
163
debug('populateCJSExportsFromESM from require(esm) in imported CJS', url, mod, job.module);
164
populateCJSExportsFromESM(mod, job.module, job.module.getNamespace());
165
mod.loaded = true;
166
}
167
return mod.exports;
168
};
169
setOwnProperty(requireFn, 'resolve', function resolve(specifier) {
170
if (!StringPrototypeStartsWith(specifier, 'node:')) {
171
const {
172
filename, url: resolvedURL,
173
} = resolveForCJSWithHooks(specifier, module, false, kShouldNotSkipModuleHooks);
174
if (specifier !== filename) {
175
specifier = resolvedURL ?? `${pathToFileURL(filename)}`;
176
}
177
}
178
179
const request = { specifier, __proto__: null, attributes: kEmptyObject };
180
// Skip sync hooks in resolveSync since resolveForCJSWithHooks already ran them above.
181
const { url: resolvedURL } = cascadedLoader.resolveSync(url, request, /* shouldSkipSyncHooks */ true);
182
return urlToFilename(resolvedURL);
183
});
184
setOwnProperty(requireFn, 'main', process.mainModule);
185
186
FunctionPrototypeCall(compiledWrapper, module.exports,
187
module.exports, requireFn, module, filename, __dirname);
188
setOwnProperty(module, 'loaded', true);
189
}
190
191
// TODO: can we use a weak map instead?
192
const cjsCache = new SafeMap();
193
194
/**
195
* Creates a ModuleWrap object for a CommonJS module.
196
* @param {string} url - The URL of the module.
197
* @param {{ format: ModuleFormat, source: ModuleSource }} translateContext Context for the translator
198
* @param {string|undefined} parentURL URL of the module initiating the module loading for the first time.
199
* Undefined if it's the entry point.
200
* @param {typeof loadCJSModule} [loadCJS] - The function to load the CommonJS module.
201
* @returns {ModuleWrap} The ModuleWrap object for the CommonJS module.
202
*/
203
function createCJSModuleWrap(url, translateContext, parentURL, loadCJS = loadCJSModule) {
204
debug(`Translating CJSModule ${url}`, translateContext);
205
206
const { format: sourceFormat } = translateContext;
207
let { source } = translateContext;
208
const isMain = (parentURL === undefined);
209
const filename = urlToFilename(url);
210
// In case the source was not provided by the `load` step, we need fetch it now.
211
source = stringify(source ?? getSourceSync(new URL(url)).source);
212
213
const { exportNames, module } = cjsPreparseModuleExports(filename, source, sourceFormat);
214
cjsCache.set(url, module);
215
216
const wrapperNames = [...exportNames];
217
if (!exportNames.has('default')) {
218
ArrayPrototypePush(wrapperNames, 'default');
219
}
220
if (!exportNames.has('module.exports')) {
221
ArrayPrototypePush(wrapperNames, 'module.exports');
222
}
223
224
if (isMain) {
225
setOwnProperty(process, 'mainModule', module);
226
}
227
228
return new ModuleWrap(url, undefined, wrapperNames, function() {
229
debug(`Loading CJSModule ${url}`);
230
231
if (!module.loaded) {
232
loadCJS(module, source, url, filename, !!isMain);
233
}
234
235
let exports;
236
if (module[kModuleExport] !== undefined) {
237
exports = module[kModuleExport];
238
module[kModuleExport] = undefined;
239
} else {
240
({ exports } = module);
241
}
242
for (const exportName of exportNames) {
243
if (exportName === 'default' || exportName === 'module.exports' ||
244
!ObjectPrototypeHasOwnProperty(exports, exportName)) {
245
continue;
246
}
247
// We might trigger a getter -> dont fail.
248
let value;
249
try {
250
value = exports[exportName];
251
} catch {
252
// Continue regardless of error.
253
}
254
this.setExport(exportName, value);
255
}
256
this.setExport('default', exports);
257
this.setExport('module.exports', exports);
258
}, module);
259
}
260
261
/**
262
* Creates a ModuleWrap object for a CommonJS module without source texts.
263
* @param {string} url - The URL of the module.
264
* @param {string|undefined} parentURL - URL of the parent module, if any.
265
* @returns {ModuleWrap} The ModuleWrap object for the CommonJS module.
266
*/
267
function createCJSNoSourceModuleWrap(url, parentURL) {
268
debug(`Translating CJSModule without source ${url}`);
269
const isMain = (parentURL === undefined);
270
271
const filename = urlToFilename(url);
272
273
const module = cjsEmplaceModuleCacheEntry(filename);
274
cjsCache.set(url, module);
275
276
if (isMain) {
277
setOwnProperty(process, 'mainModule', module);
278
}
279
280
// Addon export names are not known until the addon is loaded.
281
const exportNames = ['default', 'module.exports'];
282
return new ModuleWrap(url, undefined, exportNames, function evaluationCallback() {
283
debug(`Loading CJSModule ${url}`);
284
285
if (!module.loaded) {
286
// If it gets here in the translators, the hooks must have already been invoked
287
// in the loader. Skip them in the synthetic module evaluation step.
288
wrapModuleLoad(filename, null, isMain, kShouldSkipModuleHooks);
289
}
290
291
/** @type {import('./loader').ModuleExports} */
292
let exports;
293
if (module[kModuleExport] !== undefined) {
294
exports = module[kModuleExport];
295
module[kModuleExport] = undefined;
296
} else {
297
({ exports } = module);
298
}
299
300
this.setExport('default', exports);
301
this.setExport('module.exports', exports);
302
}, module);
303
}
304
305
translators.set('commonjs-sync', function requireCommonJS(url, translateContext, parentURL) {
306
return createCJSModuleWrap(url, translateContext, parentURL, loadCJSModuleWithModuleLoad);
307
});
308
309
// Handle CommonJS modules referenced by `require` calls.
310
// This translator function must be sync, as `require` is sync.
311
translators.set('require-commonjs', (url, translateContext, parentURL) => {
312
return createCJSModuleWrap(url, translateContext, parentURL);
313
});
314
315
// Handle CommonJS modules referenced by `require` calls.
316
// This translator function must be sync, as `require` is sync.
317
translators.set('require-commonjs-typescript', (url, translateContext, parentURL) => {
318
translateContext.source = stripTypeScriptModuleTypes(stringify(translateContext.source), url);
319
return createCJSModuleWrap(url, translateContext, parentURL);
320
});
321
322
// This goes through Module._load to accommodate monkey-patchers.
323
function loadCJSModuleWithModuleLoad(module, source, url, filename, isMain) {
324
assert(module === CJSModule._cache[filename]);
325
// If it gets here in the translators, the hooks must have already been invoked
326
// in the loader. Skip them in the synthetic module evaluation step.
327
wrapModuleLoad(filename, undefined, isMain, kShouldSkipModuleHooks);
328
}
329
330
// Handle CommonJS modules referenced by `import` statements or expressions,
331
// or as the initial entry point when the ESM loader handles a CommonJS entry.
332
translators.set('commonjs', function commonjsStrategy(url, translateContext, parentURL) {
333
// For backward-compatibility, it's possible to return a nullish value for
334
// CJS source associated with a `file:` URL - that usually means the source is not
335
// customized (is loaded by default load) or the hook author wants it to be reloaded
336
// through CJS routine. In this case, the source is obtained by calling the
337
// monkey-patchable CJS loader.
338
// TODO(joyeecheung): just use wrapModuleLoad and let the CJS loader
339
// invoke the off-thread hooks. Use a special parent to avoid invoking in-thread
340
// hooks twice.
341
const shouldReloadByCJSLoader = (translateContext.shouldBeReloadedByCJSLoader || translateContext.source == null);
342
const cjsLoader = shouldReloadByCJSLoader ? loadCJSModuleWithModuleLoad : loadCJSModule;
343
344
try {
345
// We still need to read the FS to detect the exports.
346
// If you are reading this code to figure out how to patch Node.js module loading
347
// behavior - DO NOT depend on the patchability in new code: Node.js
348
// internals may stop going through the JavaScript fs module entirely.
349
// Prefer module.registerHooks() or other more formal fs hooks released in the future.
350
translateContext.source ??= fs.readFileSync(new URL(url), 'utf8');
351
} catch {
352
// Continue regardless of error.
353
}
354
return createCJSModuleWrap(url, translateContext, parentURL, cjsLoader);
355
});
356
357
/**
358
* Get or create an entry in the CJS module cache for the given filename.
359
* @param {string} filename CJS module filename
360
* @param {CJSModule} parent The parent CJS module
361
* @returns {CJSModule} the cached CJS module entry
362
*/
363
function cjsEmplaceModuleCacheEntry(filename, parent) {
364
// TODO: Do we want to keep hitting the user mutable CJS loader here?
365
let cjsMod = CJSModule._cache[filename];
366
if (cjsMod) {
367
return cjsMod;
368
}
369
370
cjsMod = new CJSModule(filename, parent);
371
cjsMod.filename = filename;
372
cjsMod.paths = CJSModule._nodeModulePaths(cjsMod.path);
373
cjsMod[kIsCachedByESMLoader] = true;
374
CJSModule._cache[filename] = cjsMod;
375
376
return cjsMod;
377
}
378
379
/**
380
* Pre-parses a CommonJS module's exports and re-exports.
381
* @param {string} filename - The filename of the module.
382
* @param {string} [source] - The source code of the module.
383
* @param {string} [format]
384
* @returns {{module: CJSModule, exportNames: string[]}}
385
*/
386
function cjsPreparseModuleExports(filename, source, format) {
387
const module = cjsEmplaceModuleCacheEntry(filename);
388
if (module[kModuleExportNames] !== undefined) {
389
return { module, exportNames: module[kModuleExportNames] };
390
}
391
392
if (source === undefined) {
393
({ source } = loadSourceForCJSWithHooks(module, filename, format));
394
}
395
module[kModuleSource] = source;
396
397
debug(`Preparsing exports of ${filename}`);
398
const { 0: exportNames, 1: reexports } = cjsParse(source);
399
400
// Set first for cycles.
401
module[kModuleExportNames] = exportNames;
402
403
// If there are any re-exports e.g. `module.exports = { ...require(...) }`,
404
// pre-parse the dependencies to find transitively exported names.
405
if (reexports.length) {
406
module.filename ??= filename;
407
module.paths ??= CJSModule._nodeModulePaths(dirname(filename));
408
409
for (let i = 0; i < reexports.length; i++) {
410
debug(`Preparsing re-exports of '${filename}'`);
411
const reexport = reexports[i];
412
let resolved;
413
let format;
414
try {
415
({ format, filename: resolved } = resolveForCJSWithHooks(reexport, module, false, kShouldNotSkipModuleHooks));
416
} catch (e) {
417
debug(`Failed to resolve '${reexport}', skipping`, e);
418
continue;
419
}
420
421
if (format === 'commonjs' ||
422
(!BuiltinModule.normalizeRequirableId(resolved) && findLongestRegisteredExtension(resolved) === '.js')) {
423
const { exportNames: reexportNames } = cjsPreparseModuleExports(resolved, undefined, format);
424
for (const name of reexportNames) {
425
exportNames.add(name);
426
}
427
}
428
}
429
}
430
431
return { module, exportNames };
432
}
433
434
// Strategy for loading a node builtin CommonJS module that isn't
435
// through normal resolution
436
translators.set('builtin', function builtinStrategy(url, translateContext) {
437
debug(`Translating BuiltinModule ${url}`, translateContext);
438
// Slice 'node:' scheme
439
const id = StringPrototypeSlice(url, 5);
440
const module = loadBuiltinModule(id, url);
441
cjsCache.set(url, module);
442
if (!StringPrototypeStartsWith(url, 'node:') || !module) {
443
throw new ERR_UNKNOWN_BUILTIN_MODULE(url);
444
}
445
debug(`Loading BuiltinModule ${url}`);
446
return module.getESMFacade();
447
});
448
449
// Strategy for loading a JSON file
450
translators.set('json', function jsonStrategy(url, translateContext) {
451
let { source } = translateContext;
452
assertBufferSource(source, true, 'load');
453
debug(`Loading JSONModule ${url}`);
454
const pathname = StringPrototypeStartsWith(url, 'file:') ?
455
fileURLToPath(url) : null;
456
const shouldCheckAndPopulateCJSModuleCache =
457
// We want to involve the CJS loader cache only for `file:` URL with no search query and no hash.
458
pathname && !StringPrototypeIncludes(url, '?') && !StringPrototypeIncludes(url, '#');
459
let modulePath;
460
let module;
461
if (shouldCheckAndPopulateCJSModuleCache) {
462
modulePath = isWindows ?
463
StringPrototypeReplaceAll(pathname, '/', '\\') : pathname;
464
module = CJSModule._cache[modulePath];
465
if (module?.loaded) {
466
const exports = module.exports;
467
return new ModuleWrap(url, undefined, ['default'], function() {
468
this.setExport('default', exports);
469
});
470
}
471
}
472
source = stringify(source);
473
if (shouldCheckAndPopulateCJSModuleCache) {
474
// A require call could have been called on the same file during loading and
475
// that resolves synchronously. To make sure we always return the identical
476
// export, we have to check again if the module already exists or not.
477
// TODO: remove CJS loader from here as well.
478
module = CJSModule._cache[modulePath];
479
if (module?.loaded) {
480
const exports = module.exports;
481
return new ModuleWrap(url, undefined, ['default'], function() {
482
this.setExport('default', exports);
483
});
484
}
485
}
486
try {
487
const exports = JSONParse(stripBOM(source));
488
module = {
489
exports,
490
loaded: true,
491
};
492
} catch (err) {
493
// TODO (BridgeAR): We could add a NodeCore error that wraps the JSON
494
// parse error instead of just manipulating the original error message.
495
// That would allow to add further properties and maybe additional
496
// debugging information.
497
err.message = errPath(url) + ': ' + err.message;
498
throw err;
499
}
500
if (shouldCheckAndPopulateCJSModuleCache) {
501
CJSModule._cache[modulePath] = module;
502
}
503
cjsCache.set(url, module);
504
return new ModuleWrap(url, undefined, ['default'], function() {
505
debug(`Parsing JSONModule ${url}`);
506
this.setExport('default', module.exports);
507
});
508
});
509
510
// Strategy for loading a wasm module
511
// This logic should collapse into WebAssembly Module Record in future.
512
/**
513
* @type {WeakMap<
514
* import('internal/modules/esm/utils').ModuleNamespaceObject,
515
* WebAssembly.Instance
516
* >} [[Instance]] slot proxy for WebAssembly Module Record
517
*/
518
const wasmInstances = new SafeWeakMap();
519
translators.set('wasm', function(url, translateContext) {
520
const { source } = translateContext;
521
// WebAssembly global is not available during snapshot building, so we need to get it lazily.
522
const { WebAssembly } = globalThis;
523
assertBufferSource(source, false, 'load');
524
525
debug(`Translating WASMModule ${url}`, translateContext);
526
527
let compiled;
528
try {
529
compiled = new WebAssembly.Module(source, {
530
builtins: ['js-string'],
531
importedStringConstants: 'wasm:js/string-constants',
532
});
533
} catch (err) {
534
err.message = errPath(url) + ': ' + err.message;
535
throw err;
536
}
537
538
const importsList = new SafeSet();
539
const wasmGlobalImports = [];
540
for (const impt of WebAssembly.Module.imports(compiled)) {
541
if (impt.kind === 'global') {
542
ArrayPrototypePush(wasmGlobalImports, impt);
543
}
544
// Prefix reservations per https://webassembly.github.io/esm-integration/js-api/index.html#parse-a-webassembly-module.
545
if (impt.module.startsWith('wasm-js:')) {
546
throw new WebAssembly.LinkError(`Invalid Wasm import "${impt.module}" in ${url}`);
547
}
548
if (impt.name.startsWith('wasm:') || impt.name.startsWith('wasm-js:')) {
549
throw new WebAssembly.LinkError(`Invalid Wasm import name "${impt.module}" in ${url}`);
550
}
551
importsList.add(impt.module);
552
}
553
554
const exportsList = new SafeSet();
555
const wasmGlobalExports = new SafeSet();
556
for (const expt of WebAssembly.Module.exports(compiled)) {
557
if (expt.kind === 'global') {
558
wasmGlobalExports.add(expt.name);
559
}
560
if (expt.name.startsWith('wasm:') || expt.name.startsWith('wasm-js:')) {
561
throw new WebAssembly.LinkError(`Invalid Wasm export name "${expt.name}" in ${url}`);
562
}
563
exportsList.add(expt.name);
564
}
565
566
const createDynamicModule = require('internal/modules/esm/create_dynamic_module');
567
568
const { module } = createDynamicModule([...importsList], [...exportsList], url, (reflect) => {
569
emitExperimentalWarning('Importing WebAssembly module instances');
570
for (const impt of importsList) {
571
const importNs = reflect.imports[impt];
572
const wasmInstance = wasmInstances.get(importNs);
573
if (wasmInstance) {
574
const wrappedModule = ObjectAssign({ __proto__: null }, reflect.imports[impt]);
575
for (const { module, name } of wasmGlobalImports) {
576
if (module !== impt) {
577
continue;
578
}
579
// Import of Wasm module global -> get direct WebAssembly.Global wrapped value.
580
// JS API validations otherwise remain the same.
581
wrappedModule[name] = wasmInstance[name];
582
}
583
reflect.imports[impt] = wrappedModule;
584
}
585
}
586
// In cycles importing unexecuted Wasm, wasmInstance will be undefined, which will fail during
587
// instantiation, since all bindings will be in the Temporal Deadzone (TDZ).
588
const { exports } = new WebAssembly.Instance(compiled, reflect.imports);
589
wasmInstances.set(module.getNamespace(), exports);
590
for (const expt of exportsList) {
591
let val = exports[expt];
592
// Unwrap WebAssembly.Global for JS bindings
593
if (wasmGlobalExports.has(expt)) {
594
try {
595
// v128 will throw in GetGlobalValue, see:
596
// https://webassembly.github.io/esm-integration/js-api/index.html#getglobalvalue
597
val = val.value;
598
} catch {
599
// v128 doesn't support ToJsValue() -> use undefined (ideally should stay in TDZ)
600
continue;
601
}
602
}
603
reflect.exports[expt].set(val);
604
}
605
});
606
// WebAssembly modules support source phase imports, to import the compiled module
607
// separate from the linked instance.
608
module.setModuleSourceObject(compiled);
609
return module;
610
});
611
612
// Strategy for loading a addon
613
translators.set('addon', function translateAddon(url, translateContext, parentURL) {
614
emitExperimentalWarning('Importing addons');
615
616
const { source } = translateContext;
617
// The addon must be loaded from file system with dlopen. Assert
618
// the source is null.
619
if (source !== null) {
620
throw new ERR_INVALID_RETURN_PROPERTY_VALUE(
621
'null',
622
'load',
623
'source',
624
source);
625
}
626
627
debug(`Translating addon ${url}`, translateContext);
628
629
return createCJSNoSourceModuleWrap(url, parentURL);
630
});
631
632
// Strategy for loading a commonjs TypeScript module
633
translators.set('commonjs-typescript', function(url, translateContext, parentURL) {
634
const { source } = translateContext;
635
assertBufferSource(source, true, 'load');
636
debug(`Translating TypeScript ${url}`, translateContext);
637
translateContext.source = stripTypeScriptModuleTypes(stringify(source), url);
638
return FunctionPrototypeCall(translators.get('commonjs'), this, url, translateContext, parentURL);
639
});
640
641
// Strategy for loading an esm TypeScript module
642
translators.set('module-typescript', function(url, translateContext, parentURL) {
643
const { source } = translateContext;
644
assertBufferSource(source, true, 'load');
645
debug(`Translating TypeScript ${url}`, translateContext);
646
translateContext.source = stripTypeScriptModuleTypes(stringify(source), url);
647
return FunctionPrototypeCall(translators.get('module'), this, url, translateContext, parentURL);
648
});