From 584c38282e17d161c7d4b732f57f1aa587f2497e Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Thu, 25 Apr 2024 01:48:13 +0200 Subject: [PATCH] module: move callbacks and conditions into This moves the following utils into modules/esm/utils.js: - Code related to default conditions - The callbackMap (which is now created in the module instead of hanging off the module_wrap binding, since the C++ land does not need it). - Per-isolate module callbacks These are self-contained code that can be included into the built-in snapshot. PR-URL: https://github.com/nodejs/node/pull/45849 Backport-PR-URL: https://github.com/nodejs/node/pull/46425 Reviewed-By: Geoffrey Booth Reviewed-By: Chengzhong Wu --- .../modules/esm/create_dynamic_module.js | 6 ++-- .../lib/internal/modules/esm/loader.js | 12 ++++--- .../lib/internal/modules/esm/resolve.js | 32 +------------------ .../lib/internal/modules/esm/translators.js | 3 +- .../lib/internal/process/esm_loader.js | 29 ----------------- .../lib/internal/process/pre_execution.js | 15 ++------- graal-nodejs/lib/internal/vm.js | 7 ++-- graal-nodejs/lib/internal/vm/module.js | 4 +-- graal-nodejs/lib/vm.js | 7 ++-- .../test/parallel/test-bootstrap-modules.js | 1 + 10 files changed, 25 insertions(+), 91 deletions(-) diff --git a/graal-nodejs/lib/internal/modules/esm/create_dynamic_module.js b/graal-nodejs/lib/internal/modules/esm/create_dynamic_module.js index c99da19d5c8..32f1c82a7a2 100644 --- a/graal-nodejs/lib/internal/modules/esm/create_dynamic_module.js +++ b/graal-nodejs/lib/internal/modules/esm/create_dynamic_module.js @@ -35,7 +35,7 @@ ${ArrayPrototypeJoin(ArrayPrototypeMap(imports, createImport), '\n')} ${ArrayPrototypeJoin(ArrayPrototypeMap(exports, createExport), '\n')} import.meta.done(); `; - const { ModuleWrap, callbackMap } = internalBinding('module_wrap'); + const { ModuleWrap } = internalBinding('module_wrap'); const m = new ModuleWrap(`${url}`, undefined, source, 0, 0); const readyfns = new SafeSet(); @@ -46,8 +46,8 @@ import.meta.done(); if (imports.length) reflect.imports = ObjectCreate(null); - - callbackMap.set(m, { + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(m, { initializeImportMeta: (meta, wrap) => { meta.exports = reflect.exports; if (reflect.imports) diff --git a/graal-nodejs/lib/internal/modules/esm/loader.js b/graal-nodejs/lib/internal/modules/esm/loader.js index 64d07fb1468..a367fa415a3 100644 --- a/graal-nodejs/lib/internal/modules/esm/loader.js +++ b/graal-nodejs/lib/internal/modules/esm/loader.js @@ -47,9 +47,12 @@ function newModuleMap() { const { defaultResolve, - DEFAULT_CONDITIONS, } = require('internal/modules/esm/resolve'); +const { + getDefaultConditions, +} = require('internal/modules/esm/utils'); + function getTranslators() { const { translators } = require('internal/modules/esm/translators'); return translators; @@ -375,9 +378,10 @@ class ESMLoader { url = pathToFileURL(`${process.cwd()}/[eval${++this.evalIndex}]`).href, ) { const evalInstance = (url) => { - const { ModuleWrap, callbackMap } = internalBinding('module_wrap'); + const { ModuleWrap } = internalBinding('module_wrap'); + const { setCallbackForWrap } = require('internal/modules/esm/utils'); const module = new ModuleWrap(url, undefined, source, 0, 0); - callbackMap.set(module, { + setCallbackForWrap(module, { importModuleDynamically: (specifier, { url }, importAssertions) => { return this.import(specifier, url, importAssertions); }, @@ -802,7 +806,7 @@ class ESMLoader { } const chain = this.#hooks.resolve; const context = { - conditions: DEFAULT_CONDITIONS, + conditions: getDefaultConditions(), importAssertions, parentURL, }; diff --git a/graal-nodejs/lib/internal/modules/esm/resolve.js b/graal-nodejs/lib/internal/modules/esm/resolve.js index 7006887a6fe..0dc8711643c 100644 --- a/graal-nodejs/lib/internal/modules/esm/resolve.js +++ b/graal-nodejs/lib/internal/modules/esm/resolve.js @@ -6,7 +6,6 @@ const { ArrayPrototypeShift, JSONParse, JSONStringify, - ObjectFreeze, ObjectGetOwnPropertyNames, ObjectPrototypeHasOwnProperty, RegExp, @@ -46,7 +45,6 @@ const typeFlag = getOptionValue('--input-type'); const { URL, pathToFileURL, fileURLToPath } = require('internal/url'); const { ERR_INPUT_TYPE_NOT_ALLOWED, - ERR_INVALID_ARG_VALUE, ERR_INVALID_MODULE_SPECIFIER, ERR_INVALID_PACKAGE_CONFIG, ERR_INVALID_PACKAGE_TARGET, @@ -61,25 +59,13 @@ const { const { Module: CJSModule } = require('internal/modules/cjs/loader'); const packageJsonReader = require('internal/modules/package_json_reader'); const { getPackageConfig, getPackageScopeConfig } = require('internal/modules/esm/package_config'); +const { getConditionsSet } = require('internal/modules/esm/utils'); /** * @typedef {import('internal/modules/esm/package_config.js').PackageConfig} PackageConfig */ -const userConditions = getOptionValue('--conditions'); -const noAddons = getOptionValue('--no-addons'); -const addonConditions = noAddons ? [] : ['node-addons']; - -const DEFAULT_CONDITIONS = ObjectFreeze([ - 'node', - 'import', - ...addonConditions, - ...userConditions, -]); - -const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS); - const emittedPackageWarnings = new SafeSet(); function emitTrailingSlashPatternDeprecation(match, pjsonUrl, base) { @@ -150,21 +136,6 @@ function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) { } } -/** - * @param {string[]} [conditions] - * @returns {Set} - */ -function getConditionsSet(conditions) { - if (conditions !== undefined && conditions !== DEFAULT_CONDITIONS) { - if (!ArrayIsArray(conditions)) { - throw new ERR_INVALID_ARG_VALUE('conditions', conditions, - 'expected an array'); - } - return new SafeSet(conditions); - } - return DEFAULT_CONDITIONS_SET; -} - const realpathCache = new SafeMap(); /** @@ -1167,7 +1138,6 @@ async function defaultResolve(specifier, context = {}) { } module.exports = { - DEFAULT_CONDITIONS, defaultResolve, encodedSepRegEx, getPackageScopeConfig, diff --git a/graal-nodejs/lib/internal/modules/esm/translators.js b/graal-nodejs/lib/internal/modules/esm/translators.js index eb03858c586..e185e29ad04 100644 --- a/graal-nodejs/lib/internal/modules/esm/translators.js +++ b/graal-nodejs/lib/internal/modules/esm/translators.js @@ -115,7 +115,8 @@ translators.set('module', async function moduleStrategy(url, source, isMain) { maybeCacheSourceMap(url, source); debug(`Translating StandardModule ${url}`); const module = new ModuleWrap(url, undefined, source, 0, 0); - moduleWrap.callbackMap.set(module, { + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(module, { initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }), importModuleDynamically, }); diff --git a/graal-nodejs/lib/internal/process/esm_loader.js b/graal-nodejs/lib/internal/process/esm_loader.js index bb621d2aa25..70f48c2f9ac 100644 --- a/graal-nodejs/lib/internal/process/esm_loader.js +++ b/graal-nodejs/lib/internal/process/esm_loader.js @@ -5,40 +5,11 @@ const { ObjectCreate, } = primordials; -const { - ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING, -} = require('internal/errors').codes; const { ESMLoader } = require('internal/modules/esm/loader'); const { hasUncaughtExceptionCaptureCallback, } = require('internal/process/execution'); const { pathToFileURL } = require('internal/url'); -const { - getModuleFromWrap, -} = require('internal/vm/module'); - -exports.initializeImportMetaObject = function(wrap, meta) { - const { callbackMap } = internalBinding('module_wrap'); - if (callbackMap.has(wrap)) { - const { initializeImportMeta } = callbackMap.get(wrap); - if (initializeImportMeta !== undefined) { - initializeImportMeta(meta, getModuleFromWrap(wrap) || wrap); - } - } -}; - -exports.importModuleDynamicallyCallback = -async function importModuleDynamicallyCallback(wrap, specifier, assertions) { - const { callbackMap } = internalBinding('module_wrap'); - if (callbackMap.has(wrap)) { - const { importModuleDynamically } = callbackMap.get(wrap); - if (importModuleDynamically !== undefined) { - return importModuleDynamically( - specifier, getModuleFromWrap(wrap) || wrap, assertions); - } - } - throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING(); -}; const esmLoader = new ESMLoader(); exports.esmLoader = esmLoader; diff --git a/graal-nodejs/lib/internal/process/pre_execution.js b/graal-nodejs/lib/internal/process/pre_execution.js index eaf04e9c3a1..cacf436853f 100644 --- a/graal-nodejs/lib/internal/process/pre_execution.js +++ b/graal-nodejs/lib/internal/process/pre_execution.js @@ -5,7 +5,6 @@ const { ObjectDefineProperties, ObjectDefineProperty, SafeMap, - SafeWeakMap, StringPrototypeStartsWith, Symbol, SymbolDispose, @@ -561,20 +560,10 @@ function initializeCJSLoader() { } function initializeESMLoader() { - // Create this WeakMap in js-land because V8 has no C++ API for WeakMap. - internalBinding('module_wrap').callbackMap = new SafeWeakMap(); - if (getEmbedderOptions().shouldNotRegisterESMLoader) return; - const { - setImportModuleDynamicallyCallback, - setInitializeImportMetaObjectCallback, - } = internalBinding('module_wrap'); - const esm = require('internal/process/esm_loader'); - // Setup per-isolate callbacks that locate data or callbacks that we keep - // track of for different ESM modules. - setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject); - setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback); + const { initializeESM } = require('internal/modules/esm/utils'); + initializeESM(); // Patch the vm module when --experimental-vm-modules is on. // Please update the comments in vm.js when this block changes. diff --git a/graal-nodejs/lib/internal/vm.js b/graal-nodejs/lib/internal/vm.js index 4f87ce87cc2..b14ba13e7e4 100644 --- a/graal-nodejs/lib/internal/vm.js +++ b/graal-nodejs/lib/internal/vm.js @@ -97,12 +97,11 @@ function internalCompileFunction(code, params, options) { if (importModuleDynamically !== undefined) { validateFunction(importModuleDynamically, 'options.importModuleDynamically'); - const { importModuleDynamicallyWrap } = - require('internal/vm/module'); - const { callbackMap } = internalBinding('module_wrap'); + const { importModuleDynamicallyWrap } = require('internal/vm/module'); const wrapped = importModuleDynamicallyWrap(importModuleDynamically); const func = result.function; - callbackMap.set(result.cacheKey, { + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(result.cacheKey, { importModuleDynamically: (s, _k, i) => wrapped(s, func, i), }); } diff --git a/graal-nodejs/lib/internal/vm/module.js b/graal-nodejs/lib/internal/vm/module.js index 109b2d7e5b6..ec9618139b5 100644 --- a/graal-nodejs/lib/internal/vm/module.js +++ b/graal-nodejs/lib/internal/vm/module.js @@ -125,8 +125,8 @@ class Module { this[kWrap] = new ModuleWrap(identifier, context, sourceText, options.lineOffset, options.columnOffset, options.cachedData); - - binding.callbackMap.set(this[kWrap], { + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(this[kWrap], { initializeImportMeta: options.initializeImportMeta, importModuleDynamically: options.importModuleDynamically ? importModuleDynamicallyWrap(options.importModuleDynamically) : diff --git a/graal-nodejs/lib/vm.js b/graal-nodejs/lib/vm.js index 21acc55e2ef..b48e79c2825 100644 --- a/graal-nodejs/lib/vm.js +++ b/graal-nodejs/lib/vm.js @@ -105,10 +105,9 @@ class Script extends ContextifyScript { if (importModuleDynamically !== undefined) { validateFunction(importModuleDynamically, 'options.importModuleDynamically'); - const { importModuleDynamicallyWrap } = - require('internal/vm/module'); - const { callbackMap } = internalBinding('module_wrap'); - callbackMap.set(this, { + const { importModuleDynamicallyWrap } = require('internal/vm/module'); + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(this, { importModuleDynamically: importModuleDynamicallyWrap(importModuleDynamically), }); diff --git a/graal-nodejs/test/parallel/test-bootstrap-modules.js b/graal-nodejs/test/parallel/test-bootstrap-modules.js index 5019081110a..03904f55d51 100644 --- a/graal-nodejs/test/parallel/test-bootstrap-modules.js +++ b/graal-nodejs/test/parallel/test-bootstrap-modules.js @@ -65,6 +65,7 @@ const expectedModules = new Set([ 'NativeModule internal/modules/esm/package_config', 'NativeModule internal/modules/esm/resolve', 'NativeModule internal/modules/esm/translators', + 'NativeModule internal/modules/esm/utils', 'NativeModule internal/modules/package_json_reader', 'NativeModule internal/modules/run_main', 'NativeModule internal/net',