diff --git a/benchmark/esm/load-cache.js b/benchmark/esm/load-cache.js new file mode 100644 index 00000000000..69237f68a93 --- /dev/null +++ b/benchmark/esm/load-cache.js @@ -0,0 +1,26 @@ +'use strict'; + +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + urls: [1, 100], + n: [1e7], +}, { + flags: ['--expose-internals'], +}); + +function main({ urls, n }) { + const { LoadCache } = require('internal/modules/esm/module_map'); + const cache = new LoadCache(); + const job = () => {}; + const keys = Array.from({ length: urls }, (_, i) => `file:///module-${i}.mjs`); + for (let i = 0; i < keys.length; i++) cache.set(keys[i], undefined, job); + + bench.start(); + for (let i = 0; i < n; i++) { + if (cache.get(keys[i % keys.length]) !== job) { + throw new Error('Load cache miss'); + } + } + bench.end(n); +} diff --git a/lib/internal/modules/esm/module_map.js b/lib/internal/modules/esm/module_map.js index 207515573c7..c9f57f0f829 100644 --- a/lib/internal/modules/esm/module_map.js +++ b/lib/internal/modules/esm/module_map.js @@ -6,6 +6,7 @@ const { ArrayPrototypeSort, JSONStringify, ObjectKeys, + ObjectSetPrototypeOf, SafeMap, } = primordials; const { kImplicitTypeAttribute } = require('internal/modules/esm/assert'); @@ -108,7 +109,7 @@ class LoadCache extends SafeMap { debug(`Storing ${url} (${ type === kImplicitTypeAttribute ? 'implicit type' : type }) in ModuleLoadMap`); - const cachedJobsForUrl = super.get(url) ?? { __proto__: null }; + const cachedJobsForUrl = super.get(url) ?? ObjectSetPrototypeOf({}, null); cachedJobsForUrl[type] = job; return super.set(url, cachedJobsForUrl); } diff --git a/test/es-module/test-esm-loader-load-cache-prototype.js b/test/es-module/test-esm-loader-load-cache-prototype.js new file mode 100644 index 00000000000..f9a516c6aca --- /dev/null +++ b/test/es-module/test-esm-loader-load-cache-prototype.js @@ -0,0 +1,22 @@ +'use strict'; +// Flags: --expose-internals + +require('../common'); + +const assert = require('assert'); +const { LoadCache } = require('internal/modules/esm/module_map'); + +const cache = new LoadCache(); +const url = 'file:///module.mjs'; +const job = () => {}; + +assert.strictEqual(cache.get(url, '__proto__'), undefined); +assert.strictEqual(cache.has(url, 'constructor'), false); +cache.set(url, '__proto__', job); +assert.strictEqual(cache.get(url, '__proto__'), job); +assert.strictEqual(cache.has(url, '__proto__'), true); +assert.strictEqual(cache.has(url, 'constructor'), false); +cache.set(url, 'constructor', job); +assert.strictEqual(cache.get(url, 'constructor'), job); +cache.delete(url, '__proto__'); +assert.strictEqual(cache.get(url, '__proto__'), undefined);