Skip to content
Closed
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
63 changes: 37 additions & 26 deletions lib/internal/freeze_intrinsics.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const {
ArrayPrototype,
ArrayPrototypeForEach,
ArrayPrototypePush,
AsyncFunctionPrototype,
AsyncGeneratorFunctionPrototype,
AsyncGeneratorFunctionPrototypePrototype,
AsyncIteratorPrototype,
Atomics,
BigInt,
Expand All @@ -57,14 +60,19 @@ const {
Float64ArrayPrototype,
Function,
FunctionPrototype,
GeneratorFunctionPrototype,
GeneratorFunctionPrototypePrototype,
Int16Array,
Int16ArrayPrototype,
Int32Array,
Int32ArrayPrototype,
Int8Array,
Int8ArrayPrototype,
Iterator,
IteratorHelperPrototype,
IteratorPrototype,
Map,
MapIteratorPrototype,
MapPrototype,
Number,
NumberPrototype,
Expand All @@ -88,15 +96,15 @@ const {
ReflectOwnKeys,
RegExp,
RegExpPrototype,
RegExpStringIteratorPrototype,
SafeSet,
Set,
SetIteratorPrototype,
SetPrototype,
String,
StringIteratorPrototype,
StringPrototype,
Symbol,
SymbolIterator,
SymbolMatchAll,
SymbolPrototype,
SyntaxError,
SyntaxErrorPrototype,
Expand All @@ -120,6 +128,7 @@ const {
WeakRefPrototype,
WeakSet,
WeakSetPrototype,
WrapForValidIteratorPrototype,
decodeURI,
decodeURIComponent,
encodeURI,
Expand Down Expand Up @@ -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
Expand All @@ -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

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

Expand All @@ -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
Expand Down
88 changes: 63 additions & 25 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,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]()),
} },
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: '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 }) => {
Comment thread
aduh95 marked this conversation as resolved.
primordials[name] = original;
copyPrototype(original, primordials, name);
});

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

Expand Down Expand Up @@ -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);
Expand All @@ -406,6 +447,7 @@ primordials.makeSafe = makeSafe;
primordials.SafeMap = makeSafe(
Map,
class SafeMap extends Map {},
primordials.MapIteratorPrototypeNext,
);
primordials.SafeWeakMap = makeSafe(
WeakMap,
Expand All @@ -415,6 +457,7 @@ primordials.SafeWeakMap = makeSafe(
primordials.SafeSet = makeSafe(
Set,
class SafeSet extends Set {},
primordials.SetIteratorPrototypeNext,
);
primordials.SafeWeakSet = makeSafe(
WeakSet,
Expand Down Expand Up @@ -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(
Expand Down
34 changes: 32 additions & 2 deletions typings/primordials.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type TypedArrayContentType<T extends TypedArrayConstructor> = InstanceType<T>[nu
*/
declare namespace primordials {
export function uncurryThis<T extends (...args: unknown[]) => unknown>(fn: T): UncurryThis<T>;
export function makeSafe<T extends NewableFunction>(unsafe: NewableFunction, safe: T): T;
export function makeSafe<T extends NewableFunction>(unsafe: NewableFunction, safe: T, next?: Function): T;

export import decodeURI = globalThis.decodeURI;
export import decodeURIComponent = globalThis.decodeURIComponent;
Expand Down Expand Up @@ -168,7 +168,6 @@ declare namespace primordials {
export const ArrayBufferPrototypeSlice: UncurryThis<typeof ArrayBuffer.prototype.slice>
export const ArrayBufferPrototypeTransfer: UncurryThis<typeof ArrayBuffer.prototype.transfer>
export const ArrayBufferPrototypeGetByteLength: UncurryGetter<typeof ArrayBuffer.prototype , "byteLength">;
export const AsyncIteratorPrototype: AsyncIterable<any>;
export import BigInt = globalThis.BigInt;
export const BigIntPrototype: typeof BigInt.prototype
export const BigIntAsUintN: typeof BigInt.asUintN
Expand Down Expand Up @@ -545,6 +544,37 @@ 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>
export const ArrayIteratorPrototype: ReturnType<typeof Array.prototype[typeof Symbol.iterator]>
export const ArrayIteratorPrototypeNext: UncurryThis<typeof ArrayIteratorPrototype.next>
export const AsyncFunctionPrototype: Function
export const AsyncGeneratorFunctionPrototype: Function
export const AsyncIteratorPrototype: AsyncIterable<any>
export const GeneratorFunctionPrototype: Function
export const IteratorHelperPrototype: ReturnType<typeof Iterator.prototype.drop>
export const MapIteratorPrototype: ReturnType<typeof Map.prototype[typeof Symbol.iterator]>
export const MapIteratorPrototypeNext: UncurryThis<typeof MapIteratorPrototype.next>
export const RegExpStringIteratorPrototype: ReturnType<typeof RegExp.prototype[typeof Symbol.matchAll]>
export const RegExpStringIteratorPrototypeNext: UncurryThis<typeof RegExpStringIteratorPrototype.next>
export const SetIteratorPrototype: ReturnType<typeof Set.prototype[typeof Symbol.iterator]>
export const SetIteratorPrototypeNext: UncurryThis<typeof SetIteratorPrototype.next>
export const StringIteratorPrototype: ReturnType<typeof String.prototype[typeof Symbol.iterator]>
export const StringIteratorPrototypeNext: UncurryThis<typeof StringIteratorPrototype.next>
export const WrapForValidIteratorPrototype: ReturnType<typeof Iterator.from>
import _globalThis = globalThis
export { _globalThis as globalThis }
}
Loading