0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

refactor: use primordials for extensions/webidl (#11227)

This commit is contained in:
Luca Casonato 2021-07-02 16:37:41 +02:00 committed by GitHub
parent 68b4d60fd7
commit 4ae50f5c06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 145 additions and 79 deletions

View file

@ -167,6 +167,9 @@
primordials[name] = globalThis[name]; primordials[name] = globalThis[name];
}); });
// Create copy of isNaN
primordials[isNaN.name] = isNaN;
// Create copies of URI handling functions // Create copies of URI handling functions
[ [
decodeURI, decodeURI,

1
core/internal.d.ts vendored
View file

@ -68,6 +68,7 @@ declare namespace __bootstrap {
safe: T, safe: T,
): T; ): T;
export const isNaN: typeof globalThis.isNaN;
export const decodeURI: typeof globalThis.decodeURI; export const decodeURI: typeof globalThis.decodeURI;
export const decodeURIComponent: typeof globalThis.decodeURIComponent; export const decodeURIComponent: typeof globalThis.decodeURIComponent;
export const encodeURI: typeof globalThis.encodeURI; export const encodeURI: typeof globalThis.encodeURI;

View file

@ -4,13 +4,74 @@
// Copyright Domenic Denicola. Licensed under BSD-2-Clause License. // Copyright Domenic Denicola. Licensed under BSD-2-Clause License.
// Original license at https://github.com/jsdom/webidl-conversions/blob/master/LICENSE.md. // Original license at https://github.com/jsdom/webidl-conversions/blob/master/LICENSE.md.
/// <reference path="../../core/internal.d.ts" />
"use strict"; "use strict";
((window) => { ((window) => {
const {
ArrayBuffer,
ArrayBufferIsView,
ArrayPrototypePush,
ArrayPrototypeSort,
BigInt,
BigIntAsIntN,
BigIntAsUintN,
DataView,
Float32Array,
Float64Array,
FunctionPrototypeBind,
Int16Array,
Int32Array,
Int8Array,
isNaN,
MathFloor,
MathFround,
MathMax,
MathMin,
MathPow,
MathRound,
MathTrunc,
Number,
NumberIsFinite,
NumberIsNaN,
// deno-lint-ignore camelcase
NumberMAX_SAFE_INTEGER,
// deno-lint-ignore camelcase
NumberMIN_SAFE_INTEGER,
ObjectCreate,
ObjectDefineProperties,
ObjectDefineProperty,
ObjectGetOwnPropertyDescriptor,
ObjectGetOwnPropertyDescriptors,
ObjectGetPrototypeOf,
ObjectIs,
PromisePrototypeThen,
PromiseReject,
PromiseResolve,
ReflectApply,
ReflectDefineProperty,
ReflectGetOwnPropertyDescriptor,
ReflectOwnKeys,
RegExpPrototypeTest,
Set,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBuffer,
String,
StringFromCodePoint,
StringPrototypeCharCodeAt,
StringPrototypeCodePointAt,
Symbol,
SymbolIterator,
SymbolToStringTag,
TypeError,
Uint16Array,
Uint32Array,
Uint8Array,
Uint8ClampedArray,
} = window.__bootstrap.primordials;
function makeException(ErrorType, message, opts = {}) { function makeException(ErrorType, message, opts = {}) {
if (opts.globals) {
ErrorType = opts.globals[ErrorType.name];
}
return new ErrorType( return new ErrorType(
`${opts.prefix ? opts.prefix + ": " : ""}${ `${opts.prefix ? opts.prefix + ": " : ""}${
opts.context ? opts.context : "Value" opts.context ? opts.context : "Value"
@ -18,14 +79,11 @@
); );
} }
function toNumber(value, opts = {}) { function toNumber(value) {
if (!opts.globals) {
return +value;
}
if (typeof value === "bigint") { if (typeof value === "bigint") {
throw opts.globals.TypeError("Cannot convert a BigInt value to a number"); throw TypeError("Cannot convert a BigInt value to a number");
} }
return opts.globals.Number(value); return Number(value);
} }
function type(V) { function type(V) {
@ -73,14 +131,14 @@
(x > 0 && x % 1 === +0.5 && (x & 1) === 0) || (x > 0 && x % 1 === +0.5 && (x & 1) === 0) ||
(x < 0 && x % 1 === -0.5 && (x & 1) === 1) (x < 0 && x % 1 === -0.5 && (x & 1) === 1)
) { ) {
return censorNegativeZero(Math.floor(x)); return censorNegativeZero(MathFloor(x));
} }
return censorNegativeZero(Math.round(x)); return censorNegativeZero(MathRound(x));
} }
function integerPart(n) { function integerPart(n) {
return censorNegativeZero(Math.trunc(n)); return censorNegativeZero(MathTrunc(n));
} }
function sign(x) { function sign(x) {
@ -107,25 +165,25 @@
let lowerBound; let lowerBound;
let upperBound; let upperBound;
if (bitLength === 64) { if (bitLength === 64) {
upperBound = Number.MAX_SAFE_INTEGER; upperBound = NumberMAX_SAFE_INTEGER;
lowerBound = !isSigned ? 0 : Number.MIN_SAFE_INTEGER; lowerBound = !isSigned ? 0 : NumberMIN_SAFE_INTEGER;
} else if (!isSigned) { } else if (!isSigned) {
lowerBound = 0; lowerBound = 0;
upperBound = Math.pow(2, bitLength) - 1; upperBound = MathPow(2, bitLength) - 1;
} else { } else {
lowerBound = -Math.pow(2, bitLength - 1); lowerBound = -MathPow(2, bitLength - 1);
upperBound = Math.pow(2, bitLength - 1) - 1; upperBound = MathPow(2, bitLength - 1) - 1;
} }
const twoToTheBitLength = Math.pow(2, bitLength); const twoToTheBitLength = MathPow(2, bitLength);
const twoToOneLessThanTheBitLength = Math.pow(2, bitLength - 1); const twoToOneLessThanTheBitLength = MathPow(2, bitLength - 1);
return (V, opts = {}) => { return (V, opts = {}) => {
let x = toNumber(V, opts); let x = toNumber(V, opts);
x = censorNegativeZero(x); x = censorNegativeZero(x);
if (opts.enforceRange) { if (opts.enforceRange) {
if (!Number.isFinite(x)) { if (!NumberIsFinite(x)) {
throw makeException(TypeError, "is not a finite number", opts); throw makeException(TypeError, "is not a finite number", opts);
} }
@ -142,13 +200,13 @@
return x; return x;
} }
if (!Number.isNaN(x) && opts.clamp) { if (!NumberIsNaN(x) && opts.clamp) {
x = Math.min(Math.max(x, lowerBound), upperBound); x = MathMin(MathMax(x, lowerBound), upperBound);
x = evenRound(x); x = evenRound(x);
return x; return x;
} }
if (!Number.isFinite(x) || x === 0) { if (!NumberIsFinite(x) || x === 0) {
return 0; return 0;
} }
x = integerPart(x); x = integerPart(x);
@ -169,16 +227,16 @@
} }
function createLongLongConversion(bitLength, { unsigned }) { function createLongLongConversion(bitLength, { unsigned }) {
const upperBound = Number.MAX_SAFE_INTEGER; const upperBound = NumberMAX_SAFE_INTEGER;
const lowerBound = unsigned ? 0 : Number.MIN_SAFE_INTEGER; const lowerBound = unsigned ? 0 : NumberMIN_SAFE_INTEGER;
const asBigIntN = unsigned ? BigInt.asUintN : BigInt.asIntN; const asBigIntN = unsigned ? BigIntAsUintN : BigIntAsIntN;
return (V, opts = {}) => { return (V, opts = {}) => {
let x = toNumber(V, opts); let x = toNumber(V, opts);
x = censorNegativeZero(x); x = censorNegativeZero(x);
if (opts.enforceRange) { if (opts.enforceRange) {
if (!Number.isFinite(x)) { if (!NumberIsFinite(x)) {
throw makeException(TypeError, "is not a finite number", opts); throw makeException(TypeError, "is not a finite number", opts);
} }
@ -195,13 +253,13 @@
return x; return x;
} }
if (!Number.isNaN(x) && opts.clamp) { if (!NumberIsNaN(x) && opts.clamp) {
x = Math.min(Math.max(x, lowerBound), upperBound); x = MathMin(MathMax(x, lowerBound), upperBound);
x = evenRound(x); x = evenRound(x);
return x; return x;
} }
if (!Number.isFinite(x) || x === 0) { if (!NumberIsFinite(x) || x === 0) {
return 0; return 0;
} }
@ -240,7 +298,7 @@
converters.float = (V, opts) => { converters.float = (V, opts) => {
const x = toNumber(V, opts); const x = toNumber(V, opts);
if (!Number.isFinite(x)) { if (!NumberIsFinite(x)) {
throw makeException( throw makeException(
TypeError, TypeError,
"is not a finite floating-point value", "is not a finite floating-point value",
@ -248,13 +306,13 @@
); );
} }
if (Object.is(x, -0)) { if (ObjectIs(x, -0)) {
return x; return x;
} }
const y = Math.fround(x); const y = MathFround(x);
if (!Number.isFinite(y)) { if (!NumberIsFinite(y)) {
throw makeException( throw makeException(
TypeError, TypeError,
"is outside the range of a single-precision floating-point value", "is outside the range of a single-precision floating-point value",
@ -272,17 +330,17 @@
return x; return x;
} }
if (Object.is(x, -0)) { if (ObjectIs(x, -0)) {
return x; return x;
} }
return Math.fround(x); return MathFround(x);
}; };
converters.double = (V, opts) => { converters.double = (V, opts) => {
const x = toNumber(V, opts); const x = toNumber(V, opts);
if (!Number.isFinite(x)) { if (!NumberIsFinite(x)) {
throw makeException( throw makeException(
TypeError, TypeError,
"is not a finite floating-point value", "is not a finite floating-point value",
@ -312,14 +370,13 @@
); );
} }
const StringCtor = opts.globals ? opts.globals.String : String; return String(V);
return StringCtor(V);
}; };
converters.ByteString = (V, opts) => { converters.ByteString = (V, opts) => {
const x = converters.DOMString(V, opts); const x = converters.DOMString(V, opts);
let c; let c;
for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) { for (let i = 0; (c = StringPrototypeCodePointAt(x, i)) !== undefined; ++i) {
if (c > 255) { if (c > 255) {
throw makeException(TypeError, "is not a valid ByteString", opts); throw makeException(TypeError, "is not a valid ByteString", opts);
} }
@ -333,22 +390,22 @@
const n = S.length; const n = S.length;
let U = ""; let U = "";
for (let i = 0; i < n; ++i) { for (let i = 0; i < n; ++i) {
const c = S.charCodeAt(i); const c = StringPrototypeCharCodeAt(S, i);
if (c < 0xd800 || c > 0xdfff) { if (c < 0xd800 || c > 0xdfff) {
U += String.fromCodePoint(c); U += StringFromCodePoint(c);
} else if (0xdc00 <= c && c <= 0xdfff) { } else if (0xdc00 <= c && c <= 0xdfff) {
U += String.fromCodePoint(0xfffd); U += StringFromCodePoint(0xfffd);
} else if (i === n - 1) { } else if (i === n - 1) {
U += String.fromCodePoint(0xfffd); U += StringFromCodePoint(0xfffd);
} else { } else {
const d = S.charCodeAt(i + 1); const d = StringPrototypeCharCodeAt(S, i + 1);
if (0xdc00 <= d && d <= 0xdfff) { if (0xdc00 <= d && d <= 0xdfff) {
const a = c & 0x3ff; const a = c & 0x3ff;
const b = d & 0x3ff; const b = d & 0x3ff;
U += String.fromCodePoint((2 << 15) + (2 << 9) * a + b); U += StringFromCodePoint((2 << 15) + (2 << 9) * a + b);
++i; ++i;
} else { } else {
U += String.fromCodePoint(0xfffd); U += StringFromCodePoint(0xfffd);
} }
} }
} }
@ -436,9 +493,9 @@
// if the `this` value isn't a valid `TypedArray` object. // if the `this` value isn't a valid `TypedArray` object.
// //
// https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag // https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
const typedArrayNameGetter = Object.getOwnPropertyDescriptor( const typedArrayNameGetter = ObjectGetOwnPropertyDescriptor(
Object.getPrototypeOf(Uint8Array).prototype, ObjectGetPrototypeOf(Uint8Array).prototype,
Symbol.toStringTag, SymbolToStringTag,
).get; ).get;
[ [
Int8Array, Int8Array,
@ -452,9 +509,9 @@
Float64Array, Float64Array,
].forEach((func) => { ].forEach((func) => {
const name = func.name; const name = func.name;
const article = /^[AEIOU]/.test(name) ? "an" : "a"; const article = RegExpPrototypeTest(/^[AEIOU]/, name) ? "an" : "a";
converters[name] = (V, opts = {}) => { converters[name] = (V, opts = {}) => {
if (!ArrayBuffer.isView(V) || typedArrayNameGetter.call(V) !== name) { if (!ArrayBufferIsView(V) || typedArrayNameGetter.call(V) !== name) {
throw makeException( throw makeException(
TypeError, TypeError,
`is not ${article} ${name} object`, `is not ${article} ${name} object`,
@ -483,7 +540,7 @@
// Common definitions // Common definitions
converters.ArrayBufferView = (V, opts = {}) => { converters.ArrayBufferView = (V, opts = {}) => {
if (!ArrayBuffer.isView(V)) { if (!ArrayBufferIsView(V)) {
throw makeException( throw makeException(
TypeError, TypeError,
"is not a view on an ArrayBuffer or SharedArrayBuffer", "is not a view on an ArrayBuffer or SharedArrayBuffer",
@ -510,7 +567,7 @@
}; };
converters.BufferSource = (V, opts = {}) => { converters.BufferSource = (V, opts = {}) => {
if (ArrayBuffer.isView(V)) { if (ArrayBufferIsView(V)) {
if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) {
throw makeException( throw makeException(
TypeError, TypeError,
@ -616,10 +673,10 @@
if (member.required) { if (member.required) {
hasRequiredKey = true; hasRequiredKey = true;
} }
allMembers.push(member); ArrayPrototypePush(allMembers, member);
} }
} }
allMembers.sort((a, b) => { ArrayPrototypeSort(allMembers, (a, b) => {
if (a.key == b.key) { if (a.key == b.key) {
return 0; return 0;
} }
@ -640,7 +697,7 @@
) { ) {
defaultValues[member.key] = idlMemberValue; defaultValues[member.key] = idlMemberValue;
} else { } else {
Object.defineProperty(defaultValues, member.key, { ObjectDefineProperty(defaultValues, member.key, {
get() { get() {
return member.defaultValue; return member.defaultValue;
}, },
@ -745,7 +802,7 @@
opts, opts,
); );
} }
const iter = V?.[Symbol.iterator]?.(); const iter = V?.[SymbolIterator]?.();
if (iter === undefined) { if (iter === undefined) {
throw makeException( throw makeException(
TypeError, TypeError,
@ -768,7 +825,7 @@
...opts, ...opts,
context: `${opts.context}, index ${array.length}`, context: `${opts.context}, index ${array.length}`,
}); });
array.push(val); ArrayPrototypePush(array, val);
} }
return array; return array;
}; };
@ -783,10 +840,10 @@
opts, opts,
); );
} }
const keys = Reflect.ownKeys(V); const keys = ReflectOwnKeys(V);
const result = {}; const result = {};
for (const key of keys) { for (const key of keys) {
const desc = Object.getOwnPropertyDescriptor(V, key); const desc = ObjectGetOwnPropertyDescriptor(V, key);
if (desc !== undefined && desc.enumerable === true) { if (desc !== undefined && desc.enumerable === true) {
const typedKey = keyConverter(key, opts); const typedKey = keyConverter(key, opts);
const value = V[key]; const value = V[key];
@ -799,7 +856,8 @@
} }
function createPromiseConverter(converter) { function createPromiseConverter(converter) {
return (V, opts) => Promise.resolve(V).then((V) => converter(V, opts)); return (V, opts) =>
PromisePrototypeThen(PromiseResolve(V), (V) => converter(V, opts));
} }
function invokeCallbackFunction( function invokeCallbackFunction(
@ -810,14 +868,14 @@
opts, opts,
) { ) {
try { try {
const rv = Reflect.apply(callable, thisArg, args); const rv = ReflectApply(callable, thisArg, args);
return returnValueConverter(rv, { return returnValueConverter(rv, {
prefix: opts.prefix, prefix: opts.prefix,
context: "return value", context: "return value",
}); });
} catch (err) { } catch (err) {
if (opts.returnsPromise === true) { if (opts.returnsPromise === true) {
return Promise.reject(err); return PromiseReject(err);
} }
throw err; throw err;
} }
@ -834,8 +892,9 @@
}; };
} }
// TODO(lucacasonato): have the user pass in the prototype, and not the type.
function createBranded(Type) { function createBranded(Type) {
const t = Object.create(Type.prototype); const t = ObjectCreate(Type.prototype);
t[brand] = brand; t[brand] = brand;
return t; return t;
} }
@ -851,9 +910,9 @@
} }
function define(target, source) { function define(target, source) {
for (const key of Reflect.ownKeys(source)) { for (const key of ReflectOwnKeys(source)) {
const descriptor = Reflect.getOwnPropertyDescriptor(source, key); const descriptor = ReflectGetOwnPropertyDescriptor(source, key);
if (descriptor && !Reflect.defineProperty(target, key, descriptor)) { if (descriptor && !ReflectDefineProperty(target, key, descriptor)) {
throw new TypeError(`Cannot redefine property: ${String(key)}`); throw new TypeError(`Cannot redefine property: ${String(key)}`);
} }
} }
@ -861,12 +920,12 @@
const _iteratorInternal = Symbol("iterator internal"); const _iteratorInternal = Symbol("iterator internal");
const globalIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf( const globalIteratorPrototype = ObjectGetPrototypeOf(ObjectGetPrototypeOf(
[][Symbol.iterator](), [][SymbolIterator](),
)); ));
function mixinPairIterable(name, prototype, dataSymbol, keyKey, valueKey) { function mixinPairIterable(name, prototype, dataSymbol, keyKey, valueKey) {
const iteratorPrototype = Object.create(globalIteratorPrototype, { const iteratorPrototype = ObjectCreate(globalIteratorPrototype, {
[Symbol.toStringTag]: { configurable: true, value: `${name} Iterator` }, [Symbol.toStringTag]: { configurable: true, value: `${name} Iterator` },
}); });
define(iteratorPrototype, { define(iteratorPrototype, {
@ -901,8 +960,8 @@
}, },
}); });
function createDefaultIterator(target, kind) { function createDefaultIterator(target, kind) {
const iterator = Object.create(iteratorPrototype); const iterator = ObjectCreate(iteratorPrototype);
Object.defineProperty(iterator, _iteratorInternal, { ObjectDefineProperty(iterator, _iteratorInternal, {
value: { target, kind, index: 0 }, value: { target, kind, index: 0 },
configurable: true, configurable: true,
}); });
@ -921,7 +980,7 @@
enumerable: true, enumerable: true,
configurable: true, configurable: true,
}, },
[Symbol.iterator]: { [SymbolIterator]: {
value: entries, value: entries,
writable: true, writable: true,
enumerable: false, enumerable: false,
@ -954,7 +1013,10 @@
prefix, prefix,
context: "Argument 1", context: "Argument 1",
}); });
idlCallback = idlCallback.bind(thisArg ?? globalThis); idlCallback = FunctionPrototypeBind(
idlCallback,
thisArg ?? globalThis,
);
const pairs = this[dataSymbol]; const pairs = this[dataSymbol];
for (let i = 0; i < pairs.length; i++) { for (let i = 0; i < pairs.length; i++) {
const entry = pairs[i]; const entry = pairs[i];
@ -966,22 +1028,22 @@
configurable: true, configurable: true,
}, },
}; };
return Object.defineProperties(prototype.prototype, properties); return ObjectDefineProperties(prototype.prototype, properties);
} }
function configurePrototype(prototype) { function configurePrototype(prototype) {
const descriptors = Object.getOwnPropertyDescriptors(prototype.prototype); const descriptors = ObjectGetOwnPropertyDescriptors(prototype.prototype);
for (const key in descriptors) { for (const key in descriptors) {
if (key === "constructor") continue; if (key === "constructor") continue;
const descriptor = descriptors[key]; const descriptor = descriptors[key];
if ("value" in descriptor && typeof descriptor.value === "function") { if ("value" in descriptor && typeof descriptor.value === "function") {
Object.defineProperty(prototype.prototype, key, { ObjectDefineProperty(prototype.prototype, key, {
enumerable: true, enumerable: true,
writable: true, writable: true,
configurable: true, configurable: true,
}); });
} else if ("get" in descriptor) { } else if ("get" in descriptor) {
Object.defineProperty(prototype.prototype, key, { ObjectDefineProperty(prototype.prototype, key, {
enumerable: true, enumerable: true,
configurable: true, configurable: true,
}); });