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..05437199726cb3 100644 --- a/lib/internal/freeze_intrinsics.js +++ b/lib/internal/freeze_intrinsics.js @@ -31,6 +31,9 @@ const { ArrayPrototype, ArrayPrototypeForEach, ArrayPrototypePush, + AsyncFunctionPrototype, + AsyncGeneratorFunctionPrototype, + AsyncGeneratorFunctionPrototypePrototype, AsyncIteratorPrototype, Atomics, BigInt, @@ -57,14 +60,19 @@ const { Float64ArrayPrototype, Function, FunctionPrototype, + GeneratorFunctionPrototype, + GeneratorFunctionPrototypePrototype, Int16Array, Int16ArrayPrototype, Int32Array, Int32ArrayPrototype, Int8Array, Int8ArrayPrototype, + Iterator, + IteratorHelperPrototype, IteratorPrototype, Map, + MapIteratorPrototype, MapPrototype, Number, NumberPrototype, @@ -88,15 +96,15 @@ const { ReflectOwnKeys, RegExp, RegExpPrototype, + RegExpStringIteratorPrototype, SafeSet, Set, + SetIteratorPrototype, SetPrototype, String, StringIteratorPrototype, StringPrototype, Symbol, - SymbolIterator, - SymbolMatchAll, SymbolPrototype, SyntaxError, SyntaxErrorPrototype, @@ -120,6 +128,7 @@ const { WeakRefPrototype, WeakSet, WeakSetPrototype, + WrapForValidIteratorPrototype, decodeURI, decodeURIComponent, encodeURI, @@ -173,8 +182,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 +203,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 +218,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 + GeneratorFunctionPrototypePrototype, + // 27.6 AsyncGeneratorPrototype + AsyncGeneratorFunctionPrototypePrototype, + AsyncFunctionPrototype, // 27.7 // Other APIs / Web Compatibility Console.prototype, @@ -268,8 +282,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 +303,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 +321,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..49576c2d949764 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,68 @@ 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: 'AsyncFunctionPrototype', + original: Reflect.getPrototypeOf(async function() {}), + }, + { + name: 'AsyncGeneratorFunctionPrototype', + original: Reflect.getPrototypeOf(async function*() {}), + }, + { + name: 'AsyncIteratorPrototype', + original: Reflect.getPrototypeOf(Reflect.getPrototypeOf(async function*() {}).prototype), + }, + { + name: 'GeneratorFunctionPrototype', + original: Reflect.getPrototypeOf(function*() {}), + }, + { + name: 'IteratorHelperPrototype', + original: Reflect.getPrototypeOf(primordials.IteratorPrototypeDrop({ __proto__: null }, null)), + }, + { + name: 'MapIteratorPrototype', + original: Reflect.getPrototypeOf(new primordials.Map()[Symbol.iterator]()), + }, + { + name: 'RegExpStringIteratorPrototype', + original: Reflect.getPrototypeOf(primordials.RegExp.prototype[Symbol.matchAll]()), + }, + { + name: 'SetIteratorPrototype', + original: Reflect.getPrototypeOf(new primordials.Set()[Symbol.iterator]()), + }, + { + name: 'StringIteratorPrototype', + original: Reflect.getPrototypeOf(String.prototype[Symbol.iterator]()), + }, + { + name: 'WrapForValidIteratorPrototype', + original: Reflect.getPrototypeOf(primordials.IteratorFrom({ __proto__: null })), + }, +].forEach(({ name, original }) => { + primordials[name] = original; + copyPrototype(original, primordials, name); +}); /* eslint-enable node-core/prefer-primordials */ @@ -366,21 +410,18 @@ const copyProps = (src, dest) => { /** * @type {typeof primordials.makeSafe} */ -const makeSafe = (unsafe, safe) => { - if (SymbolIterator in unsafe.prototype) { +const makeSafe = (unsafe, safe, next) => { + if (next) { const dummy = new unsafe(); - let next; // We can reuse the same `next` method. - ArrayPrototypeForEach(ReflectOwnKeys(unsafe.prototype), (key) => { if (!ReflectGetOwnPropertyDescriptor(safe.prototype, key)) { const desc = ReflectGetOwnPropertyDescriptor(unsafe.prototype, key); if ( typeof desc.value === 'function' && desc.value.length === 0 && - SymbolIterator in (FunctionPrototypeCall(desc.value, dummy) ?? {}) + FunctionPrototypeCall(desc.value, dummy)?.next === next ) { const createIterator = uncurryThis(desc.value); - next ??= uncurryThis(createIterator(dummy).next); const SafeIterator = createSafeIterator(createIterator, next); desc.value = function() { return new SafeIterator(this); @@ -406,6 +447,7 @@ primordials.makeSafe = makeSafe; primordials.SafeMap = makeSafe( Map, class SafeMap extends Map {}, + primordials.MapIteratorPrototypeNext, ); primordials.SafeWeakMap = makeSafe( WeakMap, @@ -415,6 +457,7 @@ primordials.SafeWeakMap = makeSafe( primordials.SafeSet = makeSafe( Set, class SafeSet extends Set {}, + primordials.SetIteratorPrototypeNext, ); primordials.SafeWeakSet = makeSafe( WeakSet, @@ -453,11 +496,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..7a424c7295028d 100644 --- a/typings/primordials.d.ts +++ b/typings/primordials.d.ts @@ -40,7 +40,7 @@ type TypedArrayContentType = InstanceType[nu */ declare namespace primordials { export function uncurryThis unknown>(fn: T): UncurryThis; - export function makeSafe(unsafe: NewableFunction, safe: T): T; + export function makeSafe(unsafe: NewableFunction, safe: T, next?: Function): T; export import decodeURI = globalThis.decodeURI; export import decodeURIComponent = globalThis.decodeURIComponent; @@ -168,7 +168,6 @@ declare namespace primordials { export const ArrayBufferPrototypeSlice: UncurryThis export const ArrayBufferPrototypeTransfer: UncurryThis export const ArrayBufferPrototypeGetByteLength: UncurryGetter; - export const AsyncIteratorPrototype: AsyncIterable; export import BigInt = globalThis.BigInt; export const BigIntPrototype: typeof BigInt.prototype export const BigIntAsUintN: typeof BigInt.asUintN @@ -545,6 +544,37 @@ 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 + export const ArrayIteratorPrototype: ReturnType + export const ArrayIteratorPrototypeNext: UncurryThis + export const AsyncFunctionPrototype: Function + export const AsyncGeneratorFunctionPrototype: Function + export const AsyncIteratorPrototype: AsyncIterable + export const GeneratorFunctionPrototype: Function + export const IteratorHelperPrototype: ReturnType + export const MapIteratorPrototype: ReturnType + export const MapIteratorPrototypeNext: UncurryThis + export const RegExpStringIteratorPrototype: ReturnType + export const RegExpStringIteratorPrototypeNext: UncurryThis + export const SetIteratorPrototype: ReturnType + export const SetIteratorPrototypeNext: UncurryThis + export const StringIteratorPrototype: ReturnType + export const StringIteratorPrototypeNext: UncurryThis + export const WrapForValidIteratorPrototype: ReturnType import _globalThis = globalThis export { _globalThis as globalThis } }