diff --git a/lib/eslint.config_partial.mjs b/lib/eslint.config_partial.mjs index 005cd0a410c2f6..335692e2cf4a18 100644 --- a/lib/eslint.config_partial.mjs +++ b/lib/eslint.config_partial.mjs @@ -164,10 +164,6 @@ export default [ name: 'Intl', message: 'Use `const { Intl } = globalThis;` instead of the global.', }, - { - name: 'Iterator', - message: 'Use `const { Iterator } = globalThis;` instead of the global.', - }, { name: 'MessageChannel', message: "Use `const { MessageChannel } = require('internal/worker/io');` instead of the global.", @@ -464,6 +460,7 @@ export default [ { name: 'Int16Array' }, { name: 'Int32Array' }, { name: 'Int8Array' }, + { name: 'Iterator' }, { name: 'isFinite', into: 'Number', diff --git a/lib/internal/freeze_intrinsics.js b/lib/internal/freeze_intrinsics.js index 4f083dc34f44d2..20cea3a0e053bb 100644 --- a/lib/internal/freeze_intrinsics.js +++ b/lib/internal/freeze_intrinsics.js @@ -63,9 +63,13 @@ const { Int32ArrayPrototype, Int8Array, Int8ArrayPrototype, + Iterator, + IteratorFrom, IteratorPrototype, + IteratorPrototypeDrop, Map, MapPrototype, + MapPrototypeSymbolIterator, Number, NumberPrototype, Object, @@ -88,15 +92,15 @@ const { ReflectOwnKeys, RegExp, RegExpPrototype, + RegExpPrototypeSymbolMatchAll, SafeSet, Set, SetPrototype, + SetPrototypeSymbolIterator, String, StringIteratorPrototype, StringPrototype, Symbol, - SymbolIterator, - SymbolMatchAll, SymbolPrototype, SyntaxError, SyntaxErrorPrototype, @@ -148,6 +152,16 @@ module.exports = function() { setTimeout, } = require('timers'); + const AsyncFunctionPrototype = ObjectGetPrototypeOf(async function() {}); + const AsyncGeneratorFunctionPrototype = ObjectGetPrototypeOf(async function*() {}); + const GeneratorFunctionPrototype = ObjectGetPrototypeOf(function*() {}); + const IteratorHelperPrototype = ObjectGetPrototypeOf(IteratorPrototypeDrop({ __proto__: null }, null)); + const MapIteratorPrototype = ObjectGetPrototypeOf(MapPrototypeSymbolIterator(new Map())); + // eslint-disable-next-line node-core/avoid-prototype-pollution, regexp/no-empty-group + const RegExpStringIteratorPrototype = ObjectGetPrototypeOf(RegExpPrototypeSymbolMatchAll(/(?:)/)); + const SetIteratorPrototype = ObjectGetPrototypeOf(SetPrototypeSymbolIterator(new Set())); + const WrapForValidIteratorPrototype = ObjectGetPrototypeOf(IteratorFrom({ __proto__: null })); + const intrinsicPrototypes = [ // 20 Fundamental Objects ObjectPrototype, // 20.1 @@ -173,8 +187,7 @@ module.exports = function() { StringPrototype, // 22.1 StringIteratorPrototype, // 22.1.5 RegExpPrototype, // 22.2 - // 22.2.7 RegExpStringIteratorPrototype - ObjectGetPrototypeOf(/e/[SymbolMatchAll]()), + RegExpStringIteratorPrototype, // 22.2.9 // 23 Indexed Collections ArrayPrototype, // 23.1 @@ -195,11 +208,9 @@ module.exports = function() { // 24 Keyed Collections MapPrototype, // 24.1 - // 24.1.5 MapIteratorPrototype - ObjectGetPrototypeOf(new Map()[SymbolIterator]()), + MapIteratorPrototype, // 24.1.5 SetPrototype, // 24.2 - // 24.2.5 SetIteratorPrototype - ObjectGetPrototypeOf(new Set()[SymbolIterator]()), + SetIteratorPrototype, // 24.2.6 WeakMapPrototype, // 24.3 WeakSetPrototype, // 24.4 @@ -212,10 +223,18 @@ module.exports = function() { FinalizationRegistryPrototype, // 26.2 // 27 Control Abstraction Objects - // 27.1 Iteration - IteratorPrototype, // 27.1.2 IteratorPrototype - AsyncIteratorPrototype, // 27.1.3 AsyncIteratorPrototype + IteratorHelperPrototype, // 27.1.2 + IteratorPrototype, // 27.1.3 + WrapForValidIteratorPrototype, // 27.1.3.2.2.1 + AsyncIteratorPrototype, // 27.1.4 PromisePrototype, // 27.2 + GeneratorFunctionPrototype, // 27.3 + AsyncGeneratorFunctionPrototype, // 27.4 + // 27.5 GeneratorPrototype + GeneratorFunctionPrototype.prototype, + // 27.6 AsyncGeneratorPrototype + AsyncGeneratorFunctionPrototype.prototype, + AsyncFunctionPrototype, // 27.7 // Other APIs / Web Compatibility Console.prototype, @@ -268,8 +287,7 @@ module.exports = function() { String, // 22.1 StringIteratorPrototype, // 22.1.5 RegExp, // 22.2 - // 22.2.7 RegExpStringIteratorPrototype - ObjectGetPrototypeOf(/e/[SymbolMatchAll]()), + RegExpStringIteratorPrototype, // 22.2.9 // 23 Indexed Collections Array, // 23.1 @@ -290,11 +308,9 @@ module.exports = function() { // 24 Keyed Collections Map, // 24.1 - // 24.1.5 MapIteratorPrototype - ObjectGetPrototypeOf(new Map()[SymbolIterator]()), + MapIteratorPrototype, // 24.1.5 Set, // 24.2 - // 24.2.5 SetIteratorPrototype - ObjectGetPrototypeOf(new Set()[SymbolIterator]()), + SetIteratorPrototype, // 24.2.6 WeakMap, // 24.3 WeakSet, // 24.4 @@ -310,19 +326,19 @@ module.exports = function() { FinalizationRegistry, // 26.2 // 27 Control Abstraction Objects - // 27.1 Iteration - ObjectGetPrototypeOf(ArrayIteratorPrototype), // 27.1.2 IteratorPrototype - // 27.1.3 AsyncIteratorPrototype - ObjectGetPrototypeOf(ObjectGetPrototypeOf(ObjectGetPrototypeOf( - (async function*() {})(), - ))), + IteratorHelperPrototype, // 27.1.2 + Iterator, // 27.1.3 + WrapForValidIteratorPrototype, // 27.1.3.2.2.1 + ArrayIteratorPrototype, // 27.1.4 Promise, // 27.2 // 27.3 GeneratorFunction - ObjectGetPrototypeOf(function* () {}), + // 27.5 Generator + GeneratorFunctionPrototype, // 27.4 AsyncGeneratorFunction - ObjectGetPrototypeOf(async function* () {}), + // 27.6 AsyncGenerator + AsyncGeneratorFunctionPrototype, // 27.7 AsyncFunction - ObjectGetPrototypeOf(async function() {}), + AsyncFunctionPrototype, // 28 Reflection // eslint-disable-next-line node-core/prefer-primordials diff --git a/lib/internal/per_context/primordials.js b/lib/internal/per_context/primordials.js index e2b5f763df7dd9..4d4de7b4e3aafb 100644 --- a/lib/internal/per_context/primordials.js +++ b/lib/internal/per_context/primordials.js @@ -202,6 +202,7 @@ function copyPrototype(src, dest, prefix) { 'Int16Array', 'Int32Array', 'Int8Array', + 'Iterator', 'Map', 'Number', 'Object', @@ -230,10 +231,10 @@ function copyPrototype(src, dest, prefix) { }); -// Create copies of intrinsic objects that require a valid `this` to call -// static methods. -// Refs: https://www.ecma-international.org/ecma-262/#sec-promise.all +// Create copies of intrinsic objects whose static methods require the +// constructor to be passed as the receiver. [ + // Refs: https://tc39.es/ecma-262/#sec-promise.all 'Promise', ].forEach((name) => { // eslint-disable-next-line no-restricted-globals @@ -244,25 +245,36 @@ function copyPrototype(src, dest, prefix) { }); // Create copies of abstract intrinsic objects that are not directly exposed -// on the global object. -// Refs: https://tc39.es/ecma262/#sec-%typedarray%-intrinsic-object +// on the global object, and whose static methods require a valid subclass +// constructor to be passed as the receiver. [ + // Refs: https://tc39.es/ecma262/#sec-%typedarray%-intrinsic-object { name: 'TypedArray', original: Reflect.getPrototypeOf(Uint8Array) }, - { name: 'ArrayIterator', original: { - prototype: Reflect.getPrototypeOf(Array.prototype[Symbol.iterator]()), - } }, - { name: 'StringIterator', original: { - prototype: Reflect.getPrototypeOf(String.prototype[Symbol.iterator]()), - } }, ].forEach(({ name, original }) => { primordials[name] = original; - // The static %TypedArray% methods require a valid `this`, but can't be bound, - // as they need a subclass constructor as the receiver: copyPrototype(original, primordials, name); copyPrototype(original.prototype, primordials, `${name}Prototype`); }); -primordials.IteratorPrototype = Reflect.getPrototypeOf(primordials.ArrayIteratorPrototype); +// Create copies of abstract intrinsic prototypes that are not directly exposed +// on the global object and which do not have corresponding constructors. +[ + { + name: 'ArrayIteratorPrototype', + original: Reflect.getPrototypeOf(Array.prototype[Symbol.iterator]()), + }, + { + name: 'AsyncIteratorPrototype', + original: Reflect.getPrototypeOf(Reflect.getPrototypeOf(async function*() {}).prototype), + }, + { + name: 'StringIteratorPrototype', + original: Reflect.getPrototypeOf(String.prototype[Symbol.iterator]()), + }, +].forEach(({ name, original }) => { + primordials[name] = original; + copyPrototype(original, primordials, name); +}); /* eslint-enable node-core/prefer-primordials */ @@ -453,11 +465,6 @@ primordials.SafePromisePrototypeFinally = (thisPromise, onFinally) => .then(a, b), ); -primordials.AsyncIteratorPrototype = - primordials.ReflectGetPrototypeOf( - primordials.ReflectGetPrototypeOf( - async function* () {}).prototype); - const arrayToSafePromiseIterable = (promises, mapFn) => new primordials.SafeArrayIterator( ArrayPrototypeMap( diff --git a/typings/primordials.d.ts b/typings/primordials.d.ts index 5437ac2736792a..dbe727cbaa943b 100644 --- a/typings/primordials.d.ts +++ b/typings/primordials.d.ts @@ -545,6 +545,21 @@ declare namespace primordials { export const PromisePrototypeFinally: UncurryThis export const PromiseWithResolvers: typeof Promise.withResolvers export import Proxy = globalThis.Proxy + export import Iterator = globalThis.Iterator + export const IteratorFrom: typeof Iterator.from + export const IteratorPrototype: typeof Iterator.prototype + export const IteratorPrototypeDrop: UncurryThis + export const IteratorPrototypeEvery: UncurryThis + export const IteratorPrototypeFilter: UncurryThis + export const IteratorPrototypeFind: UncurryThis + export const IteratorPrototypeFlatMap: UncurryThis + export const IteratorPrototypeForEach: UncurryThis + export const IteratorPrototypeMap: UncurryThis + export const IteratorPrototypeReduce: UncurryThis + export const IteratorPrototypeSome: UncurryThis + export const IteratorPrototypeTake: UncurryThis + export const IteratorPrototypeToArray: UncurryThis + export const IteratorPrototypeSymbolIterator: UncurryMethod import _globalThis = globalThis export { _globalThis as globalThis } }