Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions lib/eslint.config_partial.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand Down Expand Up @@ -464,6 +460,7 @@ export default [
{ name: 'Int16Array' },
{ name: 'Int32Array' },
{ name: 'Int8Array' },
{ name: 'Iterator' },
{
name: 'isFinite',
into: 'Number',
Expand Down
68 changes: 42 additions & 26 deletions lib/internal/freeze_intrinsics.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ const {
Int32ArrayPrototype,
Int8Array,
Int8ArrayPrototype,
Iterator,
IteratorFrom,
IteratorPrototype,
IteratorPrototypeDrop,
Map,
MapPrototype,
MapPrototypeSymbolIterator,
Number,
NumberPrototype,
Object,
Expand All @@ -88,15 +92,15 @@ const {
ReflectOwnKeys,
RegExp,
RegExpPrototype,
RegExpPrototypeSymbolMatchAll,
SafeSet,
Set,
SetPrototype,
SetPrototypeSymbolIterator,
String,
StringIteratorPrototype,
StringPrototype,
Symbol,
SymbolIterator,
SymbolMatchAll,
SymbolPrototype,
SyntaxError,
SyntaxErrorPrototype,
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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

Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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
Expand Down
45 changes: 26 additions & 19 deletions lib/internal/per_context/primordials.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ function copyPrototype(src, dest, prefix) {
'Int16Array',
'Int32Array',
'Int8Array',
'Iterator',
'Map',
'Number',
'Object',
Expand Down Expand Up @@ -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
Expand All @@ -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]()),
} },
Comment thread
ljharb marked this conversation as resolved.
].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 }) => {
Comment on lines +261 to +274
Copy link
Copy Markdown
Contributor

@aduh95 aduh95 Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might as well put them all into primordials since we're using them. wdyt about droping the repeating Prototype since this whole section is prototype-only as reminded by the comment you added?

Suggested change
[
{
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 }) => {
Object.entries({
ArrayIterator: Reflect.getPrototypeOf(Array.prototype[Symbol.iterator]()),
AsyncFunction: Reflect.getPrototypeOf(async function() {}),
AsyncGeneratorFunction: Reflect.getPrototypeOf(async function*() {}),
AsyncIterator: Reflect.getPrototypeOf(Reflect.getPrototypeOf(async function*() {}).prototype),
GeneratorFunction: Reflect.getPrototypeOf(function*() {}),
IteratorHelper: Reflect.getPrototypeOf(primordials.IteratorPrototypeDrop({ __proto__: null }, null)),
MapIterator: Reflect.getPrototypeOf(new primordials.Map()[Symbol.iterator]()),
// eslint-disable-next-line regexp/no-empty-group
RegExpStringIterator: Reflect.getPrototypeOf(/(?:)/[Symbol.matchAll]()),
SetIterator: Reflect.getPrototypeOf(new primordials.Set()[Symbol.iterator]()),
StringIterator: Reflect.getPrototypeOf(String.prototype[Symbol.iterator]()),
WrapForValidIterator: Reflect.getPrototypeOf(primordials.IteratorFrom({ __proto__: null })),
}).forEach(({ 0: name, 1: original }) => {
name += 'Prototype';

primordials[name] = original;
copyPrototype(original, primordials, name);
});

/* eslint-enable node-core/prefer-primordials */

Expand Down Expand Up @@ -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(
Expand Down
15 changes: 15 additions & 0 deletions typings/primordials.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,21 @@ declare namespace primordials {
export const PromisePrototypeFinally: UncurryThis<typeof Promise.prototype.finally>
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<typeof Iterator.prototype.drop>
export const IteratorPrototypeEvery: UncurryThis<typeof Iterator.prototype.every>
export const IteratorPrototypeFilter: UncurryThis<typeof Iterator.prototype.filter>
export const IteratorPrototypeFind: UncurryThis<typeof Iterator.prototype.find>
export const IteratorPrototypeFlatMap: UncurryThis<typeof Iterator.prototype.flatMap>
export const IteratorPrototypeForEach: UncurryThis<typeof Iterator.prototype.forEach>
export const IteratorPrototypeMap: UncurryThis<typeof Iterator.prototype.map>
export const IteratorPrototypeReduce: UncurryThis<typeof Iterator.prototype.reduce>
export const IteratorPrototypeSome: UncurryThis<typeof Iterator.prototype.some>
export const IteratorPrototypeTake: UncurryThis<typeof Iterator.prototype.take>
export const IteratorPrototypeToArray: UncurryThis<typeof Iterator.prototype.toArray>
export const IteratorPrototypeSymbolIterator: UncurryMethod<typeof Iterator.prototype, typeof Symbol.iterator>
import _globalThis = globalThis
export { _globalThis as globalThis }
}
Loading