fix: strict type check for cross realms (#21669)

Deno v1.39 introduces `vm.runInNewContext`. This may cause problems when
using `Object.prototype.isPrototypeOf` to check built-in types.

```js
import vm from "node:vm";

const err = new Error();
const crossErr = vm.runInNewContext(`new Error()`);

console.assert( !(crossErr instanceof Error) );
console.assert( Object.getPrototypeOf(err) !== Object.getPrototypeOf(crossErr) );
```

This PR changes to check using internal slots solves them.

---

current: 

```
> import vm from "node:vm";
undefined
> vm.runInNewContext(`new Error("message")`)
Error {}
> vm.runInNewContext(`new Date("2018-12-10T02:26:59.002Z")`)
Date {}
```

this PR:

```
> import vm from "node:vm";
undefined
> vm.runInNewContext(`new Error("message")`)
Error: message
    at <anonymous>:1:1
> vm.runInNewContext(`new Date("2018-12-10T02:26:59.002Z")`)
2018-12-10T02:26:59.002Z
```

---------

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
Kenta Moriuchi 2024-01-04 13:12:38 +09:00 committed by GitHub
parent 4855674857
commit b2cd254c35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 532 additions and 906 deletions

View File

@ -16,14 +16,12 @@ const {
ArrayPrototypeShift,
DateNow,
Error,
FunctionPrototype,
Map,
MapPrototypeGet,
MapPrototypeHas,
MapPrototypeSet,
MathCeil,
ObjectKeys,
ObjectPrototypeIsPrototypeOf,
Promise,
SafeArrayIterator,
Set,
@ -1294,7 +1292,7 @@ function createTestContext(desc) {
let stepDesc;
if (typeof nameOrFnOrOptions === "string") {
if (!(ObjectPrototypeIsPrototypeOf(FunctionPrototype, maybeFn))) {
if (typeof maybeFn !== "function") {
throw new TypeError("Expected function for second argument.");
}
stepDesc = {

View File

@ -52,6 +52,7 @@ util::unit_test_factory!(
assertion_error_test,
buffer_test,
child_process_test,
console_test,
crypto_cipher_test = crypto / crypto_cipher_test,
crypto_cipher_gcm_test = crypto / crypto_cipher_gcm_test,
crypto_hash_test = crypto / crypto_hash_test,

View File

@ -1845,18 +1845,36 @@ Deno.test(function consoleLogShouldNotThrowErrorWhenInvalidDateIsPassed() {
// console.log(new Proxy(new Set(), {}))
Deno.test(function consoleLogShouldNotThrowErrorWhenInputIsProxiedSet() {
mockConsole((console, out) => {
const proxiedSet = new Proxy(new Set(), {});
const proxiedSet = new Proxy(new Set([1, 2]), {});
console.log(proxiedSet);
assertEquals(stripColor(out.toString()), "Set {}\n");
assertEquals(stripColor(out.toString()), "Set(2) { 1, 2 }\n");
});
});
// console.log(new Proxy(new Map(), {}))
Deno.test(function consoleLogShouldNotThrowErrorWhenInputIsProxiedMap() {
mockConsole((console, out) => {
const proxiedMap = new Proxy(new Map(), {});
const proxiedMap = new Proxy(new Map([[1, 1], [2, 2]]), {});
console.log(proxiedMap);
assertEquals(stripColor(out.toString()), "Map {}\n");
assertEquals(stripColor(out.toString()), "Map(2) { 1 => 1, 2 => 2 }\n");
});
});
// console.log(new Proxy(new Uint8Array(), {}))
Deno.test(function consoleLogShouldNotThrowErrorWhenInputIsProxiedTypedArray() {
mockConsole((console, out) => {
const proxiedUint8Array = new Proxy(new Uint8Array([1, 2]), {});
console.log(proxiedUint8Array);
assertEquals(stripColor(out.toString()), "Uint8Array(2) [ 1, 2 ]\n");
});
});
// console.log(new Proxy(new RegExp(), {}))
Deno.test(function consoleLogShouldNotThrowErrorWhenInputIsProxiedRegExp() {
mockConsole((console, out) => {
const proxiedRegExp = new Proxy(/aaaa/, {});
console.log(proxiedRegExp);
assertEquals(stripColor(out.toString()), "/aaaa/\n");
});
});
@ -1869,6 +1887,15 @@ Deno.test(function consoleLogShouldNotThrowErrorWhenInputIsProxiedDate() {
});
});
// console.log(new Proxy(new Error(), {}))
Deno.test(function consoleLogShouldNotThrowErrorWhenInputIsProxiedError() {
mockConsole((console, out) => {
const proxiedError = new Proxy(new Error("message"), {});
console.log(proxiedError);
assertStringIncludes(stripColor(out.toString()), "Error: message\n");
});
});
// console.dir test
Deno.test(function consoleDir() {
mockConsole((console, out) => {

View File

@ -0,0 +1,28 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import vm from "node:vm";
import { stripColor } from "../../../test_util/std/fmt/colors.ts";
import { assertStringIncludes } from "../../../test_util/std/assert/mod.ts";
Deno.test(function inspectCrossRealmObjects() {
assertStringIncludes(
stripColor(
Deno.inspect(vm.runInNewContext(`new Error("This is an error")`)),
),
"Error: This is an error",
);
assertStringIncludes(
stripColor(
Deno.inspect(
vm.runInNewContext(`new AggregateError([], "This is an error")`),
),
),
"AggregateError: This is an error",
);
assertStringIncludes(
stripColor(
Deno.inspect(vm.runInNewContext(`new Date("2018-12-10T02:26:59.002Z")`)),
),
"2018-12-10T02:26:59.002Z",
);
});

View File

@ -8,6 +8,7 @@ import {
} from "../../../test_util/std/assert/mod.ts";
import { stripColor } from "../../../test_util/std/fmt/colors.ts";
import * as util from "node:util";
import { Buffer } from "node:buffer";
Deno.test({
name: "[util] format",
@ -130,9 +131,11 @@ Deno.test({
fn() {
const java = new Error();
const nodejs = Reflect.construct(Error, [], Object);
const bun = new DOMException();
const deno = "Future";
assert(util.isError(java));
assert(util.isError(nodejs));
assert(util.isError(bun));
assert(!util.isError(deno));
},
});
@ -190,6 +193,40 @@ Deno.test({
},
});
Deno.test({
name: "[util] isDate",
fn() {
// Test verifies the method is exposed. See _util/_util_types_test for details
assert(util.isDate(new Date()));
},
});
Deno.test({
name: "[util] isBuffer",
fn() {
assert(util.isBuffer(new Buffer(4)));
assert(!util.isBuffer(new Uint8Array(4)));
},
});
Deno.test({
name: "[util] types.isTypedArray",
fn() {
assert(util.types.isTypedArray(new Buffer(4)));
assert(util.types.isTypedArray(new Uint8Array(4)));
assert(!util.types.isTypedArray(new DataView(new ArrayBuffer(4))));
},
});
Deno.test({
name: "[util] types.isNativeError",
fn() {
assert(util.types.isNativeError(new Error()));
assert(util.types.isNativeError(new TypeError()));
assert(!util.types.isNativeError(new DOMException()));
},
});
Deno.test({
name: "[util] TextDecoder",
fn() {
@ -216,14 +253,6 @@ Deno.test({
},
});
Deno.test({
name: "[util] isDate",
fn() {
// Test verifies the method is exposed. See _util/_util_types_test for details
assert(util.types.isDate(new Date()));
},
});
Deno.test({
name: "[util] getSystemErrorName()",
fn() {

View File

@ -13,7 +13,7 @@ import {
setTarget,
} from "ext:deno_web/02_event.js";
import { defer } from "ext:deno_web/02_timers.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
const {
op_broadcast_recv,
op_broadcast_send,

View File

@ -4,9 +4,7 @@
import { core, internals, primordials } from "ext:core/mod.js";
const {
AggregateErrorPrototype,
Array,
ArrayBufferIsView,
ArrayBufferPrototypeGetByteLength,
ArrayIsArray,
ArrayPrototypeFill,
@ -29,18 +27,16 @@ const {
Boolean,
BooleanPrototypeValueOf,
DateNow,
DatePrototype,
DatePrototypeGetTime,
DatePrototypeToISOString,
Error,
ErrorCaptureStackTrace,
ErrorPrototype,
ErrorCaptureStackTrace,
ErrorPrototypeToString,
FunctionPrototypeBind,
FunctionPrototypeCall,
FunctionPrototypeToString,
NumberIsNaN,
MapPrototype,
MapPrototypeDelete,
MapPrototypeEntries,
MapPrototypeForEach,
@ -93,7 +89,6 @@ const {
SafeSet,
SafeSetIterator,
SafeStringIterator,
SetPrototype,
SetPrototypeAdd,
SetPrototypeHas,
SetPrototypeGetSize,
@ -128,12 +123,38 @@ const {
SymbolToStringTag,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetLength,
TypedArrayPrototypeGetSymbolToStringTag,
Uint8Array,
WeakMapPrototypeHas,
WeakSetPrototypeHas,
} = primordials;
const ops = core.ops;
const {
isAnyArrayBuffer,
isArgumentsObject,
isArrayBuffer,
isAsyncFunction,
isBigIntObject,
isBooleanObject,
isBoxedPrimitive,
isDataView,
isDate,
isGeneratorFunction,
isMap,
isMapIterator,
isModuleNamespaceObject,
isNativeError,
isNumberObject,
isPromise,
isRegExp,
isSet,
isSetIterator,
isStringObject,
isTypedArray,
isWeakSet,
isWeakMap,
} = core;
const {
op_get_non_index_property_names,
op_get_constructor_name,
op_preview_entries,
} = core.ensureFastOps(true);
let noColor = () => false;
@ -263,187 +284,17 @@ function getSharedArrayBufferByteLength(value) {
return FunctionPrototypeCall(_getSharedArrayBufferByteLength, value);
}
function isObjectLike(value) {
return value !== null && typeof value === "object";
}
function isAnyArrayBuffer(value) {
return ops.op_is_any_arraybuffer(value);
}
function isArgumentsObject(value) {
return core.isArgumentsObject(value);
}
function isArrayBuffer(value) {
try {
ArrayBufferPrototypeGetByteLength(value);
return true;
} catch {
return false;
}
}
function isAsyncFunction(value) {
return core.isAsyncFunction(value);
}
function isBooleanObject(value) {
if (!isObjectLike(value)) {
return false;
}
try {
BooleanPrototypeValueOf(value);
return true;
} catch {
return false;
}
}
function isBoxedPrimitive(
value,
) {
// The name property is used to allow cross realms to make a determination
// This is the same as WHATWG's structuredClone algorithm
// https://github.com/whatwg/html/pull/5150
function isAggregateError(value) {
return (
isBooleanObject(value) ||
isStringObject(value) ||
isNumberObject(value) ||
isSymbolObject(value) ||
isBigIntObject(value)
isNativeError(value) &&
value.name === "AggregateError" &&
ArrayIsArray(value.errors)
);
}
function isDataView(value) {
return (
ArrayBufferIsView(value) &&
TypedArrayPrototypeGetSymbolToStringTag(value) === undefined
);
}
function isTypedArray(value) {
return TypedArrayPrototypeGetSymbolToStringTag(value) !== undefined;
}
function isGeneratorFunction(value) {
return core.isGeneratorFunction(value);
}
function isMap(value) {
try {
MapPrototypeGetSize(value);
return true;
} catch {
return false;
}
}
function isMapIterator(value) {
return core.isMapIterator(value);
}
function isModuleNamespaceObject(value) {
return core.isModuleNamespaceObject(value);
}
function isNativeError(value) {
return core.isNativeError(value);
}
function isNumberObject(value) {
if (!isObjectLike(value)) {
return false;
}
try {
NumberPrototypeValueOf(value);
return true;
} catch {
return false;
}
}
function isBigIntObject(value) {
if (!isObjectLike(value)) {
return false;
}
try {
BigIntPrototypeValueOf(value);
return true;
} catch {
return false;
}
}
function isPromise(value) {
return core.isPromise(value);
}
function isRegExp(value) {
return core.isRegExp(value);
}
function isSet(value) {
try {
SetPrototypeGetSize(value);
return true;
} catch {
return false;
}
}
function isSetIterator(value) {
return core.isSetIterator(value);
}
function isStringObject(value) {
if (!isObjectLike(value)) {
return false;
}
try {
StringPrototypeValueOf(value);
return true;
} catch {
return false;
}
}
function isSymbolObject(value) {
if (!isObjectLike(value)) {
return false;
}
try {
SymbolPrototypeValueOf(value);
return true;
} catch {
return false;
}
}
function isWeakMap(
value,
) {
try {
WeakMapPrototypeHas(value, null);
return true;
} catch {
return false;
}
}
function isWeakSet(
value,
) {
try {
WeakSetPrototypeHas(value, null);
return true;
} catch {
return false;
}
}
const kObjectType = 0;
const kArrayType = 1;
const kArrayExtrasType = 2;
@ -778,7 +629,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) {
let extrasType = kObjectType;
if (proxyDetails != null && ctx.showProxy) {
if (proxyDetails !== null && ctx.showProxy) {
return `Proxy ` + formatValue(ctx, proxyDetails, recurseTimes);
} else {
// Iterators and the rest are split to reduce checks.
@ -791,7 +642,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) {
const prefix = (constructor !== "Array" || tag !== "")
? getPrefix(constructor, tag, "Array", `(${value.length})`)
: "";
keys = ops.op_get_non_index_property_names(value, filter);
keys = op_get_non_index_property_names(value, filter);
braces = [`${prefix}[`, "]"];
if (
value.length === 0 && keys.length === 0 && protoProps === undefined
@ -800,31 +651,43 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) {
}
extrasType = kArrayExtrasType;
formatter = formatArray;
} else if (isSet(value)) {
const size = SetPrototypeGetSize(value);
} else if (
(proxyDetails === null && isSet(value)) ||
(proxyDetails !== null && isSet(proxyDetails[0]))
) {
const set = proxyDetails?.[0] ?? value;
const size = SetPrototypeGetSize(set);
const prefix = getPrefix(constructor, tag, "Set", `(${size})`);
keys = getKeys(value, ctx.showHidden);
keys = getKeys(set, ctx.showHidden);
formatter = constructor !== null
? FunctionPrototypeBind(formatSet, null, value)
: FunctionPrototypeBind(formatSet, null, SetPrototypeValues(value));
? FunctionPrototypeBind(formatSet, null, set)
: FunctionPrototypeBind(formatSet, null, SetPrototypeValues(set));
if (size === 0 && keys.length === 0 && protoProps === undefined) {
return `${prefix}{}`;
}
braces = [`${prefix}{`, "}"];
} else if (isMap(value)) {
const size = MapPrototypeGetSize(value);
} else if (
(proxyDetails === null && isMap(value)) ||
(proxyDetails !== null && isMap(proxyDetails[0]))
) {
const map = proxyDetails?.[0] ?? value;
const size = MapPrototypeGetSize(map);
const prefix = getPrefix(constructor, tag, "Map", `(${size})`);
keys = getKeys(value, ctx.showHidden);
keys = getKeys(map, ctx.showHidden);
formatter = constructor !== null
? FunctionPrototypeBind(formatMap, null, value)
: FunctionPrototypeBind(formatMap, null, MapPrototypeEntries(value));
? FunctionPrototypeBind(formatMap, null, map)
: FunctionPrototypeBind(formatMap, null, MapPrototypeEntries(map));
if (size === 0 && keys.length === 0 && protoProps === undefined) {
return `${prefix}{}`;
}
braces = [`${prefix}{`, "}"];
} else if (isTypedArray(value)) {
keys = core.ops.op_get_non_index_property_names(value, filter);
const bound = value;
} else if (
(proxyDetails === null && isTypedArray(value)) ||
(proxyDetails !== null && isTypedArray(proxyDetails[0]))
) {
const typedArray = proxyDetails?.[0] ?? value;
keys = op_get_non_index_property_names(typedArray, filter);
const bound = typedArray;
const fallback = "";
if (constructor === null) {
// TODO(wafuwafu13): Implement
@ -832,23 +695,31 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) {
// // Reconstruct the array information.
// bound = new primordials[fallback](value);
}
const size = TypedArrayPrototypeGetLength(value);
const size = TypedArrayPrototypeGetLength(typedArray);
const prefix = getPrefix(constructor, tag, fallback, `(${size})`);
braces = [`${prefix}[`, "]"];
if (value.length === 0 && keys.length === 0 && !ctx.showHidden) {
if (typedArray.length === 0 && keys.length === 0 && !ctx.showHidden) {
return `${braces[0]}]`;
}
// Special handle the value. The original value is required below. The
// bound function is required to reconstruct missing information.
formatter = FunctionPrototypeBind(formatTypedArray, null, bound, size);
extrasType = kArrayExtrasType;
} else if (isMapIterator(value)) {
keys = getKeys(value, ctx.showHidden);
} else if (
(proxyDetails === null && isMapIterator(value)) ||
(proxyDetails !== null && isMapIterator(proxyDetails[0]))
) {
const mapIterator = proxyDetails?.[0] ?? value;
keys = getKeys(mapIterator, ctx.showHidden);
braces = getIteratorBraces("Map", tag);
// Add braces to the formatter parameters.
formatter = FunctionPrototypeBind(formatIterator, null, braces);
} else if (isSetIterator(value)) {
keys = getKeys(value, ctx.showHidden);
} else if (
(proxyDetails === null && isSetIterator(value)) ||
(proxyDetails !== null && isSetIterator(proxyDetails[0]))
) {
const setIterator = proxyDetails?.[0] ?? value;
keys = getKeys(setIterator, ctx.showHidden);
braces = getIteratorBraces("Set", tag);
// Add braces to the formatter parameters.
formatter = FunctionPrototypeBind(formatIterator, null, braces);
@ -873,10 +744,14 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) {
if (keys.length === 0 && protoProps === undefined) {
return ctx.stylize(base, "special");
}
} else if (isRegExp(value)) {
} else if (
(proxyDetails === null && isRegExp(value)) ||
(proxyDetails !== null && isRegExp(proxyDetails[0]))
) {
const regExp = proxyDetails?.[0] ?? value;
// Make RegExps say that they are RegExps
base = RegExpPrototypeToString(
constructor !== null ? value : new SafeRegExp(value),
constructor !== null ? regExp : new SafeRegExp(regExp),
);
const prefix = getPrefix(constructor, tag, "RegExp");
if (prefix !== "RegExp ") {
@ -888,8 +763,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) {
) {
return ctx.stylize(base, "regexp");
}
} else if (ObjectPrototypeIsPrototypeOf(DatePrototype, value)) {
const date = proxyDetails ? proxyDetails[0] : value;
} else if (
(proxyDetails === null && isDate(value)) ||
(proxyDetails !== null && isDate(proxyDetails[0]))
) {
const date = proxyDetails?.[0] ?? value;
if (NumberIsNaN(DatePrototypeGetTime(date))) {
return ctx.stylize("Invalid Date", "date");
} else {
@ -898,8 +776,16 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) {
return ctx.stylize(base, "date");
}
}
} else if (ObjectPrototypeIsPrototypeOf(ErrorPrototype, value)) {
base = inspectError(value, ctx);
} else if (
(proxyDetails === null &&
(isNativeError(value) ||
ObjectPrototypeIsPrototypeOf(ErrorPrototype, value))) ||
(proxyDetails !== null &&
(isNativeError(proxyDetails[0]) ||
ObjectPrototypeIsPrototypeOf(ErrorPrototype, proxyDetails[0])))
) {
const error = proxyDetails?.[0] ?? value;
base = inspectError(error, ctx);
if (keys.length === 0 && protoProps === undefined) {
return base;
}
@ -1180,7 +1066,7 @@ function getConstructorName(obj, ctx, recurseTimes, protoProps) {
return null;
}
const res = core.ops.op_get_constructor_name(tmp);
const res = op_get_constructor_name(tmp);
if (recurseTimes > ctx.depth && ctx.depth !== null) {
return `${res} <Complex prototype>`;
@ -1290,7 +1176,7 @@ function formatArray(ctx, value, recurseTimes) {
function getCtxStyle(value, constructor, tag) {
let fallback = "";
if (constructor === null) {
fallback = core.ops.op_get_constructor_name(value);
fallback = op_get_constructor_name(value);
if (fallback === tag) {
fallback = "Object";
}
@ -1433,7 +1319,7 @@ function getIteratorBraces(type, tag) {
const iteratorRegExp = new SafeRegExp(" Iterator] {$");
function formatIterator(braces, ctx, value, recurseTimes) {
const { 0: entries, 1: isKeyValue } = ops.op_preview_entries(value, true);
const { 0: entries, 1: isKeyValue } = op_preview_entries(value, true);
if (isKeyValue) {
// Mark entry iterators as such.
braces[0] = StringPrototypeReplace(
@ -1498,7 +1384,7 @@ function inspectError(value, ctx) {
let finalMessage = MapPrototypeGet(refMap, value) ?? "";
if (ObjectPrototypeIsPrototypeOf(AggregateErrorPrototype, value)) {
if (isAggregateError(value)) {
const stackLines = StringPrototypeSplit(value.stack, "\n");
while (true) {
const line = ArrayPrototypeShift(stackLines);
@ -1635,12 +1521,12 @@ function formatWeakCollection(ctx) {
}
function formatWeakSet(ctx, value, recurseTimes) {
const entries = ops.op_preview_entries(value, false);
const entries = op_preview_entries(value, false);
return formatSetIterInner(ctx, recurseTimes, entries, kWeak);
}
function formatWeakMap(ctx, value, recurseTimes) {
const entries = ops.op_preview_entries(value, false);
const entries = op_preview_entries(value, false);
return formatMapIterInner(ctx, recurseTimes, entries, kWeak);
}
@ -3278,14 +3164,14 @@ class Console {
const toTable = (header, body) => this.log(cliTable(header, body));
let resultData;
const isSet = ObjectPrototypeIsPrototypeOf(SetPrototype, data);
const isMap = ObjectPrototypeIsPrototypeOf(MapPrototype, data);
const isSetObject = isSet(data);
const isMapObject = isMap(data);
const valuesKey = "Values";
const indexKey = isSet || isMap ? "(iter idx)" : "(idx)";
const indexKey = isSetObject || isMapObject ? "(iter idx)" : "(idx)";
if (isSet) {
if (isSetObject) {
resultData = [...new SafeSetIterator(data)];
} else if (isMap) {
} else if (isMapObject) {
let idx = 0;
resultData = {};
@ -3342,7 +3228,7 @@ class Console {
const headerProps = properties ||
[
...new SafeArrayIterator(headerKeys),
!isMap && hasPrimitives && valuesKey,
!isMapObject && hasPrimitives && valuesKey,
];
const header = ArrayPrototypeFilter([
indexKey,

View File

@ -5,7 +5,7 @@ use std::path::PathBuf;
deno_core::extension!(
deno_console,
ops = [op_is_any_arraybuffer, op_preview_entries,],
ops = [op_preview_entries],
esm = ["01_console.js"],
);
@ -13,11 +13,6 @@ pub fn get_declaration() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_console.d.ts")
}
#[op2(fast)]
fn op_is_any_arraybuffer(value: &v8::Value) -> bool {
value.is_array_buffer() || value.is_shared_array_buffer()
}
#[op2]
pub fn op_preview_entries<'s>(
scope: &mut v8::HandleScope<'s>,

View File

@ -20,10 +20,9 @@ const {
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
const {
ArrayBufferIsView,
ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
ArrayBufferPrototypeSlice,
ArrayPrototypeEvery,
@ -58,6 +57,11 @@ const {
WeakMapPrototypeGet,
WeakMapPrototypeSet,
} = primordials;
const {
isArrayBuffer,
isTypedArray,
isDataView,
} = core;
// P-521 is not yet supported.
const supportedNamedCurves = ["P-256", "P-384"];
@ -280,26 +284,22 @@ function normalizeAlgorithm(algorithm, op) {
* @returns {Uint8Array}
*/
function copyBuffer(input) {
if (ArrayBufferIsView(input)) {
if (TypedArrayPrototypeGetSymbolToStringTag(input) !== undefined) {
// TypedArray
return TypedArrayPrototypeSlice(
new Uint8Array(
TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (input)),
TypedArrayPrototypeGetByteOffset(/** @type {Uint8Array} */ (input)),
TypedArrayPrototypeGetByteLength(/** @type {Uint8Array} */ (input)),
),
);
} else {
// DataView
return TypedArrayPrototypeSlice(
new Uint8Array(
DataViewPrototypeGetBuffer(/** @type {DataView} */ (input)),
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (input)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (input)),
),
);
}
if (isTypedArray(input)) {
return TypedArrayPrototypeSlice(
new Uint8Array(
TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (input)),
TypedArrayPrototypeGetByteOffset(/** @type {Uint8Array} */ (input)),
TypedArrayPrototypeGetByteLength(/** @type {Uint8Array} */ (input)),
),
);
} else if (isDataView(input)) {
return TypedArrayPrototypeSlice(
new Uint8Array(
DataViewPrototypeGetBuffer(/** @type {DataView} */ (input)),
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (input)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (input)),
),
);
}
// ArrayBuffer
return TypedArrayPrototypeSlice(
@ -944,19 +944,13 @@ class SubtleCrypto {
// 2.
if (format !== "jwk") {
if (
ArrayBufferIsView(keyData) ||
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, keyData)
) {
if (ArrayBufferIsView(keyData) || isArrayBuffer(keyData)) {
keyData = copyBuffer(keyData);
} else {
throw new TypeError("keyData is a JsonWebKey");
}
} else {
if (
ArrayBufferIsView(keyData) ||
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, keyData)
) {
if (ArrayBufferIsView(keyData) || isArrayBuffer(keyData)) {
throw new TypeError("keyData is not a JsonWebKey");
}
}
@ -4778,10 +4772,7 @@ webidl.converters["BufferSource or JsonWebKey"] = (
opts,
) => {
// Union for (BufferSource or JsonWebKey)
if (
ArrayBufferIsView(V) ||
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V)
) {
if (ArrayBufferIsView(V) || isArrayBuffer(V)) {
return webidl.converters.BufferSource(V, prefix, context, opts);
}
return webidl.converters.JsonWebKey(V, prefix, context, opts);

View File

@ -37,7 +37,6 @@ import {
readableStreamThrowIfErrored,
} from "ext:deno_web/06_streams.js";
const {
ArrayBufferPrototype,
ArrayBufferIsView,
ArrayPrototypeMap,
DataViewPrototypeGetBuffer,
@ -46,8 +45,6 @@ const {
JSONParse,
ObjectDefineProperties,
ObjectPrototypeIsPrototypeOf,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetByteOffset,
@ -56,6 +53,10 @@ const {
TypeError,
Uint8Array,
} = primordials;
const {
isAnyArrayBuffer,
isArrayBuffer,
} = core;
/**
* @param {Uint8Array | string} chunk
@ -412,7 +413,7 @@ function extractBody(object) {
);
}
source = TypedArrayPrototypeSlice(object);
} else if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, object)) {
} else if (isArrayBuffer(object)) {
source = TypedArrayPrototypeSlice(new Uint8Array(object));
} else if (ObjectPrototypeIsPrototypeOf(FormDataPrototype, object)) {
const res = formDataToBlob(object);
@ -461,11 +462,7 @@ webidl.converters["BodyInit_DOMString"] = (V, prefix, context, opts) => {
return webidl.converters["URLSearchParams"](V, prefix, context, opts);
}
if (typeof V === "object") {
if (
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V) ||
// deno-lint-ignore prefer-primordials
ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V)
) {
if (isAnyArrayBuffer(V)) {
return webidl.converters["ArrayBuffer"](V, prefix, context, opts);
}
if (ArrayBufferIsView(V)) {

View File

@ -51,7 +51,7 @@ const {
StringPrototypeStartsWith,
StringPrototypeToLowerCase,
TypeError,
Uint8ArrayPrototype,
TypedArrayPrototypeGetSymbolToStringTag,
} = primordials;
const REQUEST_BODY_HEADER_NAMES = [
@ -131,7 +131,7 @@ async function mainFetch(req, recursive, terminator) {
const stream = req.body.streamOrStatic;
const body = stream.body;
if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, body)) {
if (TypedArrayPrototypeGetSymbolToStringTag(body) === "Uint8Array") {
reqBody = body;
} else if (typeof body === "string") {
reqBody = core.encode(body);

View File

@ -7,7 +7,7 @@ import { core, primordials } from "ext:core/mod.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
import { URL } from "ext:deno_url/00_url.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import {
defineEventHandler,
EventTarget,

View File

@ -4,7 +4,6 @@ import { core, primordials } from "ext:core/mod.js";
const ops = core.ops;
const {
ArrayBufferIsView,
ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
ArrayPrototypeMap,
ArrayPrototypeJoin,
@ -16,7 +15,6 @@ const {
NumberIsSafeInteger,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetSymbolToStringTag,
TypeError,
Uint8Array,
Int32Array,
@ -32,6 +30,11 @@ const {
SafeArrayIterator,
SafeWeakMap,
} = primordials;
const {
isArrayBuffer,
isDataView,
isTypedArray,
} = core;
import { pathFromURL } from "ext:deno_web/00_infra.js";
const {
op_ffi_call_nonblocking,
@ -46,14 +49,10 @@ const {
* @returns {number}
*/
function getBufferSourceByteLength(source) {
if (ArrayBufferIsView(source)) {
if (TypedArrayPrototypeGetSymbolToStringTag(source) !== undefined) {
// TypedArray
return TypedArrayPrototypeGetByteLength(source);
} else {
// DataView
return DataViewPrototypeGetByteLength(source);
}
if (isTypedArray(source)) {
return TypedArrayPrototypeGetByteLength(source);
} else if (isDataView(source)) {
return DataViewPrototypeGetByteLength(source);
}
return ArrayBufferPrototypeGetByteLength(source);
}
@ -232,7 +231,7 @@ class UnsafePointer {
} else {
pointer = ops.op_ffi_ptr_of(value);
}
} else if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, value)) {
} else if (isArrayBuffer(value)) {
if (value.length === 0) {
pointer = ops.op_ffi_ptr_of_exact(new Uint8Array(value));
} else {

View File

@ -37,7 +37,6 @@ const {
const {
ArrayPrototypeFilter,
Date,
DatePrototype,
DatePrototypeGetTime,
Error,
Function,
@ -51,6 +50,9 @@ const {
SymbolIterator,
Uint32Array,
} = primordials;
const {
isDate,
} = core;
import { read, readSync, write, writeSync } from "ext:deno_io/12_io.js";
import * as abortSignal from "ext:deno_web/03_abort_signal.js";
import {
@ -416,7 +418,7 @@ async function link(oldpath, newpath) {
}
function toUnixTimeFromEpoch(value) {
if (ObjectPrototypeIsPrototypeOf(DatePrototype, value)) {
if (isDate(value)) {
const time = DatePrototypeGetTime(value);
const seconds = MathTrunc(time / 1e3);
const nanoseconds = MathTrunc(time - (seconds * 1e3)) * 1e6;

View File

@ -44,8 +44,8 @@ const {
PromisePrototypeThen,
Symbol,
TypeError,
TypedArrayPrototypeGetSymbolToStringTag,
Uint8Array,
Uint8ArrayPrototype,
} = primordials;
const {
@ -397,7 +397,7 @@ function fastSyncResponseOrStream(req, respBody, status, innerRequest) {
const stream = respBody.streamOrStatic;
const body = stream.body;
if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, body)) {
if (TypedArrayPrototypeGetSymbolToStringTag(body) === "Uint8Array") {
innerRequest?.close();
op_http_set_response_body_bytes(req, body, status);
return;

View File

@ -60,8 +60,8 @@ const {
Symbol,
SymbolAsyncIterator,
TypeError,
TypedArrayPrototypeGetSymbolToStringTag,
Uint8Array,
Uint8ArrayPrototype,
} = primordials;
const {
op_http_accept,
@ -272,7 +272,7 @@ function createRespondWith(
}
const isStreamingResponseBody = !(
typeof respBody === "string" ||
ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, respBody)
TypedArrayPrototypeGetSymbolToStringTag(respBody) === "Uint8Array"
);
try {
await op_http_write_headers(
@ -339,7 +339,9 @@ function createRespondWith(
while (true) {
const { value, done } = await reader.read();
if (done) break;
if (!ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, value)) {
if (
TypedArrayPrototypeGetSymbolToStringTag(value) !== "Uint8Array"
) {
await reader.cancel(new TypeError("Value not a Uint8Array"));
break;
}

View File

@ -1,6 +1,8 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// @ts-ignore internal api
import { core, primordials } from "ext:core/mod.js";
import { SymbolDispose } from "ext:deno_web/00_infra.js";
import { ReadableStream } from "ext:deno_web/06_streams.js";
const {
AsyncGeneratorPrototype,
BigIntPrototypeToString,
@ -10,19 +12,17 @@ const {
StringPrototypeReplace,
SymbolFor,
SymbolToStringTag,
Uint8ArrayPrototype,
TypedArrayPrototypeGetSymbolToStringTag,
Error,
} = globalThis.__bootstrap.primordials;
import { SymbolDispose } from "ext:deno_web/00_infra.js";
import { ReadableStream } from "ext:deno_web/06_streams.js";
const core = Deno.core;
const ops = core.ops;
} = primordials;
const {
op_kv_atomic_write,
op_kv_database_open,
op_kv_dequeue_next_message,
op_kv_encode_cursor,
op_kv_finish_dequeued_message,
op_kv_snapshot_read,
op_kv_watch,
op_kv_watch_next,
} = core.ensureFastOps();
@ -30,7 +30,7 @@ const encodeCursor: (
selector: [Deno.KvKey | null, Deno.KvKey | null, Deno.KvKey | null],
boundaryKey: Deno.KvKey,
) => string = (selector, boundaryKey) =>
ops.op_kv_encode_cursor(selector, boundaryKey);
op_kv_encode_cursor(selector, boundaryKey);
async function openKv(path: string) {
const rid = await op_kv_database_open(path);
@ -319,7 +319,7 @@ class Kv {
watch(keys: Deno.KvKey[], options = {}) {
const raw = options.raw ?? false;
const rid = ops.op_kv_watch(this.#rid, keys);
const rid = op_kv_watch(this.#rid, keys);
const lastEntries: (Deno.KvEntryMaybe<unknown> | undefined)[] = Array.from(
{ length: keys.length },
() => undefined,
@ -585,7 +585,7 @@ function deserializeValue(entry: RawKvEntry): Deno.KvEntry<unknown> {
}
function serializeValue(value: unknown): RawValue {
if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, value)) {
if (TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint8Array") {
return {
kind: "bytes",
value,

View File

@ -5,7 +5,9 @@
// deno-lint-ignore-file prefer-primordials
import { core } from "ext:core/mod.js";
const ops = core.ops;
const {
op_preview_entries,
} = core.ensureFastOps(true);
// Mock trace for now
const trace = () => {};
@ -502,7 +504,7 @@ const consoleMethods = {
let isKeyValue = false;
let i = 0;
if (mapIter) {
const res = ops.op_preview_entries(tabularData, true);
const res = op_preview_entries(tabularData, true);
tabularData = res[0];
isKeyValue = res[1];
}
@ -537,7 +539,7 @@ const consoleMethods = {
const setIter = isSetIterator(tabularData);
if (setIter) {
tabularData = ops.op_preview_entries(tabularData, false);
tabularData = op_preview_entries(tabularData, false);
}
const setlike = setIter || mapIter || isSet(tabularData);

View File

@ -24,17 +24,16 @@
// TODO(petamoriken): enable prefer-primordials for node polyfills
// deno-lint-ignore-file prefer-primordials
import { primordials } from "ext:core/mod.js";
import * as bindingTypes from "ext:deno_node/internal_binding/types.ts";
export {
isCryptoKey,
isKeyObject,
} from "ext:deno_node/internal/crypto/_keys.ts";
// https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
const _getTypedArrayToStringTag = Object.getOwnPropertyDescriptor(
Object.getPrototypeOf(Uint8Array).prototype,
Symbol.toStringTag,
)!.get!;
const {
ArrayBufferIsView,
TypedArrayPrototypeGetSymbolToStringTag,
} = primordials;
export function isArrayBufferView(
value: unknown,
@ -51,98 +50,82 @@ export function isArrayBufferView(
| Uint8ClampedArray
| Uint16Array
| Uint32Array {
return ArrayBuffer.isView(value);
return ArrayBufferIsView(value);
}
export function isBigInt64Array(value: unknown): value is BigInt64Array {
return _getTypedArrayToStringTag.call(value) === "BigInt64Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "BigInt64Array";
}
export function isBigUint64Array(value: unknown): value is BigUint64Array {
return _getTypedArrayToStringTag.call(value) === "BigUint64Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "BigUint64Array";
}
export function isFloat32Array(value: unknown): value is Float32Array {
return _getTypedArrayToStringTag.call(value) === "Float32Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Float32Array";
}
export function isFloat64Array(value: unknown): value is Float64Array {
return _getTypedArrayToStringTag.call(value) === "Float64Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Float64Array";
}
export function isInt8Array(value: unknown): value is Int8Array {
return _getTypedArrayToStringTag.call(value) === "Int8Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Int8Array";
}
export function isInt16Array(value: unknown): value is Int16Array {
return _getTypedArrayToStringTag.call(value) === "Int16Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Int16Array";
}
export function isInt32Array(value: unknown): value is Int32Array {
return _getTypedArrayToStringTag.call(value) === "Int32Array";
}
export type TypedArray =
| BigInt64Array
| BigUint64Array
| Float32Array
| Float64Array
| Int8Array
| Int16Array
| Int32Array
| Uint8Array
| Uint8ClampedArray
| Uint16Array
| Uint32Array;
export function isTypedArray(value: unknown): value is TypedArray {
return _getTypedArrayToStringTag.call(value) !== undefined;
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Int32Array";
}
export function isUint8Array(value: unknown): value is Uint8Array {
return _getTypedArrayToStringTag.call(value) === "Uint8Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint8Array";
}
export function isUint8ClampedArray(
value: unknown,
): value is Uint8ClampedArray {
return _getTypedArrayToStringTag.call(value) === "Uint8ClampedArray";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint8ClampedArray";
}
export function isUint16Array(value: unknown): value is Uint16Array {
return _getTypedArrayToStringTag.call(value) === "Uint16Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint16Array";
}
export function isUint32Array(value: unknown): value is Uint32Array {
return _getTypedArrayToStringTag.call(value) === "Uint32Array";
return TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint32Array";
}
export const {
// isExternal,
isDate,
isAnyArrayBuffer,
isArgumentsObject,
isArrayBuffer,
isAsyncFunction,
isBigIntObject,
isBooleanObject,
isNumberObject,
isStringObject,
isSymbolObject,
isNativeError,
isRegExp,
isAsyncFunction,
isBoxedPrimitive,
isDataView,
isDate,
isGeneratorFunction,
isGeneratorObject,
isPromise,
isMap,
isSet,
isMapIterator,
isModuleNamespaceObject,
isNativeError,
isNumberObject,
isPromise,
isProxy,
isRegExp,
isSet,
isSetIterator,
isSharedArrayBuffer,
isStringObject,
isSymbolObject,
isTypedArray,
isWeakMap,
isWeakSet,
isArrayBuffer,
isDataView,
isSharedArrayBuffer,
isProxy,
isModuleNamespaceObject,
isAnyArrayBuffer,
isBoxedPrimitive,
} = bindingTypes;

View File

@ -21,319 +21,35 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// TODO(petamoriken): enable prefer-primordials for node polyfills
// deno-lint-ignore-file prefer-primordials
import { core } from "ext:core/mod.js";
const { core } = globalThis.__bootstrap;
const { ops } = core;
// https://tc39.es/ecma262/#sec-bigint.prototype.valueof
const _bigIntValueOf = BigInt.prototype.valueOf;
// https://tc39.es/ecma262/#sec-boolean.prototype.valueof
const _booleanValueOf = Boolean.prototype.valueOf;
// https://tc39.es/ecma262/#sec-date.prototype.valueof
const _dateValueOf = Date.prototype.valueOf;
// https://tc39.es/ecma262/#sec-number.prototype.valueof
const _numberValueOf = Number.prototype.valueOf;
// https://tc39.es/ecma262/#sec-string.prototype.valueof
const _stringValueOf = String.prototype.valueOf;
// https://tc39.es/ecma262/#sec-symbol.prototype.valueof
const _symbolValueOf = Symbol.prototype.valueOf;
// https://tc39.es/ecma262/#sec-weakmap.prototype.has
const _weakMapHas = WeakMap.prototype.has;
// https://tc39.es/ecma262/#sec-weakset.prototype.has
const _weakSetHas = WeakSet.prototype.has;
// https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.bytelength
const _getArrayBufferByteLength = Object.getOwnPropertyDescriptor(
ArrayBuffer.prototype,
"byteLength",
)!.get!;
// https://tc39.es/ecma262/#sec-get-sharedarraybuffer.prototype.bytelength
let _getSharedArrayBufferByteLength;
// https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
const _getTypedArrayToStringTag = Object.getOwnPropertyDescriptor(
Object.getPrototypeOf(Uint8Array).prototype,
Symbol.toStringTag,
)!.get!;
// https://tc39.es/ecma262/#sec-get-set.prototype.size
const _getSetSize = Object.getOwnPropertyDescriptor(
Set.prototype,
"size",
)!.get!;
// https://tc39.es/ecma262/#sec-get-map.prototype.size
const _getMapSize = Object.getOwnPropertyDescriptor(
Map.prototype,
"size",
)!.get!;
function isObjectLike(
value: unknown,
): value is Record<string | number | symbol, unknown> {
return value !== null && typeof value === "object";
}
export function isAnyArrayBuffer(
value: unknown,
): value is ArrayBuffer | SharedArrayBuffer {
return ops.op_is_any_arraybuffer(value);
}
export function isArgumentsObject(value: unknown): value is IArguments {
return core.isArgumentsObject(value);
}
export function isArrayBuffer(value: unknown): value is ArrayBuffer {
try {
_getArrayBufferByteLength.call(value);
return true;
} catch {
return false;
}
}
export function isAsyncFunction(
value: unknown,
): value is (...args: unknown[]) => Promise<unknown> {
return core.isAsyncFunction(value);
}
// deno-lint-ignore ban-types
export function isBooleanObject(value: unknown): value is Boolean {
if (!isObjectLike(value)) {
return false;
}
try {
_booleanValueOf.call(value);
return true;
} catch {
return false;
}
}
export function isBoxedPrimitive(
value: unknown,
// deno-lint-ignore ban-types
): value is Boolean | String | Number | Symbol | BigInt {
return (
isBooleanObject(value) ||
isStringObject(value) ||
isNumberObject(value) ||
isSymbolObject(value) ||
isBigIntObject(value)
);
}
export function isDataView(value: unknown): value is DataView {
return (
ArrayBuffer.isView(value) &&
_getTypedArrayToStringTag.call(value) === undefined
);
}
export function isDate(value: unknown): value is Date {
try {
_dateValueOf.call(value);
return true;
} catch {
return false;
}
}
export function isGeneratorFunction(
value: unknown,
): value is GeneratorFunction {
return core.isGeneratorFunction(value);
}
export function isGeneratorObject(value: unknown): value is Generator {
return core.isGeneratorObject(value);
}
export function isMap(value: unknown): value is Map<unknown, unknown> {
try {
_getMapSize.call(value);
return true;
} catch {
return false;
}
}
export function isMapIterator(
value: unknown,
): value is IterableIterator<[unknown, unknown]> {
return core.isMapIterator(value);
}
export function isModuleNamespaceObject(
value: unknown,
): value is Record<string | number | symbol, unknown> {
return core.isModuleNamespaceObject(value);
}
export function isNativeError(value: unknown): value is Error {
return core.isNativeError(value);
}
// deno-lint-ignore ban-types
export function isNumberObject(value: unknown): value is Number {
if (!isObjectLike(value)) {
return false;
}
try {
_numberValueOf.call(value);
return true;
} catch {
return false;
}
}
export function isBigIntObject(value: unknown): value is bigint {
if (!isObjectLike(value)) {
return false;
}
try {
_bigIntValueOf.call(value);
return true;
} catch {
return false;
}
}
export function isPromise(value: unknown): value is Promise<unknown> {
return core.isPromise(value);
}
export function isProxy(
value: unknown,
): value is Record<string | number | symbol, unknown> {
return core.isProxy(value);
}
export function isRegExp(value: unknown): value is RegExp {
return core.isRegExp(value);
}
export function isSet(value: unknown): value is Set<unknown> {
try {
_getSetSize.call(value);
return true;
} catch {
return false;
}
}
export function isSetIterator(
value: unknown,
): value is IterableIterator<unknown> {
return core.isSetIterator(value);
}
export function isSharedArrayBuffer(
value: unknown,
): value is SharedArrayBuffer {
// TODO(kt3k): add SharedArrayBuffer to primordials
_getSharedArrayBufferByteLength ??= Object.getOwnPropertyDescriptor(
SharedArrayBuffer.prototype,
"byteLength",
)!.get!;
try {
_getSharedArrayBufferByteLength.call(value);
return true;
} catch {
return false;
}
}
// deno-lint-ignore ban-types
export function isStringObject(value: unknown): value is String {
if (!isObjectLike(value)) {
return false;
}
try {
_stringValueOf.call(value);
return true;
} catch {
return false;
}
}
// deno-lint-ignore ban-types
export function isSymbolObject(value: unknown): value is Symbol {
if (!isObjectLike(value)) {
return false;
}
try {
_symbolValueOf.call(value);
return true;
} catch {
return false;
}
}
export function isWeakMap(
value: unknown,
): value is WeakMap<Record<string | number | symbol, unknown>, unknown> {
try {
// deno-lint-ignore no-explicit-any
_weakMapHas.call(value, null as any);
return true;
} catch {
return false;
}
}
export function isWeakSet(
value: unknown,
): value is WeakSet<Record<string | number | symbol, unknown>> {
try {
// deno-lint-ignore no-explicit-any
_weakSetHas.call(value, null as any);
return true;
} catch {
return false;
}
}
export default {
isAsyncFunction,
isGeneratorFunction,
export const {
// isExternal,
isAnyArrayBuffer,
isArrayBuffer,
isArgumentsObject,
isArrayBuffer,
isAsyncFunction,
isBigIntObject,
isBooleanObject,
isBoxedPrimitive,
isDataView,
// isExternal,
isDate,
isGeneratorFunction,
isGeneratorObject,
isMap,
isMapIterator,
isModuleNamespaceObject,
isNativeError,
isNumberObject,
isPromise,
isProxy,
isRegExp,
isSet,
isSetIterator,
isSharedArrayBuffer,
isStringObject,
isSymbolObject,
isTypedArray,
isWeakMap,
isWeakSet,
isRegExp,
isDate,
isStringObject,
isNumberObject,
isBooleanObject,
isBigIntObject,
};
} = core;

View File

@ -210,4 +210,4 @@ for (let i = 0; i < entries.length; ++i) {
ObjectDefineProperty(DOMException.prototype, key, desc);
}
export default DOMException;
export { DOMException, DOMExceptionPrototype };

View File

@ -7,7 +7,7 @@
import { core, primordials } from "ext:core/mod.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
const {
ArrayPrototypeFilter,

View File

@ -7,10 +7,9 @@
/// <reference path="../web/lib.deno_web.d.ts" />
import { core, primordials } from "ext:core/mod.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
const {
ArrayBuffer,
ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
ArrayBufferPrototypeSlice,
ArrayBufferIsView,
@ -38,6 +37,9 @@ const {
Float32Array,
Float64Array,
} = primordials;
const {
isArrayBuffer,
} = core;
const objectCloneMemo = new SafeWeakMap();
@ -61,7 +63,7 @@ function cloneArrayBuffer(
function structuredClone(value) {
// Performance optimization for buffers, otherwise
// `serialize/deserialize` will allocate new buffer.
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, value)) {
if (isArrayBuffer(value)) {
const cloned = cloneArrayBuffer(
value,
0,

View File

@ -9,7 +9,7 @@
import { core, primordials } from "ext:core/mod.js";
const ops = core.ops;
import * as webidl from "ext:deno_webidl/00_webidl.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
const {
ObjectPrototypeIsPrototypeOf,
TypeErrorPrototype,

View File

@ -36,7 +36,6 @@ import {
const {
ArrayBuffer,
ArrayBufferIsView,
ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
ArrayBufferPrototypeSlice,
ArrayPrototypeMap,
@ -96,6 +95,12 @@ const {
WeakMapPrototypeSet,
queueMicrotask,
} = primordials;
const {
isAnyArrayBuffer,
isArrayBuffer,
isSharedArrayBuffer,
isTypedArray,
} = core;
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
import { assert, AssertionError } from "ext:deno_web/00_infra.js";
@ -272,8 +277,7 @@ class Queue {
* @returns {boolean}
*/
function isDetachedBuffer(O) {
// deno-lint-ignore prefer-primordials
if (ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, O)) {
if (isSharedArrayBuffer(O)) {
return false;
}
return ArrayBufferPrototypeGetByteLength(O) === 0 &&
@ -286,11 +290,7 @@ function isDetachedBuffer(O) {
*/
function canTransferArrayBuffer(O) {
assert(typeof O === "object");
assert(
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, O) ||
// deno-lint-ignore prefer-primordials
ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, O),
);
assert(isAnyArrayBuffer(O));
if (isDetachedBuffer(O)) {
return false;
}
@ -311,8 +311,7 @@ function transferArrayBuffer(O) {
* @returns {number}
*/
function getArrayBufferByteLength(O) {
// deno-lint-ignore prefer-primordials
if (ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, O)) {
if (isSharedArrayBuffer(O)) {
// TODO(petamoriken): use primordials
// deno-lint-ignore prefer-primordials
return O.byteLength;
@ -328,8 +327,7 @@ function getArrayBufferByteLength(O) {
function cloneAsUint8Array(O) {
assert(typeof O === "object");
assert(ArrayBufferIsView(O));
if (TypedArrayPrototypeGetSymbolToStringTag(O) !== undefined) {
// TypedArray
if (isTypedArray(O)) {
return TypedArrayPrototypeSlice(
new Uint8Array(
TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (O)),
@ -338,7 +336,6 @@ function cloneAsUint8Array(O) {
),
);
} else {
// DataView
return TypedArrayPrototypeSlice(
new Uint8Array(
DataViewPrototypeGetBuffer(/** @type {DataView} */ (O)),
@ -1340,15 +1337,7 @@ function readableByteStreamControllerEnqueue(controller, chunk) {
}
let buffer, byteLength, byteOffset;
if (TypedArrayPrototypeGetSymbolToStringTag(chunk) === undefined) {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk));
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
byteOffset = DataViewPrototypeGetByteOffset(
/** @type {DataView} */ (chunk),
);
} else {
if (isTypedArray(chunk)) {
buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array}} */ (chunk));
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (chunk),
@ -1356,6 +1345,14 @@ function readableByteStreamControllerEnqueue(controller, chunk) {
byteOffset = TypedArrayPrototypeGetByteOffset(
/** @type {Uint8Array} */ (chunk),
);
} else {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk));
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
byteOffset = DataViewPrototypeGetByteOffset(
/** @type {DataView} */ (chunk),
);
}
if (isDetachedBuffer(buffer)) {
@ -1461,7 +1458,7 @@ function readableByteStreamControllerEnqueueClonedChunkToQueue(
) {
let cloneResult;
try {
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, buffer)) {
if (isArrayBuffer(buffer)) {
cloneResult = ArrayBufferPrototypeSlice(
buffer,
byteOffset,
@ -2292,11 +2289,7 @@ function readableByteStreamControllerRespondWithNewView(controller, view) {
assert(controller[_pendingPullIntos].length !== 0);
let buffer, byteLength, byteOffset;
if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view));
byteLength = DataViewPrototypeGetByteLength(/** @type {DataView} */ (view));
byteOffset = DataViewPrototypeGetByteOffset(/** @type {DataView} */ (view));
} else {
if (isTypedArray(view)) {
buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array}} */ (view));
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (view),
@ -2304,7 +2297,12 @@ function readableByteStreamControllerRespondWithNewView(controller, view) {
byteOffset = TypedArrayPrototypeGetByteOffset(
/** @type {Uint8Array} */ (view),
);
} else {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view));
byteLength = DataViewPrototypeGetByteLength(/** @type {DataView} */ (view));
byteOffset = DataViewPrototypeGetByteOffset(/** @type {DataView} */ (view));
}
assert(!isDetachedBuffer(buffer));
const firstDescriptor = controller[_pendingPullIntos][0];
const state = controller[_stream][_state];
@ -3364,14 +3362,14 @@ function readableByteStreamTee(stream) {
}
if (chunk !== undefined) {
let byteLength;
if (TypedArrayPrototypeGetSymbolToStringTag(chunk) === undefined) {
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
} else {
if (isTypedArray(chunk)) {
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (chunk),
);
} else {
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
}
assert(byteLength === 0);
if (!byobCanceled) {
@ -5581,16 +5579,16 @@ class ReadableStreamBYOBReader {
}
let buffer, byteLength;
if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view));
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (view),
);
} else {
if (isTypedArray(view)) {
buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (view));
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (view),
);
} else {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view));
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (view),
);
}
if (byteLength === 0) {
return PromiseReject(
@ -5613,7 +5611,7 @@ class ReadableStreamBYOBReader {
if (options.min === 0) {
return PromiseReject(new TypeError("options.min must be non-zero"));
}
if (TypedArrayPrototypeGetSymbolToStringTag(view) !== undefined) {
if (isTypedArray(view)) {
if (options.min > TypedArrayPrototypeGetLength(view)) {
return PromiseReject(
new RangeError("options.min must be smaller or equal to view's size"),
@ -5745,12 +5743,12 @@ class ReadableStreamBYOBRequest {
}
let buffer, byteLength;
if (TypedArrayPrototypeGetSymbolToStringTag(this[_view]) === undefined) {
buffer = DataViewPrototypeGetBuffer(this[_view]);
byteLength = DataViewPrototypeGetByteLength(this[_view]);
} else {
if (isTypedArray(this[_view])) {
buffer = TypedArrayPrototypeGetBuffer(this[_view]);
byteLength = TypedArrayPrototypeGetByteLength(this[_view]);
} else {
buffer = DataViewPrototypeGetBuffer(this[_view]);
byteLength = DataViewPrototypeGetByteLength(this[_view]);
}
if (isDetachedBuffer(buffer)) {
throw new TypeError(
@ -5774,10 +5772,10 @@ class ReadableStreamBYOBRequest {
}
let buffer;
if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) {
buffer = DataViewPrototypeGetBuffer(view);
} else {
if (isTypedArray(view)) {
buffer = TypedArrayPrototypeGetBuffer(view);
} else {
buffer = DataViewPrototypeGetBuffer(view);
}
if (isDetachedBuffer(buffer)) {
throw new TypeError(
@ -5864,16 +5862,16 @@ class ReadableByteStreamController {
const arg1 = "Argument 1";
chunk = webidl.converters.ArrayBufferView(chunk, prefix, arg1);
let buffer, byteLength;
if (TypedArrayPrototypeGetSymbolToStringTag(chunk) === undefined) {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk));
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
} else {
if (isTypedArray(chunk)) {
buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (chunk));
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (chunk),
);
} else {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk));
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
}
if (byteLength === 0) {
throw webidl.makeException(

View File

@ -17,23 +17,26 @@ const {
DataViewPrototypeGetBuffer,
DataViewPrototypeGetByteLength,
DataViewPrototypeGetByteOffset,
ObjectPrototypeIsPrototypeOf,
PromiseReject,
PromiseResolve,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype
// SharedArrayBufferPrototype,
StringPrototypeCharCodeAt,
StringPrototypeSlice,
SymbolFor,
TypedArrayPrototypeSubarray,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetSymbolToStringTag,
Uint8Array,
ObjectPrototypeIsPrototypeOf,
ArrayBufferIsView,
TypedArrayPrototypeSubarray,
Uint32Array,
Uint8Array,
} = primordials;
const {
isDataView,
isSharedArrayBuffer,
isTypedArray,
} = core;
class TextDecoder {
/** @type {string} */
@ -111,51 +114,37 @@ class TextDecoder {
try {
/** @type {ArrayBufferLike} */
let buffer = input;
if (ArrayBufferIsView(input)) {
if (TypedArrayPrototypeGetSymbolToStringTag(input) !== undefined) {
// TypedArray
buffer = TypedArrayPrototypeGetBuffer(
/** @type {Uint8Array} */ (input),
);
} else {
// DataView
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (input));
}
if (isTypedArray(input)) {
buffer = TypedArrayPrototypeGetBuffer(
/** @type {Uint8Array} */ (input),
);
} else if (isDataView(input)) {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (input));
}
// Note from spec: implementations are strongly encouraged to use an implementation strategy that avoids this copy.
// When doing so they will have to make sure that changes to input do not affect future calls to decode().
if (
ObjectPrototypeIsPrototypeOf(
// deno-lint-ignore prefer-primordials
SharedArrayBuffer.prototype,
buffer,
)
) {
if (isSharedArrayBuffer(buffer)) {
// We clone the data into a non-shared ArrayBuffer so we can pass it
// to Rust.
// `input` is now a Uint8Array, and calling the TypedArray constructor
// with a TypedArray argument copies the data.
if (ArrayBufferIsView(input)) {
if (TypedArrayPrototypeGetSymbolToStringTag(input) !== undefined) {
// TypedArray
input = new Uint8Array(
buffer,
TypedArrayPrototypeGetByteOffset(
/** @type {Uint8Array} */ (input),
),
TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (input),
),
);
} else {
// DataView
input = new Uint8Array(
buffer,
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (input)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (input)),
);
}
if (isTypedArray(input)) {
input = new Uint8Array(
buffer,
TypedArrayPrototypeGetByteOffset(
/** @type {Uint8Array} */ (input),
),
TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (input),
),
);
} else if (isDataView(input)) {
input = new Uint8Array(
buffer,
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (input)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (input)),
);
} else {
input = new Uint8Array(buffer);
}

View File

@ -16,10 +16,9 @@ import * as webidl from "ext:deno_webidl/00_webidl.js";
import { ReadableStream } from "ext:deno_web/06_streams.js";
import { URL } from "ext:deno_url/00_url.js";
const {
ArrayBufferPrototype,
ArrayBufferPrototypeSlice,
ArrayBufferPrototypeGetByteLength,
ArrayBufferIsView,
ArrayBufferPrototypeGetByteLength,
ArrayBufferPrototypeSlice,
ArrayPrototypePush,
AsyncGeneratorPrototypeNext,
DataViewPrototypeGetBuffer,
@ -31,23 +30,26 @@ const {
MathMin,
ObjectPrototypeIsPrototypeOf,
RegExpPrototypeTest,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype
SafeFinalizationRegistry,
SafeRegExp,
StringPrototypeCharAt,
StringPrototypeToLowerCase,
StringPrototypeSlice,
StringPrototypeToLowerCase,
Symbol,
SymbolFor,
TypedArrayPrototypeSet,
TypeError,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetSymbolToStringTag,
TypeError,
TypedArrayPrototypeSet,
Uint8Array,
} = primordials;
const {
isAnyArrayBuffer,
isArrayBuffer,
isDataView,
isTypedArray,
} = core;
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
const {
op_blob_read_part,
@ -129,34 +131,30 @@ function processBlobParts(parts, endings) {
let size = 0;
for (let i = 0; i < parts.length; ++i) {
const element = parts[i];
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, element)) {
if (isArrayBuffer(element)) {
const chunk = new Uint8Array(ArrayBufferPrototypeSlice(element, 0));
ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
size += ArrayBufferPrototypeGetByteLength(element);
} else if (ArrayBufferIsView(element)) {
if (TypedArrayPrototypeGetSymbolToStringTag(element) !== undefined) {
// TypedArray
const chunk = new Uint8Array(
TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (element)),
TypedArrayPrototypeGetByteOffset(/** @type {Uint8Array} */ (element)),
TypedArrayPrototypeGetByteLength(/** @type {Uint8Array} */ (element)),
);
size += TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (element),
);
ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
} else {
// DataView
const chunk = new Uint8Array(
DataViewPrototypeGetBuffer(/** @type {DataView} */ (element)),
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (element)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (element)),
);
size += DataViewPrototypeGetByteLength(
/** @type {DataView} */ (element),
);
ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
}
} else if (isTypedArray(element)) {
const chunk = new Uint8Array(
TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (element)),
TypedArrayPrototypeGetByteOffset(/** @type {Uint8Array} */ (element)),
TypedArrayPrototypeGetByteLength(/** @type {Uint8Array} */ (element)),
);
size += TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (element),
);
ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
} else if (isDataView(element)) {
const chunk = new Uint8Array(
DataViewPrototypeGetBuffer(/** @type {DataView} */ (element)),
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (element)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (element)),
);
size += DataViewPrototypeGetByteLength(
/** @type {DataView} */ (element),
);
ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
} else if (ObjectPrototypeIsPrototypeOf(BlobPrototype, element)) {
ArrayPrototypePush(processedParts, element);
size += element.size;
@ -446,11 +444,7 @@ webidl.converters["BlobPart"] = (V, prefix, context, opts) => {
if (ObjectPrototypeIsPrototypeOf(BlobPrototype, V)) {
return webidl.converters["Blob"](V, prefix, context, opts);
}
if (
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V) ||
// deno-lint-ignore prefer-primordials
ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V)
) {
if (isAnyArrayBuffer(V)) {
return webidl.converters["ArrayBuffer"](V, prefix, context, opts);
}
if (ArrayBufferIsView(V)) {

View File

@ -18,7 +18,7 @@ import { forgivingBase64Encode } from "ext:deno_web/00_infra.js";
import { EventTarget, ProgressEvent } from "ext:deno_web/02_event.js";
import { decode, TextDecoder } from "ext:deno_web/08_text_encoding.js";
import { parseMimeType } from "ext:deno_web/01_mimesniff.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
const {
ArrayPrototypePush,
ArrayPrototypeReduce,

View File

@ -3,7 +3,7 @@
/// <reference path="../../core/internal.d.ts" />
import { URL } from "ext:deno_url/00_url.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import { primordials } from "ext:core/mod.js";
const {
Error,

View File

@ -18,9 +18,8 @@ import {
setIsTrusted,
} from "ext:deno_web/02_event.js";
import { isDetachedBuffer } from "ext:deno_web/06_streams.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
const {
ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
ArrayPrototypeFilter,
ArrayPrototypeIncludes,
@ -31,6 +30,9 @@ const {
SymbolIterator,
TypeError,
} = primordials;
const {
isArrayBuffer,
} = core;
const {
op_message_port_recv_message,
} = core.ensureFastOps();
@ -282,7 +284,7 @@ function serializeJsMessageData(data, transferables) {
const hostObjects = [];
for (let i = 0, j = 0; i < transferables.length; i++) {
const t = transferables[i];
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, t)) {
if (isArrayBuffer(t)) {
if (
ArrayBufferPrototypeGetByteLength(t) === 0 &&
isDetachedBuffer(t)
@ -329,9 +331,7 @@ function serializeJsMessageData(data, transferables) {
kind: "messagePort",
data: id,
});
} else if (
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, transferable)
) {
} else if (isArrayBuffer(transferable)) {
ArrayPrototypePush(serializedTransferables, {
kind: "arrayBuffer",
data: transferredArrayBuffers[arrayBufferI],

View File

@ -19,7 +19,7 @@ import { structuredClone } from "ext:deno_web/02_structured_clone.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
import { EventTarget } from "ext:deno_web/02_event.js";
import { opNow } from "ext:deno_web/02_timers.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
const illegalConstructorKey = Symbol("illegalConstructorKey");
let performanceEntries = [];

View File

@ -1,7 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import * as webidl from "ext:deno_webidl/00_webidl.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
const primordials = globalThis.__bootstrap.primordials;
const {

View File

@ -47,7 +47,7 @@ declare module "ext:deno_web/00_infra.js" {
}
declare module "ext:deno_web/01_dom_exception.js" {
export = DOMException;
const DOMException: DOMException;
}
declare module "ext:deno_web/01_mimesniff.js" {

View File

@ -10,11 +10,10 @@ import { core, primordials } from "ext:core/mod.js";
const ops = core.ops;
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { EventTarget } from "ext:deno_web/02_event.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
const {
ArrayBuffer,
ArrayBufferIsView,
ArrayIsArray,
ArrayPrototypeFilter,
ArrayPrototypeMap,
@ -45,9 +44,12 @@ const {
SymbolIterator,
TypeError,
Uint32Array,
Uint32ArrayPrototype,
Uint8Array,
} = primordials;
const {
isDataView,
isTypedArray,
} = core;
const {
op_webgpu_buffer_get_map_async,
op_webgpu_request_adapter,
@ -1690,17 +1692,14 @@ class GPUQueue {
});
/** @type {ArrayBufferLike} */
let abLike = data;
if (ArrayBufferIsView(data)) {
if (TypedArrayPrototypeGetSymbolToStringTag(data) !== undefined) {
// TypedArray
abLike = TypedArrayPrototypeGetBuffer(
/** @type {Uint8Array} */ (data),
);
} else {
// DataView
abLike = DataViewPrototypeGetBuffer(/** @type {DataView} */ (data));
}
if (isTypedArray(data)) {
abLike = TypedArrayPrototypeGetBuffer(
/** @type {Uint8Array} */ (data),
);
} else if (isDataView(data)) {
abLike = DataViewPrototypeGetBuffer(/** @type {DataView} */ (data));
}
const { err } = ops.op_webgpu_write_buffer(
device.rid,
bufferRid,
@ -1744,16 +1743,12 @@ class GPUQueue {
/** @type {ArrayBufferLike} */
let abLike = data;
if (ArrayBufferIsView(data)) {
if (TypedArrayPrototypeGetSymbolToStringTag(data) !== undefined) {
// TypedArray
abLike = TypedArrayPrototypeGetBuffer(
/** @type {Uint8Array} */ (data),
);
} else {
// DataView
abLike = DataViewPrototypeGetBuffer(/** @type {DataView} */ (data));
}
if (isTypedArray(data)) {
abLike = TypedArrayPrototypeGetBuffer(
/** @type {Uint8Array} */ (data),
);
} else if (isDataView(data)) {
abLike = DataViewPrototypeGetBuffer(/** @type {DataView} */ (data));
}
const { err } = ops.op_webgpu_write_texture(
@ -3778,10 +3773,8 @@ class GPURenderPassEncoder {
selfContext: "this",
});
if (
!(ObjectPrototypeIsPrototypeOf(
Uint32ArrayPrototype,
dynamicOffsetsData,
))
TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !==
"Uint32Array"
) {
dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []);
dynamicOffsetsDataStart = 0;
@ -4337,10 +4330,8 @@ class GPUComputePassEncoder {
selfContext: "this",
});
if (
!(ObjectPrototypeIsPrototypeOf(
Uint32ArrayPrototype,
dynamicOffsetsData,
))
TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !==
"Uint32Array"
) {
dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []);
dynamicOffsetsDataStart = 0;
@ -4555,10 +4546,8 @@ class GPURenderBundleEncoder {
selfContext: "this",
});
if (
!(ObjectPrototypeIsPrototypeOf(
Uint32ArrayPrototype,
dynamicOffsetsData,
))
TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !==
"Uint32Array"
) {
dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []);
dynamicOffsetsDataStart = 0;

View File

@ -8,7 +8,6 @@
import { core, primordials } from "ext:core/mod.js";
const {
ArrayBufferPrototype,
ArrayBufferIsView,
ArrayPrototypeForEach,
ArrayPrototypePush,
@ -67,7 +66,7 @@ const {
SetPrototypeDelete,
SetPrototypeAdd,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype
// SharedArrayBufferPrototype,
String,
StringPrototypeCharCodeAt,
StringPrototypeToWellFormed,
@ -82,6 +81,12 @@ const {
Uint8Array,
Uint8ClampedArray,
} = primordials;
const {
isArrayBuffer,
isDataView,
isSharedArrayBuffer,
isTypedArray,
} = core;
function makeException(ErrorType, message, prefix, context) {
return new ErrorType(
@ -456,27 +461,13 @@ function convertCallbackFunction(V, prefix, context, _opts) {
return V;
}
function isDataView(V) {
return ArrayBufferIsView(V) &&
TypedArrayPrototypeGetSymbolToStringTag(V) === undefined;
}
function isNonSharedArrayBuffer(V) {
return ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V);
}
function isSharedArrayBuffer(V) {
// deno-lint-ignore prefer-primordials
return ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V);
}
converters.ArrayBuffer = (
V,
prefix = undefined,
context = undefined,
opts = {},
) => {
if (!isNonSharedArrayBuffer(V)) {
if (!isArrayBuffer(V)) {
if (opts.allowShared && !isSharedArrayBuffer(V)) {
throw makeException(
TypeError,
@ -511,7 +502,10 @@ converters.DataView = (
);
}
if (!opts.allowShared && isSharedArrayBuffer(DataViewPrototypeGetBuffer(V))) {
if (
!opts.allowShared &&
isSharedArrayBuffer(DataViewPrototypeGetBuffer(V))
) {
throw makeException(
TypeError,
"is backed by a SharedArrayBuffer, which is not allowed",
@ -588,7 +582,7 @@ converters.ArrayBufferView = (
);
}
let buffer;
if (TypedArrayPrototypeGetSymbolToStringTag(V) !== undefined) {
if (isTypedArray(V)) {
buffer = TypedArrayPrototypeGetBuffer(V);
} else {
buffer = DataViewPrototypeGetBuffer(V);
@ -613,7 +607,7 @@ converters.BufferSource = (
) => {
if (ArrayBufferIsView(V)) {
let buffer;
if (TypedArrayPrototypeGetSymbolToStringTag(V) !== undefined) {
if (isTypedArray(V)) {
buffer = TypedArrayPrototypeGetBuffer(V);
} else {
buffer = DataViewPrototypeGetBuffer(V);
@ -630,7 +624,7 @@ converters.BufferSource = (
return V;
}
if (!opts.allowShared && !isNonSharedArrayBuffer(V)) {
if (!opts.allowShared && !isArrayBuffer(V)) {
throw makeException(
TypeError,
"is not an ArrayBuffer or a view on one",
@ -641,7 +635,7 @@ converters.BufferSource = (
if (
opts.allowShared &&
!isSharedArrayBuffer(V) &&
!isNonSharedArrayBuffer(V)
!isArrayBuffer(V)
) {
throw makeException(
TypeError,

View File

@ -7,7 +7,7 @@ import { URL } from "ext:deno_url/00_url.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
import { HTTP_TOKEN_CODE_POINT_RE } from "ext:deno_web/00_infra.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import {
CloseEvent,
defineEventHandler,
@ -21,7 +21,6 @@ import {
import { Blob, BlobPrototype } from "ext:deno_web/09_file.js";
import { getLocationHref } from "ext:deno_web/12_location.js";
const {
ArrayBufferPrototype,
ArrayBufferIsView,
ArrayPrototypeJoin,
ArrayPrototypeMap,
@ -29,21 +28,24 @@ const {
ErrorPrototypeToString,
ObjectDefineProperties,
ObjectPrototypeIsPrototypeOf,
PromisePrototypeCatch,
PromisePrototypeThen,
RegExpPrototypeExec,
SafeSet,
SetPrototypeGetSize,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype
String,
StringPrototypeEndsWith,
StringPrototypeToLowerCase,
Symbol,
SymbolIterator,
PromisePrototypeCatch,
SymbolFor,
SymbolIterator,
TypedArrayPrototypeGetByteLength,
Uint8Array,
} = primordials;
const {
isAnyArrayBuffer,
isArrayBuffer,
} = core;
import {
op_ws_check_permission_and_cancel_handle,
op_ws_close,
@ -80,11 +82,7 @@ webidl.converters["WebSocketSend"] = (V, prefix, context, opts) => {
return webidl.converters["Blob"](V, prefix, context, opts);
}
if (typeof V === "object") {
if (
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V) ||
// deno-lint-ignore prefer-primordials
ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V)
) {
if (isAnyArrayBuffer(V)) {
return webidl.converters["ArrayBuffer"](V, prefix, context, opts);
}
if (ArrayBufferIsView(V)) {
@ -329,8 +327,7 @@ class WebSocket extends EventTarget {
if (ArrayBufferIsView(data)) {
op_ws_send_binary(this[_rid], data);
} else if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, data)) {
// deno-lint-ignore prefer-primordials
} else if (isArrayBuffer(data)) {
op_ws_send_binary(this[_rid], new Uint8Array(data));
} else if (ObjectPrototypeIsPrototypeOf(BlobPrototype, data)) {
PromisePrototypeThen(

View File

@ -6,7 +6,7 @@ import { core, primordials } from "ext:core/mod.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
import { Deferred, writableStreamClose } from "ext:deno_web/06_streams.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import { add, remove } from "ext:deno_web/03_abort_signal.js";
import {
fillHeaders,
@ -29,7 +29,7 @@ const {
SymbolFor,
TypeError,
TypedArrayPrototypeGetByteLength,
Uint8ArrayPrototype,
TypedArrayPrototypeGetSymbolToStringTag,
} = primordials;
import {
op_ws_check_permission_and_cancel_handle,
@ -214,7 +214,8 @@ class WebSocketStream {
if (typeof chunk === "string") {
await op_ws_send_text_async(this[_rid], chunk);
} else if (
ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, chunk)
TypedArrayPrototypeGetSymbolToStringTag(chunk) ===
"Uint8Array"
) {
await op_ws_send_binary_async(this[_rid], chunk);
} else {

View File

@ -36,7 +36,7 @@ import * as fetch from "ext:deno_fetch/26_fetch.js";
import * as eventSource from "ext:deno_fetch/27_eventsource.js";
import * as messagePort from "ext:deno_web/13_message_port.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import * as abortSignal from "ext:deno_web/03_abort_signal.js";
import * as globalInterfaces from "ext:deno_web/04_global_interfaces.js";
import * as webStorage from "ext:deno_webstorage/01_webstorage.js";

View File

@ -27,6 +27,9 @@ const {
SymbolIterator,
TypeError,
} = primordials;
const {
isNativeError,
} = core;
import * as util from "ext:runtime/06_util.js";
import * as event from "ext:deno_web/02_event.js";
import * as location from "ext:deno_web/12_location.js";
@ -52,7 +55,7 @@ import {
} from "ext:runtime/90_deno_ns.js";
import { errors } from "ext:runtime/01_errors.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import {
mainRuntimeGlobalProperties,
memoizeLazy,
@ -235,7 +238,10 @@ const opPpid = memoizeLazy(() => ops.op_ppid());
setNoColorFn(() => ops.op_bootstrap_no_color() || !ops.op_bootstrap_is_tty());
function formatException(error) {
if (ObjectPrototypeIsPrototypeOf(ErrorPrototype, error)) {
if (
isNativeError(error) ||
ObjectPrototypeIsPrototypeOf(ErrorPrototype, error)
) {
return null;
} else if (typeof error == "string") {
return `Uncaught ${