diff options
Diffstat (limited to 'src/js/internal/primordials.js')
-rw-r--r-- | src/js/internal/primordials.js | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/src/js/internal/primordials.js b/src/js/internal/primordials.js new file mode 100644 index 000000000..727ccffd4 --- /dev/null +++ b/src/js/internal/primordials.js @@ -0,0 +1,219 @@ +// TODO: Use native code and JSC intrinsics for everything in this file. +// Do not use this file for new code, many things here will be slow especailly when intrinsics for these operations is available. +// It is primarily used for `internal/util` + +const createSafeIterator = (factory, next) => { + class SafeIterator { + constructor(iterable) { + this._iterator = factory(iterable); + } + next() { + return next(this._iterator); + } + [Symbol.iterator]() { + return this; + } + } + Object.setPrototypeOf(SafeIterator.prototype, null); + Object.freeze(SafeIterator.prototype); + Object.freeze(SafeIterator); + return SafeIterator; +}; + +// Intrinsics do not have `call` as a valid identifier, so this cannot be `Function.prototype.call.bind`. +const FunctionPrototypeCall = $getByIdDirect(Function.prototype, "call"); + +function getGetter(cls, getter) { + // TODO: __lookupGetter__ is deprecated, but Object.getOwnPropertyDescriptor doesn't work on built-ins like Typed Arrays. + return FunctionPrototypeCall.bind(cls.prototype.__lookupGetter__(getter)); +} + +function uncurryThis(func) { + // Intrinsics do not have `call` as a valid identifier, so this cannot be `Function.prototype.call.bind`. + return FunctionPrototypeCall.bind(func); +} + +const copyProps = (src, dest) => { + ArrayPrototypeForEach(Reflect.ownKeys(src), key => { + if (!Reflect.getOwnPropertyDescriptor(dest, key)) { + Reflect.defineProperty(dest, key, Reflect.getOwnPropertyDescriptor(src, key)); + } + }); +}; + +const makeSafe = (unsafe, safe) => { + if (Symbol.iterator in unsafe.prototype) { + const dummy = new unsafe(); + let next; // We can reuse the same `next` method. + + ArrayPrototypeForEach(Reflect.ownKeys(unsafe.prototype), key => { + if (!Reflect.getOwnPropertyDescriptor(safe.prototype, key)) { + const desc = Reflect.getOwnPropertyDescriptor(unsafe.prototype, key); + if ( + typeof desc.value === "function" && + desc.value.length === 0 && + Symbol.iterator in (desc.value.$call(dummy) || {}) + ) { + const createIterator = uncurryThis(desc.value); + next ??= uncurryThis(createIterator(dummy).next); + const SafeIterator = createSafeIterator(createIterator, next); + desc.value = function () { + return new SafeIterator(this); + }; + } + Reflect.defineProperty(safe.prototype, key, desc); + } + }); + } else copyProps(unsafe.prototype, safe.prototype); + copyProps(unsafe, safe); + + Object.setPrototypeOf(safe.prototype, null); + Object.freeze(safe.prototype); + Object.freeze(safe); + return safe; +}; + +const StringIterator = uncurryThis(String.prototype[Symbol.iterator]); +const StringIteratorPrototype = Reflect.getPrototypeOf(StringIterator("")); +const ArrayPrototypeForEach = uncurryThis(Array.prototype.forEach); + +function ErrorCaptureStackTrace(targetObject) { + const stack = new Error().stack; + // Remove the second line, which is this function + targetObject.stack = stack.replace(/.*\n.*/, "$1"); +} + +const arrayProtoPush = Array.prototype.push; + +export default { + makeSafe, // exported for testing + Array, + ArrayFrom: Array.from, + ArrayIsArray: Array.isArray, + ArrayPrototypeFlat: uncurryThis(Array.prototype.flat), + ArrayPrototypeFilter: uncurryThis(Array.prototype.filter), + ArrayPrototypeForEach, + ArrayPrototypeIncludes: uncurryThis(Array.prototype.includes), + ArrayPrototypeIndexOf: uncurryThis(Array.prototype.indexOf), + ArrayPrototypeJoin: uncurryThis(Array.prototype.join), + ArrayPrototypeMap: uncurryThis(Array.prototype.map), + ArrayPrototypePop: uncurryThis(Array.prototype.pop), + ArrayPrototypePush: uncurryThis(arrayProtoPush), + ArrayPrototypePushApply: (a, b) => arrayProtoPush.$apply(a, b), + ArrayPrototypeSlice: uncurryThis(Array.prototype.slice), + ArrayPrototypeSort: uncurryThis(Array.prototype.sort), + ArrayPrototypeSplice: uncurryThis(Array.prototype.splice), + ArrayPrototypeUnshift: uncurryThis(Array.prototype.unshift), + BigIntPrototypeValueOf: uncurryThis(BigInt.prototype.valueOf), + BooleanPrototypeValueOf: uncurryThis(Boolean.prototype.valueOf), + DatePrototypeGetTime: uncurryThis(Date.prototype.getTime), + DatePrototypeToISOString: uncurryThis(Date.prototype.toISOString), + DatePrototypeToString: uncurryThis(Date.prototype.toString), + ErrorCaptureStackTrace, + ErrorPrototypeToString: uncurryThis(Error.prototype.toString), + FunctionPrototypeToString: uncurryThis(Function.prototype.toString), + JSONStringify: JSON.stringify, + MapPrototypeGetSize: getGetter(Map, "size"), + MapPrototypeEntries: uncurryThis(Map.prototype.entries), + MapPrototypeValues: uncurryThis(Map.prototype.values), + MapPrototypeKeys: uncurryThis(Map.prototype.keys), + MathFloor: Math.floor, + MathMax: Math.max, + MathMin: Math.min, + MathRound: Math.round, + MathSqrt: Math.sqrt, + MathTrunc: Math.trunc, + Number, + NumberIsFinite: Number.isFinite, + NumberIsNaN: Number.isNaN, + NumberParseFloat: Number.parseFloat, + NumberParseInt: Number.parseInt, + NumberPrototypeToString: uncurryThis(Number.prototype.toString), + NumberPrototypeValueOf: uncurryThis(Number.prototype.valueOf), + Object, + ObjectAssign: Object.assign, + ObjectCreate: Object.create, + ObjectDefineProperty: Object.defineProperty, + ObjectEntries: Object.entries, + ObjectGetOwnPropertyDescriptor: Object.getOwnPropertyDescriptor, + ObjectGetOwnPropertyDescriptors: Object.getOwnPropertyDescriptors, + ObjectGetOwnPropertyNames: Object.getOwnPropertyNames, + ObjectGetOwnPropertySymbols: Object.getOwnPropertySymbols, + ObjectGetPrototypeOf: Object.getPrototypeOf, + ObjectIs: Object.is, + ObjectKeys: Object.keys, + ObjectPrototypeHasOwnProperty: uncurryThis(Object.prototype.hasOwnProperty), + ObjectPrototypePropertyIsEnumerable: uncurryThis(Object.prototype.propertyIsEnumerable), + ObjectPrototypeToString: uncurryThis(Object.prototype.toString), + ObjectSeal: Object.seal, + ObjectSetPrototypeOf: Object.setPrototypeOf, + ReflectApply: $getByIdDirect(Reflect, "apply"), + ReflectOwnKeys: Reflect.ownKeys, + RegExp, + RegExpPrototypeExec: uncurryThis(RegExp.prototype.exec), + RegExpPrototypeSymbolReplace: uncurryThis(RegExp.prototype[Symbol.replace]), + RegExpPrototypeSymbolSplit: uncurryThis(RegExp.prototype[Symbol.split]), + RegExpPrototypeTest: uncurryThis(RegExp.prototype.test), + RegExpPrototypeToString: uncurryThis(RegExp.prototype.toString), + SafeStringIterator: createSafeIterator(StringIterator, uncurryThis(StringIteratorPrototype.next)), + SafeMap: makeSafe( + Map, + class SafeMap extends Map { + constructor(i) { + super(i); + } + }, + ), + SafeSet: makeSafe( + Set, + class SafeSet extends Set { + constructor(i) { + super(i); + } + }, + ), + SetPrototypeGetSize: getGetter(Set, "size"), + SetPrototypeEntries: uncurryThis(Set.prototype.entries), + SetPrototypeValues: uncurryThis(Set.prototype.values), + String, + StringPrototypeCharCodeAt: uncurryThis(String.prototype.charCodeAt), + StringPrototypeCodePointAt: uncurryThis(String.prototype.codePointAt), + StringPrototypeEndsWith: uncurryThis(String.prototype.endsWith), + StringPrototypeIncludes: uncurryThis(String.prototype.includes), + StringPrototypeIndexOf: uncurryThis(String.prototype.indexOf), + StringPrototypeLastIndexOf: uncurryThis(String.prototype.lastIndexOf), + StringPrototypeMatch: uncurryThis(String.prototype.match), + StringPrototypeNormalize: uncurryThis(String.prototype.normalize), + StringPrototypePadEnd: uncurryThis(String.prototype.padEnd), + StringPrototypePadStart: uncurryThis(String.prototype.padStart), + StringPrototypeRepeat: uncurryThis(String.prototype.repeat), + StringPrototypeReplace: uncurryThis(String.prototype.replace), + StringPrototypeReplaceAll: uncurryThis(String.prototype.replaceAll), + StringPrototypeSlice: uncurryThis(String.prototype.slice), + StringPrototypeSplit: uncurryThis(String.prototype.split), + StringPrototypeStartsWith: uncurryThis(String.prototype.startsWith), + StringPrototypeToLowerCase: uncurryThis(String.prototype.toLowerCase), + StringPrototypeTrim: uncurryThis(String.prototype.trim), + StringPrototypeValueOf: uncurryThis(String.prototype.valueOf), + SymbolPrototypeToString: uncurryThis(Symbol.prototype.toString), + SymbolPrototypeValueOf: uncurryThis(Symbol.prototype.valueOf), + FunctionPrototypeToString: uncurryThis(Function.prototype.toString), + FunctionPrototypeBind: uncurryThis(Function.prototype.bind), + SymbolIterator: Symbol.iterator, + SymbolFor: Symbol.for, + SymbolToStringTag: Symbol.toStringTag, + TypedArrayPrototypeGetLength: getGetter(Uint8Array, "length"), + TypedArrayPrototypeGetSymbolToStringTag: getGetter(Uint8Array, Symbol.toStringTag), + Uint8ClampedArray, + Uint8Array, + Uint16Array, + Uint32Array, + Int8Array, + Int16Array, + Int32Array, + Float32Array, + Float64Array, + BigUint64Array, + BigInt64Array, + uncurryThis, +}; |