diff --git a/lib/internal/modules/esm/initialize_import_meta.js b/lib/internal/modules/esm/initialize_import_meta.js index 43064f14b057a4..3aafc34d1a363f 100644 --- a/lib/internal/modules/esm/initialize_import_meta.js +++ b/lib/internal/modules/esm/initialize_import_meta.js @@ -1,6 +1,8 @@ 'use strict'; const { + ObjectDefineProperties, + ObjectDefineProperty, StringPrototypeStartsWith, } = primordials; @@ -60,9 +62,37 @@ function initializeImportMeta(meta, context, loader) { if (StringPrototypeStartsWith(url, 'file:') === true) { // These only make sense for locally loaded modules, // i.e. network modules are not supported. - const filePath = fileURLToPath(url); - meta.dirname = dirname(filePath); - meta.filename = filePath; + + // Avoid paying the cost to derive these unless they're actually accessed. + ObjectDefineProperties(meta, { + dirname: { + get() { + const value = dirname(this.filename); + ObjectDefineProperty(this, 'dirname', { __proto__: null, value, writable: true }); + return value; + }, + set(value) { + ObjectDefineProperty(this, 'dirname', { __proto__: null, value, writable: true }); + }, + configurable: true, + enumerable: true, + __proto__: null, + }, + filename: { + get() { + const value = fileURLToPath(url); + ObjectDefineProperty(this, 'filename', { __proto__: null, value, writable: true }); + return value; + }, + set(value) { + ObjectDefineProperty(this, 'filename', { __proto__: null, value, writable: true }); + }, + configurable: true, + enumerable: true, + __proto__: null, + }, + __proto__: null, + }); } if (!loader || loader.allowImportMetaResolve) { diff --git a/test/es-module/test-esm-import-meta.mjs b/test/es-module/test-esm-import-meta.mjs index 50d16a3438a851..37053a88dd9f51 100644 --- a/test/es-module/test-esm-import-meta.mjs +++ b/test/es-module/test-esm-import-meta.mjs @@ -9,11 +9,8 @@ assert.deepStrictEqual(Reflect.ownKeys(import.meta), keys); const descriptors = Object.getOwnPropertyDescriptors(import.meta); for (const descriptor of Object.values(descriptors)) { delete descriptor.value; // Values are verified below. - assert.deepStrictEqual(descriptor, { - enumerable: true, - writable: true, - configurable: true - }); + assert.strictEqual(descriptor.configurable, true); + assert.strictEqual(descriptor.enumerable, true); } const urlReg = /^file:\/\/\/.*\/test\/es-module\/test-esm-import-meta\.mjs$/; @@ -24,11 +21,19 @@ assert(import.meta.url.match(urlReg)); const dirReg = /^(\/|\w:\\).*(\/|\\)test(\/|\\)es-module$/; assert.match(import.meta.dirname, dirReg); +const newDirname = 'reassigned'; +import.meta.dirname = newDirname; +assert.strictEqual(import.meta.dirname, newDirname); + // Match *nix paths: `/some/path/test/es-module/test-esm-import-meta.mjs` // Match Windows paths: `d:\\some\\path\\test\\es-module\\test-esm-import-meta.js` const fileReg = /^(\/|\w:\\).*(\/|\\)test(\/|\\)es-module(\/|\\)test-esm-import-meta\.mjs$/; assert.match(import.meta.filename, fileReg); +const newFilename = 'reassigned.js'; +import.meta.filename = newFilename; +assert.strictEqual(import.meta.filename, newFilename); + // Verify that `data:` imports do not behave like `file:` imports. import dataDirname from 'data:text/javascript,export default "dirname" in import.meta'; assert.strictEqual(dataDirname, false);