diff --git a/lib/internal/util.js b/lib/internal/util.js index 5665923a2cd297..2b8b2117d52efb 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -15,6 +15,7 @@ const { ObjectGetOwnPropertyDescriptors, ObjectGetPrototypeOf, ObjectFreeze, + ObjectIsSealed, ObjectPrototypeHasOwnProperty, ObjectSetPrototypeOf, ObjectValues, @@ -529,10 +530,13 @@ function defineLazyProperties(target, id, keys, enumerable = true) { value: `set ${key}`, }); function get() { - mod ??= require(id); if (lazyLoadedValue === undefined) { + mod ??= require(id); lazyLoadedValue = mod[key]; - set(lazyLoadedValue); + if (!ObjectIsSealed(this)) { + // Replace it with a data property. + set(lazyLoadedValue); + } } return lazyLoadedValue; } diff --git a/test/parallel/test-frozen-global.js b/test/parallel/test-frozen-global.js new file mode 100644 index 00000000000000..8284a60c54cb18 --- /dev/null +++ b/test/parallel/test-frozen-global.js @@ -0,0 +1,23 @@ +'use strict'; + +// This tests that the globals can still be loaded after globalThis is frozen. + +require('../common'); +const assert = require('assert'); + +Object.freeze(globalThis); +const keys = Reflect.ownKeys(globalThis).filter((k) => typeof k === 'string'); + +// These failures come from undici. We can remove them once they are fixed. +const knownFailures = new Set(['FormData', 'Headers', 'Request', 'Response']); +const failures = new Map(); +const success = new Map(); +for (const key of keys) { + try { + success.set(key, globalThis[key]); + } catch (e) { + failures.set(key, e); + } +} + +assert.deepStrictEqual(new Set(failures.keys()), knownFailures); diff --git a/test/parallel/test-sealed-global.js b/test/parallel/test-sealed-global.js new file mode 100644 index 00000000000000..9eb96ccdf03edb --- /dev/null +++ b/test/parallel/test-sealed-global.js @@ -0,0 +1,23 @@ +'use strict'; + +// This tests that the globals can still be loaded after globalThis is sealed. + +require('../common'); +const assert = require('assert'); + +Object.seal(globalThis); +const keys = Reflect.ownKeys(globalThis).filter((k) => typeof k === 'string'); + +// These failures come from undici. We can remove them once they are fixed. +const knownFailures = new Set(['FormData', 'Headers', 'Request', 'Response']); +const failures = new Map(); +const success = new Map(); +for (const key of keys) { + try { + success.set(key, globalThis[key]); + } catch (e) { + failures.set(key, e); + } +} + +assert.deepStrictEqual(new Set(failures.keys()), knownFailures);