'use strict';
const {
ArrayPrototypePush,
FunctionPrototypeCall,
JSONParse,
ObjectAssign,
ObjectPrototypeHasOwnProperty,
SafeMap,
SafeSet,
SafeWeakMap,
StringPrototypeIncludes,
StringPrototypeReplaceAll,
StringPrototypeSlice,
StringPrototypeStartsWith,
Uint8Array,
globalThis,
} = primordials;
const {
compileFunctionForCJSLoader,
} = internalBinding('contextify');
const { BuiltinModule } = require('internal/bootstrap/realm');
const assert = require('internal/assert');
const { dirname, extname } = require('path');
const {
assertBufferSource,
loadBuiltinModule,
stringify,
stripBOM,
urlToFilename,
} = require('internal/modules/helpers');
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,
wrapModuleLoad,
kModuleSource,
kModuleExport,
kModuleExportNames,
findLongestRegisteredExtension,
resolveForCJSWithHooks,
loadSourceForCJSWithHooks,
populateCJSExportsFromESM,
} = require('internal/modules/cjs/loader');
const { fileURLToPath, pathToFileURL, URL } = require('internal/url');
const { isAnyArrayBuffer } = require('internal/util/types');
let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {
debug = fn;
});
const { emitExperimentalWarning, kEmptyObject, setOwnProperty, isWindows } = require('internal/util');
const {
ERR_INVALID_RETURN_PROPERTY_VALUE,
ERR_UNKNOWN_BUILTIN_MODULE,
ERR_WEBASSEMBLY_NOT_SUPPORTED,
} = require('internal/errors').codes;
const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache');
const moduleWrap = internalBinding('module_wrap');
const { ModuleWrap, kEvaluationPhase } = moduleWrap;
const { getSourceSync } = require('internal/modules/esm/load');
const { parse: cjsParse } = internalBinding('cjs_lexer');
const {
getWasmCompileCacheEntry,
saveWasmCompileCacheEntry,
} = internalBinding('modules');
const translators = new SafeMap();
exports.translators = translators;
/**
* Converts a URL to a file path if the URL protocol is 'file:'.
* @param {string} url - The URL to convert.
* @returns {string|URL}
*/
function errPath(url) {
const parsed = new URL(url);
if (parsed.protocol === 'file:') {
return fileURLToPath(parsed);
}
return url;
}
// Strategy for loading a standard JavaScript module.
translators.set('module', function moduleStrategy(url, translateContext, parentURL) {
let { source } = translateContext;
const isMain = (parentURL === undefined);
assertBufferSource(source, true, 'load');
source = stringify(source);
debug(`Translating StandardModule ${url}`, translateContext);
const {
compileSourceTextModule, SourceTextModuleTypes: { kUser },
} = require('internal/modules/esm/utils');
const context = isMain ? { isMain } : undefined;
const module = compileSourceTextModule(url, source, kUser, context);
return module;
});
const { requestTypes: { kRequireInImportedCJS } } = require('internal/modules/esm/utils');
const kShouldSkipModuleHooks = { __proto__: null, shouldSkipModuleHooks: true };
const kShouldNotSkipModuleHooks = { __proto__: null, shouldSkipModuleHooks: false };
/**
* This may be eventually removed when module.register() reaches end-of-life.
*
* Loads a CommonJS module via the ESM Loader sync CommonJS translator.
* This translator creates its own version of the `require` function passed into CommonJS modules.
* Any monkey patches applied to the CommonJS Loader will not affect this module.
* Any `require` calls in this module will load all children in the same way.
* @param {import('internal/modules/cjs/loader').Module} module - The module to load.
* @param {string} source - The source code of the module.
* @param {string} url - The URL of the module.
* @param {string} filename - The filename of the module.
* @param {boolean} isMain - Whether the module is the entrypoint
* @param {TranslateContext} translateContext Context for the translator
*/
function loadCJSModuleWithSpecialRequire(module, source, url, filename, isMain, translateContext) {
// Use the full URL as the V8 resource name so that any search params
// (e.g. ?node-test-mock) are preserved in coverage reports.
const compileResult = compileFunctionForCJSLoader(source, url, false /* is_sea_main */, false);
const { function: compiledWrapper, sourceMapURL, sourceURL } = compileResult;
// Cache the source map for the cjs module if present.
if (sourceMapURL) {
maybeCacheSourceMap(url, source, module, false, sourceURL, sourceMapURL);
}
const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
const __dirname = dirname(filename);
// eslint-disable-next-line node-core/func-name-matching,func-style
const requireFn = function require(specifier) {
let importAttributes = kEmptyObject;
if (!StringPrototypeStartsWith(specifier, 'node:') && !BuiltinModule.normalizeRequirableId(specifier)) {
// TODO: do not depend on the monkey-patchable CJS loader here.
const path = CJSModule._resolveFilename(specifier, module);
switch (extname(path)) {
case '.json':
importAttributes = { __proto__: null, type: 'json' };
break;
case '.node':
// If it gets here in the translators, the hooks must have already been invoked
// in the loader. Skip them in the synthetic module evaluation step.
return wrapModuleLoad(specifier, module, false, kShouldSkipModuleHooks);
default:
// fall through
}
specifier = `${pathToFileURL(path)}`;
}
// NOTE: This re-invented require() is only used on the loader-hook worker thread.
// On the main thread, the authentic require() is used instead (fixed by #60380).
const request = { specifier, attributes: importAttributes, phase: kEvaluationPhase, __proto__: null };
const job = cascadedLoader.getOrCreateModuleJob(url, request, kRequireInImportedCJS);
job.runSync(module);
let mod = cjsCache.get(job.url);
assert(job.module, `Imported CJS module ${url} failed to load module ${job.url} using require() due to race condition`);
if (job.module.synthetic) {
assert(mod, `Imported CJS module ${url} failed to load module ${job.url} using require() due to missed cache`);
return mod.exports;
}
// The module being required is a source text module.
if (!mod) {
mod = cjsEmplaceModuleCacheEntry(job.url);
cjsCache.set(job.url, mod);
}
// The module has been cached by the re-invented require. Update the exports object
// from the namespace object and return the evaluated exports.
if (!mod.loaded) {
debug('populateCJSExportsFromESM from require(esm) in imported CJS', url, mod, job.module);
populateCJSExportsFromESM(mod, job.module, job.module.getNamespace());
mod.loaded = true;
}
return mod.exports;
};
setOwnProperty(requireFn, 'resolve', function resolve(specifier) {
if (!StringPrototypeStartsWith(specifier, 'node:')) {
const {
filename, url: resolvedURL,
} = resolveForCJSWithHooks(specifier, module, false, kShouldNotSkipModuleHooks);
if (specifier !== filename) {
specifier = resolvedURL ?? `${pathToFileURL(filename)}`;
}
}
const request = { specifier, __proto__: null, attributes: kEmptyObject };
// Skip sync hooks in resolveSync since resolveForCJSWithHooks already ran them above.
const { url: resolvedURL } = cascadedLoader.resolveSync(url, request, /* shouldSkipSyncHooks */ true);
return urlToFilename(resolvedURL);
});
setOwnProperty(requireFn, 'main', process.mainModule);
FunctionPrototypeCall(compiledWrapper, module.exports,
module.exports, requireFn, module, filename, __dirname);
setOwnProperty(module, 'loaded', true);
}
// TODO: can we use a weak map instead?
const cjsCache = new SafeMap();
/**
* Creates a ModuleWrap object for a CommonJS module.
* @param {string} url - The URL of the module.
* @param {import('./loader').TranslateContext} translateContext Context for the translator
* @param {string|undefined} parentURL URL of the module initiating the module loading for the first time.
* Undefined if it's the entry point.
* @returns {ModuleWrap} The ModuleWrap object for the CommonJS module.
*/
function createCJSModuleWrap(url, translateContext, parentURL) {
debug(`Translating CJSModule ${url}`, translateContext);
const { format: sourceFormat } = translateContext;
let { source } = translateContext;
const isMain = (parentURL === undefined);
const filename = urlToFilename(url);
try {
// In case the source was not provided by the `load` step, we need fetch it now.
source = stringify(source ?? getSourceSync(new URL(url)).source);
} catch {
// Continue regardless of error.
}
const { exportNames, module } = cjsPreparseModuleExports(filename, source, sourceFormat);
cjsCache.set(url, module);
const wrapperNames = [...exportNames];
if (!exportNames.has('default')) {
ArrayPrototypePush(wrapperNames, 'default');
}
if (!exportNames.has('module.exports')) {
ArrayPrototypePush(wrapperNames, 'module.exports');
}
if (isMain) {
setOwnProperty(process, 'mainModule', module);
}
return new ModuleWrap(url, undefined, wrapperNames, function() {
debug(`Loading CJSModule ${url}`);
if (!module.loaded) {
// For backward-compatibility, it's possible for async hooks to return a nullish value for
// CJS source associated with a `file:` URL - that usually means the source is not
// customized (is loaded by default load) or the hook author wants it to be reloaded
// through CJS routine. In this case, the source is obtained by calling the
// Module._load().
if (translateContext.translatorKey === 'commonjs-sync' ||
translateContext.isSourceLoadedSynchronously ||
translateContext.source == null) {
loadCJSModuleWithModuleLoad(module, source, url, filename, !!isMain, translateContext);
} else { // CommonJS with source customized by async hooks
// This may be eventually removed when module.register() reaches end-of-life.
loadCJSModuleWithSpecialRequire(module, source, url, filename, !!isMain, translateContext);
}
}
let exports;
if (module[kModuleExport] !== undefined) {
exports = module[kModuleExport];
module[kModuleExport] = undefined;
} else {
({ exports } = module);
}
for (const exportName of exportNames) {
if (exportName === 'default' || exportName === 'module.exports' ||
!ObjectPrototypeHasOwnProperty(exports, exportName)) {
continue;
}
// We might trigger a getter -> don't fail.
let value;
try {
value = exports[exportName];
} catch {
// Continue regardless of error.
}
this.setExport(exportName, value);
}
this.setExport('default', exports);
this.setExport('module.exports', exports);
}, module);
}
/**
* Creates a ModuleWrap object for a CommonJS module without source texts.
* @param {string} url - The URL of the module.
* @param {string|undefined} parentURL - URL of the parent module, if any.
* @returns {ModuleWrap} The ModuleWrap object for the CommonJS module.
*/
function createCJSNoSourceModuleWrap(url, parentURL) {
debug(`Translating CJSModule without source ${url}`);
const isMain = (parentURL === undefined);
const filename = urlToFilename(url);
const module = cjsEmplaceModuleCacheEntry(filename);
cjsCache.set(url, module);
if (isMain) {
setOwnProperty(process, 'mainModule', module);
}
// Addon export names are not known until the addon is loaded.
const exportNames = ['default', 'module.exports'];
return new ModuleWrap(url, undefined, exportNames, function evaluationCallback() {
debug(`Loading CJSModule ${url}`);
if (!module.loaded) {
// If it gets here in the translators, the hooks must have already been invoked
// in the loader. Skip them in the synthetic module evaluation step.
wrapModuleLoad(filename, null, isMain, kShouldSkipModuleHooks);
}
/** @type {import('./loader').ModuleExports} */
let exports;
if (module[kModuleExport] !== undefined) {
exports = module[kModuleExport];
module[kModuleExport] = undefined;
} else {
({ exports } = module);
}
this.setExport('default', exports);
this.setExport('module.exports', exports);
}, module);
}
translators.set('commonjs-sync', function requireCommonJS(url, translateContext, parentURL) {
return createCJSModuleWrap(url, translateContext, parentURL);
});
// Handle CommonJS modules referenced by `require` calls using re-invented require.
// This path is only used by require() from imported CJS customized by the *async*
// loader hooks.
translators.set('require-commonjs', (url, translateContext, parentURL) => {
return createCJSModuleWrap(url, translateContext, parentURL);
});
// Handle TypeScript CommonJS modules referenced by `require` calls using re-invented require.
// This path is only used by require() from imported CJS customized by the *async*
// loader hooks.
translators.set('require-commonjs-typescript', (url, translateContext, parentURL) => {
translateContext.source = stripTypeScriptModuleTypes(stringify(translateContext.source), url);
return createCJSModuleWrap(url, translateContext, parentURL);
});
// This goes through Module._load to accommodate monkey-patchers.
/**
* Loads a CommonJS module through Module._load to accommodate monkey-patchers.
* If the module was resolved by synchronous hooks (i.e. not by the default resolver),
* passes the pre-resolved information and source to Module._load to avoid
* re-resolving and re-loading.
* @param {import('internal/modules/cjs/loader').Module} module - The module to load.
* @param {string} source - The source code of the module.
* @param {string} url - The URL of the module.
* @param {string} filename - The filename of the module.
* @param {boolean} isMain - Whether the module is the entrypoint
* @param {import('./loader').TranslateContext} translateContext Context for the translator
*/
function loadCJSModuleWithModuleLoad(module, source, url, filename, isMain, translateContext) {
assert(module === CJSModule._cache[filename]);
debug(`loadCJSModuleWithModuleLoad ${url}`);
let exports;
if (translateContext.isResolvedBySyncHooks) {
exports = wrapModuleLoad(filename, undefined, isMain, {
__proto__: null,
resolved: {
__proto__: null,
filename,
format: translateContext.format,
url,
},
shouldSkipModuleHooks: true,
source,
});
} else {
// If it gets here in the translators, the hooks must have already been invoked
// in the loader. Skip them in the synthetic module evaluation step.
exports = wrapModuleLoad(filename, undefined, isMain, kShouldSkipModuleHooks);
}
// Patched Module._load implementations may return exports without updating the
// ESM-created cache entry. Mirror the returned value into the translator-owned
// module so the synthetic module namespace observes the loaded exports.
if (!module.loaded) {
module.exports = exports;
module.loaded = true;
}
module[kModuleExport] = exports;
}
// Handle CommonJS modules referenced by `import` statements or expressions,
// or as the initial entry point when the ESM loader handles a CommonJS entry.
translators.set('commonjs', function commonjsStrategy(url, translateContext, parentURL) {
return createCJSModuleWrap(url, translateContext, parentURL);
});
/**
* Get or create an entry in the CJS module cache for the given filename.
* @param {string} filename CJS module filename
* @param {CJSModule} parent The parent CJS module
* @returns {CJSModule} the cached CJS module entry
*/
function cjsEmplaceModuleCacheEntry(filename, parent) {
// TODO: Do we want to keep hitting the user mutable CJS loader here?
let cjsMod = CJSModule._cache[filename];
if (cjsMod) {
return cjsMod;
}
cjsMod = new CJSModule(filename, parent);
cjsMod.filename = filename;
cjsMod.paths = CJSModule._nodeModulePaths(cjsMod.path);
cjsMod[kIsCachedByESMLoader] = true;
CJSModule._cache[filename] = cjsMod;
return cjsMod;
}
/**
* Pre-parses a CommonJS module's exports and re-exports.
* @param {string} filename - The filename of the module.
* @param {string} [source] - The source code of the module.
* @param {string} [format]
* @returns {{module: CJSModule, exportNames: string[]}}
*/
function cjsPreparseModuleExports(filename, source, format) {
const module = cjsEmplaceModuleCacheEntry(filename);
if (module[kModuleExportNames] !== undefined) {
return { module, exportNames: module[kModuleExportNames] };
}
if (source === undefined) {
({ source } = loadSourceForCJSWithHooks(module, filename, format));
}
module[kModuleSource] = source;
debug(`Preparsing exports of ${filename}`);
const { 0: exportNames, 1: reexports } = cjsParse(source);
// Set first for cycles.
module[kModuleExportNames] = exportNames;
// If there are any re-exports e.g. `module.exports = { ...require(...) }`,
// pre-parse the dependencies to find transitively exported names.
if (reexports.length) {
module.filename ??= filename;
module.paths ??= CJSModule._nodeModulePaths(dirname(filename));
for (let i = 0; i < reexports.length; i++) {
debug(`Preparsing re-exports of '${filename}'`);
const reexport = reexports[i];
let resolved;
let format;
try {
({ format, filename: resolved } = resolveForCJSWithHooks(reexport, module, false, kShouldNotSkipModuleHooks));
} catch (e) {
debug(`Failed to resolve '${reexport}', skipping`, e);
continue;
}
if (format === 'commonjs' ||
(!BuiltinModule.normalizeRequirableId(resolved) && findLongestRegisteredExtension(resolved) === '.js')) {
const { exportNames: reexportNames } = cjsPreparseModuleExports(resolved, undefined, format);
for (const name of reexportNames) {
exportNames.add(name);
}
}
}
}
return { module, exportNames };
}
// Strategy for loading a node builtin CommonJS module that isn't
// through normal resolution
translators.set('builtin', function builtinStrategy(url, translateContext) {
debug(`Translating BuiltinModule ${url}`, translateContext);
// Slice 'node:' scheme
const id = StringPrototypeSlice(url, 5);
const module = loadBuiltinModule(id, url);
cjsCache.set(url, module);
if (!StringPrototypeStartsWith(url, 'node:') || !module) {
throw new ERR_UNKNOWN_BUILTIN_MODULE(url);
}
debug(`Loading BuiltinModule ${url}`);
return module.getESMFacade();
});
// Strategy for loading a JSON file
translators.set('json', function jsonStrategy(url, translateContext) {
let { source } = translateContext;
assertBufferSource(source, true, 'load');
debug(`Loading JSONModule ${url}`);
const pathname = StringPrototypeStartsWith(url, 'file:') ?
fileURLToPath(url) : null;
const shouldCheckAndPopulateCJSModuleCache =
// We want to involve the CJS loader cache only for `file:` URL with no search query and no hash.
pathname && !StringPrototypeIncludes(url, '?') && !StringPrototypeIncludes(url, '#');
let modulePath;
let module;
if (shouldCheckAndPopulateCJSModuleCache) {
modulePath = isWindows ?
StringPrototypeReplaceAll(pathname, '/', '\\') : pathname;
module = CJSModule._cache[modulePath];
if (module?.loaded) {
const exports = module.exports;
return new ModuleWrap(url, undefined, ['default'], function() {
this.setExport('default', exports);
});
}
}
source = stringify(source);
if (shouldCheckAndPopulateCJSModuleCache) {
// A require call could have been called on the same file during loading and
// that resolves synchronously. To make sure we always return the identical
// export, we have to check again if the module already exists or not.
// TODO: remove CJS loader from here as well.
module = CJSModule._cache[modulePath];
if (module?.loaded) {
const exports = module.exports;
return new ModuleWrap(url, undefined, ['default'], function() {
this.setExport('default', exports);
});
}
}
try {
const exports = JSONParse(stripBOM(source));
module = {
exports,
loaded: true,
};
} catch (err) {
// TODO (BridgeAR): We could add a NodeCore error that wraps the JSON
// parse error instead of just manipulating the original error message.
// That would allow to add further properties and maybe additional
// debugging information.
err.message = errPath(url) + ': ' + err.message;
throw err;
}
if (shouldCheckAndPopulateCJSModuleCache) {
CJSModule._cache[modulePath] = module;
}
cjsCache.set(url, module);
return new ModuleWrap(url, undefined, ['default'], function() {
debug(`Parsing JSONModule ${url}`);
this.setExport('default', module.exports);
});
});
// Strategy for loading a wasm module
// This logic should collapse into WebAssembly Module Record in future.
/**
* @type {WeakMap<
* import('internal/modules/esm/utils').ModuleNamespaceObject,
* WebAssembly.Instance
* >} [[Instance]] slot proxy for WebAssembly Module Record
*/
const wasmInstances = new SafeWeakMap();
// Compile options per https://webassembly.github.io/esm-integration/js-api/index.html#parse-a-webassembly-module.
const wasmCompileOptions = {
__proto__: null,
builtins: ['js-string'],
importedStringConstants: 'wasm:js/string-constants',
};
translators.set('wasm', function(url, translateContext) {
const { source } = translateContext;
// WebAssembly global is not available during snapshot building, so we need to get it lazily.
const { WebAssembly } = globalThis;
if (WebAssembly === undefined) {
throw new ERR_WEBASSEMBLY_NOT_SUPPORTED('WebAssembly module imports');
}
assertBufferSource(source, false, 'load');
debug(`Translating WASMModule ${url}`, translateContext);
// When the compile cache is enabled, the cache entry holds the module
// deserialized from cached optimized code if V8 accepted it.
const cacheEntry = getWasmCompileCacheEntry(
isAnyArrayBuffer(source) ? new Uint8Array(source) : source, url, wasmCompileOptions);
let compiled = cacheEntry?.module;
if (compiled === undefined) {
try {
compiled = new WebAssembly.Module(source, wasmCompileOptions);
} catch (err) {
err.message = errPath(url) + ': ' + err.message;
throw err;
}
if (cacheEntry !== undefined) {
saveWasmCompileCacheEntry(cacheEntry.external, compiled);
}
}
const importsList = new SafeSet();
const wasmGlobalImports = [];
for (const impt of WebAssembly.Module.imports(compiled)) {
if (impt.kind === 'global') {
ArrayPrototypePush(wasmGlobalImports, impt);
}
// Prefix reservations per https://webassembly.github.io/esm-integration/js-api/index.html#parse-a-webassembly-module.
if (impt.module.startsWith('wasm-js:')) {
throw new WebAssembly.LinkError(`Invalid Wasm import "${impt.module}" in ${url}`);
}
if (impt.name.startsWith('wasm:') || impt.name.startsWith('wasm-js:')) {
throw new WebAssembly.LinkError(`Invalid Wasm import name "${impt.name}" in ${url}`);
}
importsList.add(impt.module);
}
const exportsList = new SafeSet();
const wasmGlobalExports = new SafeSet();
for (const expt of WebAssembly.Module.exports(compiled)) {
if (expt.kind === 'global') {
wasmGlobalExports.add(expt.name);
}
if (expt.name.startsWith('wasm:') || expt.name.startsWith('wasm-js:')) {
throw new WebAssembly.LinkError(`Invalid Wasm export name "${expt.name}" in ${url}`);
}
exportsList.add(expt.name);
}
const createDynamicModule = require('internal/modules/esm/create_dynamic_module');
const { module } = createDynamicModule([...importsList], [...exportsList], url, (reflect) => {
emitExperimentalWarning('Importing WebAssembly module instances');
for (const impt of importsList) {
const importNs = reflect.imports[impt];
const wasmInstance = wasmInstances.get(importNs);
if (wasmInstance) {
const wrappedModule = ObjectAssign({ __proto__: null }, reflect.imports[impt]);
for (const { module, name } of wasmGlobalImports) {
if (module !== impt) {
continue;
}
// Import of Wasm module global -> get direct WebAssembly.Global wrapped value.
// JS API validations otherwise remain the same.
wrappedModule[name] = wasmInstance[name];
}
reflect.imports[impt] = wrappedModule;
}
}
// In cycles importing unexecuted Wasm, wasmInstance will be undefined, which will fail during
// instantiation, since all bindings will be in the Temporal Deadzone (TDZ).
const { exports } = new WebAssembly.Instance(compiled, reflect.imports);
wasmInstances.set(module.getNamespace(), exports);
for (const expt of exportsList) {
let val = exports[expt];
// Unwrap WebAssembly.Global for JS bindings
if (wasmGlobalExports.has(expt)) {
try {
// v128 will throw in GetGlobalValue, see:
// https://webassembly.github.io/esm-integration/js-api/index.html#getglobalvalue
val = val.value;
} catch {
// v128 doesn't support ToJsValue() -> use undefined (ideally should stay in TDZ)
continue;
}
}
reflect.exports[expt].set(val);
}
});
// WebAssembly modules support source phase imports, to import the compiled module
// separate from the linked instance.
module.setModuleSourceObject(compiled);
return module;
});
// Strategy for loading a addon
translators.set('addon', function translateAddon(url, translateContext, parentURL) {
emitExperimentalWarning('Importing addons');
const { source } = translateContext;
// The addon must be loaded from file system with dlopen. Assert
// the source is null.
if (source !== null) {
throw new ERR_INVALID_RETURN_PROPERTY_VALUE(
'null',
'load',
'source',
source);
}
debug(`Translating addon ${url}`, translateContext);
return createCJSNoSourceModuleWrap(url, parentURL);
});
// Strategy for loading a commonjs TypeScript module
translators.set('commonjs-typescript', function(url, translateContext, parentURL) {
const { source } = translateContext;
assertBufferSource(source, true, 'load');
debug(`Translating TypeScript ${url}`, translateContext);
translateContext.source = stripTypeScriptModuleTypes(stringify(source), url);
return FunctionPrototypeCall(translators.get('commonjs'), this, url, translateContext, parentURL);
});
// Strategy for loading an esm TypeScript module
translators.set('module-typescript', function(url, translateContext, parentURL) {
const { source } = translateContext;
assertBufferSource(source, true, 'load');
debug(`Translating TypeScript ${url}`, translateContext);
translateContext.source = stripTypeScriptModuleTypes(stringify(source), url);
return FunctionPrototypeCall(translators.get('module'), this, url, translateContext, parentURL);
});
// Strategy for loading source as text.
translators.set('text', function textStrategy(url, translateContext) {
emitExperimentalWarning('Text import');
let { source } = translateContext;
assertBufferSource(source, true, 'load');
source = stringify(source);
return new ModuleWrap(url, undefined, ['default'], function() {
this.setExport('default', source);
});
});