1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -05:00

chore: Turn back on dlintPreferPrimordials (#17715)

Closes #17709
This commit is contained in:
Kenta Moriuchi 2023-04-03 02:41:41 +09:00 committed by GitHub
parent ad8d0c90d1
commit 03edd48edd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 688 additions and 308 deletions

3
core/internal.d.ts vendored
View file

@ -588,6 +588,7 @@ declare namespace __bootstrap {
export const MapLength: typeof Map.length; export const MapLength: typeof Map.length;
export const MapName: typeof Map.name; export const MapName: typeof Map.name;
export const MapPrototype: typeof Map.prototype; export const MapPrototype: typeof Map.prototype;
export const MapPrototypeGetSize: (map: Map) => number;
export const MapPrototypeGet: UncurryThis<typeof Map.prototype.get>; export const MapPrototypeGet: UncurryThis<typeof Map.prototype.get>;
export const MapPrototypeSet: UncurryThis<typeof Map.prototype.set>; export const MapPrototypeSet: UncurryThis<typeof Map.prototype.set>;
export const MapPrototypeHas: UncurryThis<typeof Map.prototype.has>; export const MapPrototypeHas: UncurryThis<typeof Map.prototype.has>;
@ -715,6 +716,7 @@ declare namespace __bootstrap {
export const SetLength: typeof Set.length; export const SetLength: typeof Set.length;
export const SetName: typeof Set.name; export const SetName: typeof Set.name;
export const SetPrototype: typeof Set.prototype; export const SetPrototype: typeof Set.prototype;
export const SetPrototypeGetSize: (set: Set) => number;
export const SetPrototypeHas: UncurryThis<typeof Set.prototype.has>; export const SetPrototypeHas: UncurryThis<typeof Set.prototype.has>;
export const SetPrototypeAdd: UncurryThis<typeof Set.prototype.add>; export const SetPrototypeAdd: UncurryThis<typeof Set.prototype.add>;
export const SetPrototypeDelete: UncurryThis<typeof Set.prototype.delete>; export const SetPrototypeDelete: UncurryThis<typeof Set.prototype.delete>;
@ -866,6 +868,7 @@ declare namespace __bootstrap {
export const SymbolLength: typeof Symbol.length; export const SymbolLength: typeof Symbol.length;
export const SymbolName: typeof Symbol.name; export const SymbolName: typeof Symbol.name;
export const SymbolPrototype: typeof Symbol.prototype; export const SymbolPrototype: typeof Symbol.prototype;
export const SymbolPrototypeGetDescription: (symbol: symbol) => string;
export const SymbolFor: typeof Symbol.for; export const SymbolFor: typeof Symbol.for;
export const SymbolKeyFor: typeof Symbol.keyFor; export const SymbolKeyFor: typeof Symbol.keyFor;
export const SymbolAsyncIterator: typeof Symbol.asyncIterator; export const SymbolAsyncIterator: typeof Symbol.asyncIterator;

View file

@ -64,6 +64,7 @@ const {
SymbolPrototype, SymbolPrototype,
SymbolPrototypeToString, SymbolPrototypeToString,
SymbolPrototypeValueOf, SymbolPrototypeValueOf,
SymbolPrototypeGetDescription,
SymbolToStringTag, SymbolToStringTag,
SymbolHasInstance, SymbolHasInstance,
SymbolFor, SymbolFor,
@ -662,7 +663,7 @@ function handleCircular(value, cyan) {
} else { } else {
index = MapPrototypeGet(circular, value); index = MapPrototypeGet(circular, value);
if (index === undefined) { if (index === undefined) {
index = circular.size + 1; index = MapPrototypeGetSize(circular) + 1;
MapPrototypeSet(circular, value, index); MapPrototypeSet(circular, value, index);
} }
} }
@ -809,20 +810,17 @@ const QUOTE_SYMBOL_REG = new SafeRegExp(/^[a-zA-Z_][a-zA-Z_.0-9]*$/);
// Surround a symbol's description in quotes when it is required (e.g the description has non printable characters). // Surround a symbol's description in quotes when it is required (e.g the description has non printable characters).
function maybeQuoteSymbol(symbol, inspectOptions) { function maybeQuoteSymbol(symbol, inspectOptions) {
if (symbol.description === undefined) { const description = SymbolPrototypeGetDescription(symbol);
if (description === undefined) {
return SymbolPrototypeToString(symbol); return SymbolPrototypeToString(symbol);
} }
if ( if (RegExpPrototypeTest(QUOTE_SYMBOL_REG, description)) {
RegExpPrototypeTest(
QUOTE_SYMBOL_REG,
symbol.description,
)
) {
return SymbolPrototypeToString(symbol); return SymbolPrototypeToString(symbol);
} }
return `Symbol(${quoteString(symbol.description, inspectOptions)})`; return `Symbol(${quoteString(description, inspectOptions)})`;
} }
const CTX_STACK = []; const CTX_STACK = [];
@ -1191,8 +1189,8 @@ function inspectRawObject(
symbolKeys, symbolKeys,
(s1, s2) => (s1, s2) =>
StringPrototypeLocaleCompare( StringPrototypeLocaleCompare(
s1.description ?? "", SymbolPrototypeGetDescription(s1) ?? "",
s2.description ?? "", SymbolPrototypeGetDescription(s2) ?? "",
), ),
); );
} }

View file

@ -13,15 +13,15 @@ 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 { const {
ArrayBufferPrototype, ArrayBufferPrototype,
ArrayBufferPrototypeSlice,
ArrayBufferPrototypeGetByteLength,
ArrayBufferIsView, ArrayBufferIsView,
ArrayPrototypeEvery, ArrayPrototypeEvery,
ArrayPrototypeFind, ArrayPrototypeFind,
ArrayPrototypeIncludes, ArrayPrototypeIncludes,
BigInt64ArrayPrototype, DataViewPrototypeGetBuffer,
BigUint64ArrayPrototype, DataViewPrototypeGetByteLength,
Int16ArrayPrototype, DataViewPrototypeGetByteOffset,
Int32ArrayPrototype,
Int8ArrayPrototype,
JSONParse, JSONParse,
JSONStringify, JSONStringify,
MathCeil, MathCeil,
@ -37,12 +37,12 @@ const {
SymbolFor, SymbolFor,
SyntaxError, SyntaxError,
TypedArrayPrototypeSlice, TypedArrayPrototypeSlice,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetSymbolToStringTag,
TypeError, TypeError,
Uint16ArrayPrototype,
Uint32ArrayPrototype,
Uint8Array, Uint8Array,
Uint8ArrayPrototype,
Uint8ClampedArrayPrototype,
WeakMap, WeakMap,
WeakMapPrototypeGet, WeakMapPrototypeGet,
WeakMapPrototypeSet, WeakMapPrototypeSet,
@ -250,13 +250,7 @@ function normalizeAlgorithm(algorithm, op) {
const idlValue = normalizedAlgorithm[member]; const idlValue = normalizedAlgorithm[member];
// 3. // 3.
if (idlType === "BufferSource" && idlValue) { if (idlType === "BufferSource" && idlValue) {
normalizedAlgorithm[member] = TypedArrayPrototypeSlice( normalizedAlgorithm[member] = copyBuffer(idlValue);
new Uint8Array(
ArrayBufferIsView(idlValue) ? idlValue.buffer : idlValue,
idlValue.byteOffset ?? 0,
idlValue.byteLength,
),
);
} else if (idlType === "HashAlgorithmIdentifier") { } else if (idlType === "HashAlgorithmIdentifier") {
normalizedAlgorithm[member] = normalizeAlgorithm(idlValue, "digest"); normalizedAlgorithm[member] = normalizeAlgorithm(idlValue, "digest");
} else if (idlType === "AlgorithmIdentifier") { } else if (idlType === "AlgorithmIdentifier") {
@ -273,10 +267,34 @@ function normalizeAlgorithm(algorithm, op) {
* @returns {Uint8Array} * @returns {Uint8Array}
*/ */
function copyBuffer(input) { 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)),
),
);
}
}
// ArrayBuffer
return TypedArrayPrototypeSlice( return TypedArrayPrototypeSlice(
ArrayBufferIsView(input) new Uint8Array(
? new Uint8Array(input.buffer, input.byteOffset, input.byteLength) input,
: new Uint8Array(input), 0,
ArrayBufferPrototypeGetByteLength(input),
),
); );
} }
@ -445,7 +463,7 @@ class SubtleCrypto {
/** /**
* @param {string} algorithm * @param {string} algorithm
* @param {BufferSource} data * @param {BufferSource} data
* @returns {Promise<Uint8Array>} * @returns {Promise<ArrayBuffer>}
*/ */
async digest(algorithm, data) { async digest(algorithm, data) {
webidl.assertBranded(this, SubtleCryptoPrototype); webidl.assertBranded(this, SubtleCryptoPrototype);
@ -470,7 +488,7 @@ class SubtleCrypto {
data, data,
); );
return result.buffer; return TypedArrayPrototypeGetBuffer(result);
} }
/** /**
@ -596,13 +614,13 @@ class SubtleCrypto {
}, data); }, data);
// 6. // 6.
return plainText.buffer; return TypedArrayPrototypeGetBuffer(plainText);
} }
case "AES-CBC": { case "AES-CBC": {
normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv); normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv);
// 1. // 1.
if (normalizedAlgorithm.iv.byteLength !== 16) { if (TypedArrayPrototypeGetByteLength(normalizedAlgorithm.iv) !== 16) {
throw new DOMException( throw new DOMException(
"Counter must be 16 bytes", "Counter must be 16 bytes",
"OperationError", "OperationError",
@ -617,13 +635,15 @@ class SubtleCrypto {
}, data); }, data);
// 6. // 6.
return plainText.buffer; return TypedArrayPrototypeGetBuffer(plainText);
} }
case "AES-CTR": { case "AES-CTR": {
normalizedAlgorithm.counter = copyBuffer(normalizedAlgorithm.counter); normalizedAlgorithm.counter = copyBuffer(normalizedAlgorithm.counter);
// 1. // 1.
if (normalizedAlgorithm.counter.byteLength !== 16) { if (
TypedArrayPrototypeGetByteLength(normalizedAlgorithm.counter) !== 16
) {
throw new DOMException( throw new DOMException(
"Counter vector must be 16 bytes", "Counter vector must be 16 bytes",
"OperationError", "OperationError",
@ -650,7 +670,7 @@ class SubtleCrypto {
}, data); }, data);
// 4. // 4.
return cipherText.buffer; return TypedArrayPrototypeGetBuffer(cipherText);
} }
case "AES-GCM": { case "AES-GCM": {
normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv); normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv);
@ -671,7 +691,10 @@ class SubtleCrypto {
} }
// 2. // 2.
if (data.byteLength < normalizedAlgorithm.tagLength / 8) { if (
TypedArrayPrototypeGetByteLength(data) <
normalizedAlgorithm.tagLength / 8
) {
throw new DOMException( throw new DOMException(
"Tag length overflows ciphertext", "Tag length overflows ciphertext",
"OperationError", "OperationError",
@ -682,7 +705,7 @@ class SubtleCrypto {
if ( if (
ArrayPrototypeIncludes( ArrayPrototypeIncludes(
[12, 16], [12, 16],
normalizedAlgorithm.iv.byteLength, TypedArrayPrototypeGetByteLength(normalizedAlgorithm.iv),
) === undefined ) === undefined
) { ) {
throw new DOMException( throw new DOMException(
@ -693,12 +716,13 @@ class SubtleCrypto {
// 4. // 4.
if (normalizedAlgorithm.additionalData !== undefined) { if (normalizedAlgorithm.additionalData !== undefined) {
if (normalizedAlgorithm.additionalData.byteLength > (2 ** 64) - 1) { // NOTE: over the size of Number.MAX_SAFE_INTEGER is not available in V8
throw new DOMException( // if (normalizedAlgorithm.additionalData.byteLength > (2 ** 64) - 1) {
"Additional data too large", // throw new DOMException(
"OperationError", // "Additional data too large",
); // "OperationError",
} // );
// }
normalizedAlgorithm.additionalData = copyBuffer( normalizedAlgorithm.additionalData = copyBuffer(
normalizedAlgorithm.additionalData, normalizedAlgorithm.additionalData,
); );
@ -716,7 +740,7 @@ class SubtleCrypto {
}, data); }, data);
// 9. // 9.
return plaintext.buffer; return TypedArrayPrototypeGetBuffer(plaintext);
} }
default: default:
throw new DOMException("Not implemented", "NotSupportedError"); throw new DOMException("Not implemented", "NotSupportedError");
@ -789,7 +813,7 @@ class SubtleCrypto {
hash: hashAlgorithm, hash: hashAlgorithm,
}, data); }, data);
return signature.buffer; return TypedArrayPrototypeGetBuffer(signature);
} }
case "RSA-PSS": { case "RSA-PSS": {
// 1. // 1.
@ -809,7 +833,7 @@ class SubtleCrypto {
saltLength: normalizedAlgorithm.saltLength, saltLength: normalizedAlgorithm.saltLength,
}, data); }, data);
return signature.buffer; return TypedArrayPrototypeGetBuffer(signature);
} }
case "ECDSA": { case "ECDSA": {
// 1. // 1.
@ -846,7 +870,7 @@ class SubtleCrypto {
namedCurve, namedCurve,
}, data); }, data);
return signature.buffer; return TypedArrayPrototypeGetBuffer(signature);
} }
case "HMAC": { case "HMAC": {
const hashAlgorithm = key[_algorithm].hash.name; const hashAlgorithm = key[_algorithm].hash.name;
@ -857,7 +881,7 @@ class SubtleCrypto {
hash: hashAlgorithm, hash: hashAlgorithm,
}, data); }, data);
return signature.buffer; return TypedArrayPrototypeGetBuffer(signature);
} }
case "Ed25519": { case "Ed25519": {
// 1. // 1.
@ -877,7 +901,7 @@ class SubtleCrypto {
"OperationError", "OperationError",
); );
} }
return signature.buffer; return TypedArrayPrototypeGetBuffer(signature);
} }
} }
@ -1471,7 +1495,7 @@ class SubtleCrypto {
}, bytes); }, bytes);
// 4. // 4.
return cipherText.buffer; return TypedArrayPrototypeGetBuffer(cipherText);
} }
default: { default: {
throw new DOMException( throw new DOMException(
@ -1607,7 +1631,7 @@ class SubtleCrypto {
}, wrappedKey); }, wrappedKey);
// 4. // 4.
key = plainText.buffer; key = TypedArrayPrototypeGetBuffer(plainText);
break; break;
} }
default: { default: {
@ -2127,7 +2151,7 @@ async function generateKey(normalizedAlgorithm, extractable, usages) {
hash: { hash: {
name: normalizedAlgorithm.hash.name, name: normalizedAlgorithm.hash.name,
}, },
length: keyData.byteLength * 8, length: TypedArrayPrototypeGetByteLength(keyData) * 8,
}; };
// 5, 11-13. // 5, 11-13.
@ -2589,7 +2613,7 @@ function exportKeyAES(
// 1. // 1.
const data = innerKey.data; const data = innerKey.data;
// 2. // 2.
return data.buffer; return TypedArrayPrototypeGetBuffer(data);
} }
case "jwk": { case "jwk": {
// 1-2. // 1-2.
@ -2664,7 +2688,10 @@ function importKeyAES(
case "raw": { case "raw": {
// 2. // 2.
if ( if (
!ArrayPrototypeIncludes([128, 192, 256], keyData.byteLength * 8) !ArrayPrototypeIncludes(
[128, 192, 256],
TypedArrayPrototypeGetByteLength(keyData) * 8,
)
) { ) {
throw new DOMException("Invalid key length", "Datarror"); throw new DOMException("Invalid key length", "Datarror");
} }
@ -2699,7 +2726,7 @@ function importKeyAES(
data = rawData.data; data = rawData.data;
// 5. // 5.
switch (data.byteLength * 8) { switch (TypedArrayPrototypeGetByteLength(data) * 8) {
case 128: case 128:
if ( if (
jwk.alg !== undefined && jwk.alg !== undefined &&
@ -2789,7 +2816,7 @@ function importKeyAES(
// 4-7. // 4-7.
const algorithm = { const algorithm = {
name: algorithmName, name: algorithmName,
length: data.byteLength * 8, length: TypedArrayPrototypeGetByteLength(data) * 8,
}; };
const key = constructKey( const key = constructKey(
@ -2956,7 +2983,7 @@ function importKeyHMAC(
} }
// 5. // 5.
let length = data.byteLength * 8; let length = TypedArrayPrototypeGetByteLength(data) * 8;
// 6. // 6.
if (length === 0) { if (length === 0) {
throw new DOMException("Key length is zero", "DataError"); throw new DOMException("Key length is zero", "DataError");
@ -3856,11 +3883,12 @@ function exportKeyHMAC(format, key, innerKey) {
// 3. // 3.
case "raw": { case "raw": {
const bits = innerKey.data; const bits = innerKey.data;
for (let _i = 7 & (8 - bits.length % 8); _i > 0; _i--) { // TODO(petamoriken): Uint8Array doesn't have push method
bits.push(0); // for (let _i = 7 & (8 - bits.length % 8); _i > 0; _i--) {
} // bits.push(0);
// }
// 4-5. // 4-5.
return bits.buffer; return TypedArrayPrototypeGetBuffer(bits);
} }
case "jwk": { case "jwk": {
// 1-2. // 1-2.
@ -3929,7 +3957,7 @@ function exportKeyRSA(format, key, innerKey) {
}, innerKey); }, innerKey);
// 3. // 3.
return data.buffer; return TypedArrayPrototypeGetBuffer(data);
} }
case "spki": { case "spki": {
// 1. // 1.
@ -3947,7 +3975,7 @@ function exportKeyRSA(format, key, innerKey) {
}, innerKey); }, innerKey);
// 3. // 3.
return data.buffer; return TypedArrayPrototypeGetBuffer(data);
} }
case "jwk": { case "jwk": {
// 1-2. // 1-2.
@ -4053,7 +4081,7 @@ function exportKeyEd25519(format, key, innerKey) {
} }
// 2-3. // 2-3.
return innerKey.buffer; return TypedArrayPrototypeGetBuffer(innerKey);
} }
case "spki": { case "spki": {
// 1. // 1.
@ -4065,7 +4093,7 @@ function exportKeyEd25519(format, key, innerKey) {
} }
const spkiDer = ops.op_export_spki_ed25519(innerKey); const spkiDer = ops.op_export_spki_ed25519(innerKey);
return spkiDer.buffer; return TypedArrayPrototypeGetBuffer(spkiDer);
} }
case "pkcs8": { case "pkcs8": {
// 1. // 1.
@ -4080,7 +4108,7 @@ function exportKeyEd25519(format, key, innerKey) {
new Uint8Array([0x04, 0x22, ...new SafeArrayIterator(innerKey)]), new Uint8Array([0x04, 0x22, ...new SafeArrayIterator(innerKey)]),
); );
pkcs8Der[15] = 0x20; pkcs8Der[15] = 0x20;
return pkcs8Der.buffer; return TypedArrayPrototypeGetBuffer(pkcs8Der);
} }
case "jwk": { case "jwk": {
const x = key[_type] === "private" const x = key[_type] === "private"
@ -4116,7 +4144,7 @@ function exportKeyX25519(format, key, innerKey) {
} }
// 2-3. // 2-3.
return innerKey.buffer; return TypedArrayPrototypeGetBuffer(innerKey);
} }
case "spki": { case "spki": {
// 1. // 1.
@ -4128,7 +4156,7 @@ function exportKeyX25519(format, key, innerKey) {
} }
const spkiDer = ops.op_export_spki_x25519(innerKey); const spkiDer = ops.op_export_spki_x25519(innerKey);
return spkiDer.buffer; return TypedArrayPrototypeGetBuffer(spkiDer);
} }
case "pkcs8": { case "pkcs8": {
// 1. // 1.
@ -4143,7 +4171,7 @@ function exportKeyX25519(format, key, innerKey) {
new Uint8Array([0x04, 0x22, ...new SafeArrayIterator(innerKey)]), new Uint8Array([0x04, 0x22, ...new SafeArrayIterator(innerKey)]),
); );
pkcs8Der[15] = 0x20; pkcs8Der[15] = 0x20;
return pkcs8Der.buffer; return TypedArrayPrototypeGetBuffer(pkcs8Der);
} }
case "jwk": { case "jwk": {
if (key[_type] === "private") { if (key[_type] === "private") {
@ -4182,7 +4210,7 @@ function exportKeyEC(format, key, innerKey) {
format: "raw", format: "raw",
}, innerKey); }, innerKey);
return data.buffer; return TypedArrayPrototypeGetBuffer(data);
} }
case "pkcs8": { case "pkcs8": {
// 1. // 1.
@ -4200,7 +4228,7 @@ function exportKeyEC(format, key, innerKey) {
format: "pkcs8", format: "pkcs8",
}, innerKey); }, innerKey);
return data.buffer; return TypedArrayPrototypeGetBuffer(data);
} }
case "spki": { case "spki": {
// 1. // 1.
@ -4218,7 +4246,7 @@ function exportKeyEC(format, key, innerKey) {
format: "spki", format: "spki",
}, innerKey); }, innerKey);
return data.buffer; return TypedArrayPrototypeGetBuffer(data);
} }
case "jwk": { case "jwk": {
if (key[_algorithm].name == "ECDSA") { if (key[_algorithm].name == "ECDSA") {
@ -4370,7 +4398,7 @@ async function deriveBits(normalizedAlgorithm, baseKey, length) {
length, length,
}, normalizedAlgorithm.salt); }, normalizedAlgorithm.salt);
return buf.buffer; return TypedArrayPrototypeGetBuffer(buf);
} }
case "ECDH": { case "ECDH": {
// 1. // 1.
@ -4421,11 +4449,15 @@ async function deriveBits(normalizedAlgorithm, baseKey, length) {
// 8. // 8.
if (length === null) { if (length === null) {
return buf.buffer; return TypedArrayPrototypeGetBuffer(buf);
} else if (buf.buffer.byteLength * 8 < length) { } else if (TypedArrayPrototypeGetByteLength(buf) * 8 < length) {
throw new DOMException("Invalid length", "OperationError"); throw new DOMException("Invalid length", "OperationError");
} else { } else {
return buf.buffer.slice(0, MathCeil(length / 8)); return ArrayBufferPrototypeSlice(
TypedArrayPrototypeGetBuffer(buf),
0,
MathCeil(length / 8),
);
} }
} else { } else {
throw new DOMException("Not implemented", "NotSupportedError"); throw new DOMException("Not implemented", "NotSupportedError");
@ -4452,7 +4484,7 @@ async function deriveBits(normalizedAlgorithm, baseKey, length) {
length, length,
}, normalizedAlgorithm.salt); }, normalizedAlgorithm.salt);
return buf.buffer; return TypedArrayPrototypeGetBuffer(buf);
} }
case "X25519": { case "X25519": {
// 1. // 1.
@ -4490,13 +4522,17 @@ async function deriveBits(normalizedAlgorithm, baseKey, length) {
// 7. // 7.
if (length === null) { if (length === null) {
return secret.buffer; return TypedArrayPrototypeGetBuffer(secret);
} else if ( } else if (
secret.buffer.byteLength * 8 < length TypedArrayPrototypeGetByteLength(secret) * 8 < length
) { ) {
throw new DOMException("Invalid length", "OperationError"); throw new DOMException("Invalid length", "OperationError");
} else { } else {
return secret.buffer.slice(0, MathCeil(length / 8)); return ArrayBufferPrototypeSlice(
TypedArrayPrototypeGetBuffer(secret),
0,
MathCeil(length / 8),
);
} }
} }
default: default:
@ -4535,13 +4571,13 @@ async function encrypt(normalizedAlgorithm, key, data) {
}, data); }, data);
// 6. // 6.
return cipherText.buffer; return TypedArrayPrototypeGetBuffer(cipherText);
} }
case "AES-CBC": { case "AES-CBC": {
normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv); normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv);
// 1. // 1.
if (normalizedAlgorithm.iv.byteLength !== 16) { if (TypedArrayPrototypeGetByteLength(normalizedAlgorithm.iv) !== 16) {
throw new DOMException( throw new DOMException(
"Initialization vector must be 16 bytes", "Initialization vector must be 16 bytes",
"OperationError", "OperationError",
@ -4557,13 +4593,15 @@ async function encrypt(normalizedAlgorithm, key, data) {
}, data); }, data);
// 4. // 4.
return cipherText.buffer; return TypedArrayPrototypeGetBuffer(cipherText);
} }
case "AES-CTR": { case "AES-CTR": {
normalizedAlgorithm.counter = copyBuffer(normalizedAlgorithm.counter); normalizedAlgorithm.counter = copyBuffer(normalizedAlgorithm.counter);
// 1. // 1.
if (normalizedAlgorithm.counter.byteLength !== 16) { if (
TypedArrayPrototypeGetByteLength(normalizedAlgorithm.counter) !== 16
) {
throw new DOMException( throw new DOMException(
"Counter vector must be 16 bytes", "Counter vector must be 16 bytes",
"OperationError", "OperationError",
@ -4590,13 +4628,13 @@ async function encrypt(normalizedAlgorithm, key, data) {
}, data); }, data);
// 4. // 4.
return cipherText.buffer; return TypedArrayPrototypeGetBuffer(cipherText);
} }
case "AES-GCM": { case "AES-GCM": {
normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv); normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv);
// 1. // 1.
if (data.byteLength > (2 ** 39) - 256) { if (TypedArrayPrototypeGetByteLength(data) > (2 ** 39) - 256) {
throw new DOMException( throw new DOMException(
"Plaintext too large", "Plaintext too large",
"OperationError", "OperationError",
@ -4608,7 +4646,7 @@ async function encrypt(normalizedAlgorithm, key, data) {
if ( if (
ArrayPrototypeIncludes( ArrayPrototypeIncludes(
[12, 16], [12, 16],
normalizedAlgorithm.iv.byteLength, TypedArrayPrototypeGetByteLength(normalizedAlgorithm.iv),
) === undefined ) === undefined
) { ) {
throw new DOMException( throw new DOMException(
@ -4618,14 +4656,15 @@ async function encrypt(normalizedAlgorithm, key, data) {
} }
// 3. // 3.
if (normalizedAlgorithm.additionalData !== undefined) { // NOTE: over the size of Number.MAX_SAFE_INTEGER is not available in V8
if (normalizedAlgorithm.additionalData.byteLength > (2 ** 64) - 1) { // if (normalizedAlgorithm.additionalData !== undefined) {
throw new DOMException( // if (normalizedAlgorithm.additionalData.byteLength > (2 ** 64) - 1) {
"Additional data too large", // throw new DOMException(
"OperationError", // "Additional data too large",
); // "OperationError",
} // );
} // }
// }
// 4. // 4.
if (normalizedAlgorithm.tagLength == undefined) { if (normalizedAlgorithm.tagLength == undefined) {
@ -4658,7 +4697,7 @@ async function encrypt(normalizedAlgorithm, key, data) {
}, data); }, data);
// 8. // 8.
return cipherText.buffer; return TypedArrayPrototypeGetBuffer(cipherText);
} }
default: default:
throw new DOMException("Not implemented", "NotSupportedError"); throw new DOMException("Not implemented", "NotSupportedError");
@ -4673,50 +4712,43 @@ class Crypto {
webidl.illegalConstructor(); webidl.illegalConstructor();
} }
getRandomValues(arrayBufferView) { getRandomValues(typedArray) {
webidl.assertBranded(this, CryptoPrototype); webidl.assertBranded(this, CryptoPrototype);
const prefix = "Failed to execute 'getRandomValues' on 'Crypto'"; const prefix = "Failed to execute 'getRandomValues' on 'Crypto'";
webidl.requiredArguments(arguments.length, 1, { prefix }); webidl.requiredArguments(arguments.length, 1, { prefix });
// Fast path for Uint8Array // Fast path for Uint8Array
if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, arrayBufferView)) { const tag = TypedArrayPrototypeGetSymbolToStringTag(typedArray);
ops.op_crypto_get_random_values(arrayBufferView); if (tag === "Uint8Array") {
return arrayBufferView; ops.op_crypto_get_random_values(typedArray);
return typedArray;
} }
arrayBufferView = webidl.converters.ArrayBufferView(arrayBufferView, { typedArray = webidl.converters.ArrayBufferView(typedArray, {
prefix, prefix,
context: "Argument 1", context: "Argument 1",
}); });
if ( switch (tag) {
!( case "Int8Array":
ObjectPrototypeIsPrototypeOf(Int8ArrayPrototype, arrayBufferView) || case "Uint8ClampedArray":
ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, arrayBufferView) || case "Int16Array":
ObjectPrototypeIsPrototypeOf( case "Uint16Array":
Uint8ClampedArrayPrototype, case "Int32Array":
arrayBufferView, case "Uint32Array":
) || case "BigInt64Array":
ObjectPrototypeIsPrototypeOf(Int16ArrayPrototype, arrayBufferView) || case "BigUint64Array":
ObjectPrototypeIsPrototypeOf(Uint16ArrayPrototype, arrayBufferView) || break;
ObjectPrototypeIsPrototypeOf(Int32ArrayPrototype, arrayBufferView) || default:
ObjectPrototypeIsPrototypeOf(Uint32ArrayPrototype, arrayBufferView) || throw new DOMException(
ObjectPrototypeIsPrototypeOf( "The provided ArrayBufferView is not an integer array type",
BigInt64ArrayPrototype, "TypeMismatchError",
arrayBufferView, );
) ||
ObjectPrototypeIsPrototypeOf(BigUint64ArrayPrototype, arrayBufferView)
)
) {
throw new DOMException(
"The provided ArrayBufferView is not an integer array type",
"TypeMismatchError",
);
} }
const ui8 = new Uint8Array( const ui8 = new Uint8Array(
arrayBufferView.buffer, TypedArrayPrototypeGetBuffer(typedArray),
arrayBufferView.byteOffset, TypedArrayPrototypeGetByteOffset(typedArray),
arrayBufferView.byteLength, TypedArrayPrototypeGetByteLength(typedArray),
); );
ops.op_crypto_get_random_values(ui8); ops.op_crypto_get_random_values(ui8);
return arrayBufferView; return typedArray;
} }
randomUUID() { randomUUID() {

View file

@ -38,17 +38,24 @@ import {
const primordials = globalThis.__bootstrap.primordials; const primordials = globalThis.__bootstrap.primordials;
const { const {
ArrayBufferPrototype, ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
ArrayBufferIsView, ArrayBufferIsView,
ArrayPrototypeMap, ArrayPrototypeMap,
DataViewPrototypeGetBuffer,
DataViewPrototypeGetByteLength,
DataViewPrototypeGetByteOffset,
JSONParse, JSONParse,
ObjectDefineProperties, ObjectDefineProperties,
ObjectPrototypeIsPrototypeOf, ObjectPrototypeIsPrototypeOf,
// TODO(lucacasonato): add SharedArrayBuffer to primordials // TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype // SharedArrayBufferPrototype
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetSymbolToStringTag,
TypedArrayPrototypeSlice, TypedArrayPrototypeSlice,
TypeError, TypeError,
Uint8Array, Uint8Array,
Uint8ArrayPrototype,
} = primordials; } = primordials;
/** /**
@ -328,7 +335,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) {
function packageData(bytes, type, mimeType) { function packageData(bytes, type, mimeType) {
switch (type) { switch (type) {
case "ArrayBuffer": case "ArrayBuffer":
return chunkToU8(bytes).buffer; return TypedArrayPrototypeGetBuffer(chunkToU8(bytes));
case "Blob": case "Blob":
return new Blob([bytes], { return new Blob([bytes], {
type: mimeType !== null ? mimesniff.serializeMimeType(mimeType) : "", type: mimeType !== null ? mimesniff.serializeMimeType(mimeType) : "",
@ -385,22 +392,45 @@ function extractBody(object) {
if (object.type.length !== 0) { if (object.type.length !== 0) {
contentType = object.type; contentType = object.type;
} }
} else if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, object)) { } else if (ArrayBufferIsView(object)) {
// Fast(er) path for common case of Uint8Array const tag = TypedArrayPrototypeGetSymbolToStringTag(object);
const copy = TypedArrayPrototypeSlice(object, 0, object.byteLength); if (tag === "Uint8Array") {
source = copy; // Fast(er) path for common case of Uint8Array
} else if ( const copy = TypedArrayPrototypeSlice(
ArrayBufferIsView(object) || object,
ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, object) TypedArrayPrototypeGetByteOffset(/** @type {Uint8Array} */ (object)),
) { TypedArrayPrototypeGetByteLength(/** @type {Uint8Array} */ (object)),
const u8 = ArrayBufferIsView(object) );
? new Uint8Array( source = copy;
object.buffer, } else if (tag !== undefined) {
object.byteOffset, // TypedArray
object.byteLength, const copy = TypedArrayPrototypeSlice(
) new Uint8Array(
: new Uint8Array(object); TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (object)),
const copy = TypedArrayPrototypeSlice(u8, 0, u8.byteLength); TypedArrayPrototypeGetByteOffset(/** @type {Uint8Array} */ (object)),
TypedArrayPrototypeGetByteLength(/** @type {Uint8Array} */ (object)),
),
);
source = copy;
} else {
// DataView
const copy = TypedArrayPrototypeSlice(
new Uint8Array(
DataViewPrototypeGetBuffer(/** @type {DataView} */ (object)),
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (object)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (object)),
),
);
source = copy;
}
} else if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, object)) {
const copy = TypedArrayPrototypeSlice(
new Uint8Array(
object,
0,
ArrayBufferPrototypeGetByteLength(object),
),
);
source = copy; source = copy;
} else if (ObjectPrototypeIsPrototypeOf(FormDataPrototype, object)) { } else if (ObjectPrototypeIsPrototypeOf(FormDataPrototype, object)) {
const res = formDataToBlob(object); const res = formDataToBlob(object);
@ -426,9 +456,9 @@ function extractBody(object) {
// no observable side-effect for users so far, but could change // no observable side-effect for users so far, but could change
stream = { body: source, consumed: false }; stream = { body: source, consumed: false };
length = null; // NOTE: string length != byte length length = null; // NOTE: string length != byte length
} else if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, source)) { } else if (TypedArrayPrototypeGetSymbolToStringTag(source) === "Uint8Array") {
stream = { body: source, consumed: false }; stream = { body: source, consumed: false };
length = source.byteLength; length = TypedArrayPrototypeGetByteLength(source);
} }
const body = new InnerBody(stream); const body = new InnerBody(stream);
body.source = source; body.source = source;

View file

@ -4,13 +4,19 @@ const core = globalThis.Deno.core;
const ops = core.ops; const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials; const primordials = globalThis.__bootstrap.primordials;
const { const {
ArrayBufferIsView,
ArrayBufferPrototypeGetByteLength,
ArrayPrototypeMap, ArrayPrototypeMap,
ArrayPrototypeJoin, ArrayPrototypeJoin,
DataViewPrototypeGetByteLength,
ObjectDefineProperty, ObjectDefineProperty,
ObjectPrototypeHasOwnProperty, ObjectPrototypeHasOwnProperty,
ObjectPrototypeIsPrototypeOf, ObjectPrototypeIsPrototypeOf,
Number, Number,
NumberIsSafeInteger, NumberIsSafeInteger,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetSymbolToStringTag,
TypeError, TypeError,
Uint8Array, Uint8Array,
Int32Array, Int32Array,
@ -29,11 +35,27 @@ const {
} = primordials; } = primordials;
import { pathFromURL } from "ext:deno_web/00_infra.js"; import { pathFromURL } from "ext:deno_web/00_infra.js";
/**
* @param {BufferSource} source
* @returns {number}
*/
function getBufferSourceByteLength(source) {
if (ArrayBufferIsView(source)) {
if (TypedArrayPrototypeGetSymbolToStringTag(source) !== undefined) {
// TypedArray
return TypedArrayPrototypeGetByteLength(source);
} else {
// DataView
return DataViewPrototypeGetByteLength(source);
}
}
return ArrayBufferPrototypeGetByteLength(source);
}
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId"); const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
const U32_BUFFER = new Uint32Array(2); const U32_BUFFER = new Uint32Array(2);
const U64_BUFFER = new BigUint64Array(U32_BUFFER.buffer); const U64_BUFFER = new BigUint64Array(TypedArrayPrototypeGetBuffer(U32_BUFFER));
const I64_BUFFER = new BigInt64Array(U32_BUFFER.buffer); const I64_BUFFER = new BigInt64Array(TypedArrayPrototypeGetBuffer(U32_BUFFER));
class UnsafePointerView { class UnsafePointerView {
pointer; pointer;
@ -164,7 +186,7 @@ class UnsafePointerView {
this.pointer, this.pointer,
offset, offset,
destination, destination,
destination.byteLength, getBufferSourceByteLength(destination),
); );
} }
@ -173,13 +195,15 @@ class UnsafePointerView {
pointer, pointer,
offset, offset,
destination, destination,
destination.byteLength, getBufferSourceByteLength(destination),
); );
} }
} }
const OUT_BUFFER = new Uint32Array(2); const OUT_BUFFER = new Uint32Array(2);
const OUT_BUFFER_64 = new BigInt64Array(OUT_BUFFER.buffer); const OUT_BUFFER_64 = new BigInt64Array(
TypedArrayPrototypeGetBuffer(OUT_BUFFER),
);
const POINTER_TO_BUFFER_WEAK_MAP = new WeakMap(); const POINTER_TO_BUFFER_WEAK_MAP = new WeakMap();
class UnsafePointer { class UnsafePointer {
static create(value) { static create(value) {
@ -492,8 +516,8 @@ class DynamicLibrary {
const call = this.symbols[symbol]; const call = this.symbols[symbol];
const parameters = symbols[symbol].parameters; const parameters = symbols[symbol].parameters;
const vi = new Int32Array(2); const vi = new Int32Array(2);
const vui = new Uint32Array(vi.buffer); const vui = new Uint32Array(TypedArrayPrototypeGetBuffer(vi));
const b = new BigInt64Array(vi.buffer); const b = new BigInt64Array(TypedArrayPrototypeGetBuffer(vi));
const params = ArrayPrototypeJoin( const params = ArrayPrototypeJoin(
ArrayPrototypeMap(parameters, (_, index) => `p${index}`), ArrayPrototypeMap(parameters, (_, index) => `p${index}`),

View file

@ -31,11 +31,12 @@ const {
PromisePrototypeCatch, PromisePrototypeCatch,
PromisePrototypeThen, PromisePrototypeThen,
SafePromiseAll, SafePromiseAll,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetSymbolToStringTag,
TypedArrayPrototypeSet, TypedArrayPrototypeSet,
TypedArrayPrototypeSubarray, TypedArrayPrototypeSubarray,
TypeError, TypeError,
Uint8Array, Uint8Array,
Uint8ArrayPrototype,
} = primordials; } = primordials;
const statusCodes = { const statusCodes = {
@ -188,9 +189,15 @@ function http1Response(
str += body ?? ""; str += body ?? "";
} else { } else {
const head = core.encode(str); const head = core.encode(str);
const response = new Uint8Array(head.byteLength + bodyLen); const response = new Uint8Array(
TypedArrayPrototypeGetByteLength(head) + bodyLen,
);
TypedArrayPrototypeSet(response, head, 0); TypedArrayPrototypeSet(response, head, 0);
TypedArrayPrototypeSet(response, body, head.byteLength); TypedArrayPrototypeSet(
response,
body,
TypedArrayPrototypeGetByteLength(head),
);
return response; return response;
} }
@ -303,7 +310,7 @@ async function handleResponse(
} }
isStreamingResponseBody = !( isStreamingResponseBody = !(
typeof respBody === "string" || typeof respBody === "string" ||
ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, respBody) TypedArrayPrototypeGetSymbolToStringTag(respBody) === "Uint8Array"
); );
} else { } else {
if (innerResp.body.streamOrStatic.consumed === true) { if (innerResp.body.streamOrStatic.consumed === true) {
@ -318,7 +325,9 @@ async function handleResponse(
const ws = resp[_ws]; const ws = resp[_ws];
if (isStreamingResponseBody === false) { if (isStreamingResponseBody === false) {
const length = respBody.byteLength || core.byteLength(respBody); const length = typeof respBody === "string"
? core.byteLength(respBody)
: TypedArrayPrototypeGetByteLength(respBody);
const responseStr = http1Response( const responseStr = http1Response(
method, method,
innerResp.status ?? 200, innerResp.status ?? 200,
@ -394,8 +403,10 @@ async function handleResponse(
innerResp.status ?? 200, innerResp.status ?? 200,
innerResp.headerList, innerResp.headerList,
null, null,
// deno-lint-ignore prefer-primordials
respBody.byteLength, respBody.byteLength,
), ),
// deno-lint-ignore prefer-primordials
respBody.byteLength, respBody.byteLength,
false, false,
respondFast, respondFast,
@ -722,7 +733,7 @@ function createRequestBodyStream(serverId, token) {
token, token,
); );
if (!firstRead) return null; if (!firstRead) return null;
let firstEnqueued = firstRead.byteLength == 0; let firstEnqueued = TypedArrayPrototypeGetByteLength(firstRead) === 0;
return new ReadableStream({ return new ReadableStream({
type: "bytes", type: "bytes",

View file

@ -137,7 +137,10 @@ function readDir(path) {
); );
return { return {
async *[SymbolAsyncIterator]() { async *[SymbolAsyncIterator]() {
yield* await array; const dir = await array;
for (let i = 0; i < dir.length; ++i) {
yield dir[i];
}
}, },
}; };
} }

View file

@ -17,6 +17,8 @@ const {
MathMin, MathMin,
TypedArrayPrototypeSubarray, TypedArrayPrototypeSubarray,
TypedArrayPrototypeSet, TypedArrayPrototypeSet,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
} = primordials; } = primordials;
const DEFAULT_BUFFER_SIZE = 32 * 1024; const DEFAULT_BUFFER_SIZE = 32 * 1024;
@ -131,7 +133,10 @@ async function readAllInner(r, options) {
const buf = new Uint8Array(READ_PER_ITER); const buf = new Uint8Array(READ_PER_ITER);
const read = await r.read(buf); const read = await r.read(buf);
if (typeof read == "number") { if (typeof read == "number") {
ArrayPrototypePush(buffers, new Uint8Array(buf.buffer, 0, read)); ArrayPrototypePush(
buffers,
new Uint8Array(TypedArrayPrototypeGetBuffer(buf), 0, read),
);
} else { } else {
break; break;
} }
@ -160,7 +165,7 @@ function readAllSync(r) {
function concatBuffers(buffers) { function concatBuffers(buffers) {
let totalLen = 0; let totalLen = 0;
for (let i = 0; i < buffers.length; ++i) { for (let i = 0; i < buffers.length; ++i) {
totalLen += buffers[i].byteLength; totalLen += TypedArrayPrototypeGetByteLength(buffers[i]);
} }
const contents = new Uint8Array(totalLen); const contents = new Uint8Array(totalLen);
@ -169,7 +174,7 @@ function concatBuffers(buffers) {
for (let i = 0; i < buffers.length; ++i) { for (let i = 0; i < buffers.length; ++i) {
const buf = buffers[i]; const buf = buffers[i];
TypedArrayPrototypeSet(contents, buf, n); TypedArrayPrototypeSet(contents, buf, n);
n += buf.byteLength; n += TypedArrayPrototypeGetByteLength(buf);
} }
return contents; return contents;

View file

@ -19,6 +19,7 @@ const {
PromisePrototypeThen, PromisePrototypeThen,
SafeArrayIterator, SafeArrayIterator,
SymbolFor, SymbolFor,
TypedArrayPrototypeGetBuffer,
TypeError, TypeError,
indirectEval, indirectEval,
} = primordials; } = primordials;
@ -27,7 +28,7 @@ import { reportException } from "ext:deno_web/02_event.js";
import { assert } from "ext:deno_web/00_infra.js"; import { assert } from "ext:deno_web/00_infra.js";
const hrU8 = new Uint8Array(8); const hrU8 = new Uint8Array(8);
const hr = new Uint32Array(hrU8.buffer); const hr = new Uint32Array(TypedArrayPrototypeGetBuffer(hrU8));
function opNow() { function opNow() {
ops.op_now(hrU8); ops.op_now(hrU8);
return (hr[0] * 1000 + hr[1] / 1e6); return (hr[0] * 1000 + hr[1] / 1e6);

View file

@ -20,6 +20,7 @@ const primordials = globalThis.__bootstrap.primordials;
const { const {
ArrayBuffer, ArrayBuffer,
ArrayBufferPrototype, ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
ArrayBufferIsView, ArrayBufferIsView,
ArrayPrototypeMap, ArrayPrototypeMap,
ArrayPrototypePush, ArrayPrototypePush,
@ -67,6 +68,7 @@ const {
TypedArrayPrototypeGetByteOffset, TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetSymbolToStringTag, TypedArrayPrototypeGetSymbolToStringTag,
TypedArrayPrototypeSet, TypedArrayPrototypeSet,
TypedArrayPrototypeSlice,
Uint8Array, Uint8Array,
Uint16Array, Uint16Array,
Uint32Array, Uint32Array,
@ -208,7 +210,12 @@ function uponPromise(promise, onFulfilled, onRejected) {
* @returns {boolean} * @returns {boolean}
*/ */
function isDetachedBuffer(O) { function isDetachedBuffer(O) {
return O.byteLength === 0 && ops.op_arraybuffer_was_detached(O); // deno-lint-ignore prefer-primordials
if (ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, O)) {
return false;
}
return ArrayBufferPrototypeGetByteLength(O) === 0 &&
ops.op_arraybuffer_was_detached(O);
} }
/** /**
@ -237,6 +244,21 @@ function transferArrayBuffer(O) {
return ops.op_transfer_arraybuffer(O); return ops.op_transfer_arraybuffer(O);
} }
/**
* @param {ArrayBufferLike} O
* @returns {number}
*/
function getArrayBufferByteLength(O) {
// deno-lint-ignore prefer-primordials
if (ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, O)) {
// TODO(petamoriken): use primordials
// deno-lint-ignore prefer-primordials
return O.byteLength;
} else {
return ArrayBufferPrototypeGetByteLength(O);
}
}
/** /**
* @param {ArrayBufferView} O * @param {ArrayBufferView} O
* @returns {Uint8Array} * @returns {Uint8Array}
@ -244,9 +266,25 @@ function transferArrayBuffer(O) {
function cloneAsUint8Array(O) { function cloneAsUint8Array(O) {
assert(typeof O === "object"); assert(typeof O === "object");
assert(ArrayBufferIsView(O)); assert(ArrayBufferIsView(O));
assert(!isDetachedBuffer(O.buffer)); if (TypedArrayPrototypeGetSymbolToStringTag(O) !== undefined) {
const buffer = O.buffer.slice(O.byteOffset, O.byteOffset + O.byteLength); // TypedArray
return new Uint8Array(buffer); return TypedArrayPrototypeSlice(
new Uint8Array(
TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (O)),
TypedArrayPrototypeGetByteOffset(/** @type {Uint8Array} */ (O)),
TypedArrayPrototypeGetByteLength(/** @type {Uint8Array} */ (O)),
),
);
} else {
// DataView
return TypedArrayPrototypeSlice(
new Uint8Array(
DataViewPrototypeGetBuffer(/** @type {DataView} */ (O)),
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (O)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (O)),
),
);
}
} }
const _abortAlgorithm = Symbol("[[abortAlgorithm]]"); const _abortAlgorithm = Symbol("[[abortAlgorithm]]");
@ -695,7 +733,7 @@ function readableStreamForRid(rid, autoClose = true) {
if (controller[_readAll] === true) { if (controller[_readAll] === true) {
// fast path for tee'd streams consuming body // fast path for tee'd streams consuming body
const chunk = await core.readAll(rid); const chunk = await core.readAll(rid);
if (chunk.byteLength > 0) { if (TypedArrayPrototypeGetByteLength(chunk) > 0) {
controller.enqueue(chunk); controller.enqueue(chunk);
} }
controller.close(); controller.close();
@ -870,7 +908,7 @@ async function readableStreamCollectIntoUint8Array(stream) {
} }
ArrayPrototypePush(chunks, chunk); ArrayPrototypePush(chunks, chunk);
totalLength += chunk.byteLength; totalLength += TypedArrayPrototypeGetByteLength(chunk);
} }
const finalBuffer = new Uint8Array(totalLength); const finalBuffer = new Uint8Array(totalLength);
@ -878,7 +916,7 @@ async function readableStreamCollectIntoUint8Array(stream) {
for (let i = 0; i < chunks.length; ++i) { for (let i = 0; i < chunks.length; ++i) {
const chunk = chunks[i]; const chunk = chunks[i];
TypedArrayPrototypeSet(finalBuffer, chunk, offset); TypedArrayPrototypeSet(finalBuffer, chunk, offset);
offset += chunk.byteLength; offset += TypedArrayPrototypeGetByteLength(chunk);
} }
return finalBuffer; return finalBuffer;
} }
@ -1092,7 +1130,25 @@ function readableByteStreamControllerEnqueue(controller, chunk) {
return; return;
} }
const { buffer, byteOffset, byteLength } = 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 {
buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array}} */ (chunk));
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (chunk),
);
byteOffset = TypedArrayPrototypeGetByteOffset(
/** @type {Uint8Array} */ (chunk),
);
}
if (isDetachedBuffer(buffer)) { if (isDetachedBuffer(buffer)) {
throw new TypeError( throw new TypeError(
"chunk's buffer is detached and so cannot be enqueued", "chunk's buffer is detached and so cannot be enqueued",
@ -1101,6 +1157,7 @@ function readableByteStreamControllerEnqueue(controller, chunk) {
const transferredBuffer = transferArrayBuffer(buffer); const transferredBuffer = transferArrayBuffer(buffer);
if (controller[_pendingPullIntos].length !== 0) { if (controller[_pendingPullIntos].length !== 0) {
const firstPendingPullInto = controller[_pendingPullIntos][0]; const firstPendingPullInto = controller[_pendingPullIntos][0];
// deno-lint-ignore prefer-primordials
if (isDetachedBuffer(firstPendingPullInto.buffer)) { if (isDetachedBuffer(firstPendingPullInto.buffer)) {
throw new TypeError( throw new TypeError(
"The BYOB request's buffer has been detached and so cannot be filled with an enqueued chunk", "The BYOB request's buffer has been detached and so cannot be filled with an enqueued chunk",
@ -1108,6 +1165,7 @@ function readableByteStreamControllerEnqueue(controller, chunk) {
} }
readableByteStreamControllerInvalidateBYOBRequest(controller); readableByteStreamControllerInvalidateBYOBRequest(controller);
firstPendingPullInto.buffer = transferArrayBuffer( firstPendingPullInto.buffer = transferArrayBuffer(
// deno-lint-ignore prefer-primordials
firstPendingPullInto.buffer, firstPendingPullInto.buffer,
); );
if (firstPendingPullInto.readerType === "none") { if (firstPendingPullInto.readerType === "none") {
@ -1219,7 +1277,9 @@ function readableByteStreamControllerEnqueueDetachedPullIntoToQueue(
if (pullIntoDescriptor.bytesFilled > 0) { if (pullIntoDescriptor.bytesFilled > 0) {
readableByteStreamControllerEnqueueClonedChunkToQueue( readableByteStreamControllerEnqueueClonedChunkToQueue(
controller, controller,
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.buffer, pullIntoDescriptor.buffer,
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.byteOffset, pullIntoDescriptor.byteOffset,
pullIntoDescriptor.bytesFilled, pullIntoDescriptor.bytesFilled,
); );
@ -1238,8 +1298,11 @@ function readableByteStreamControllerGetBYOBRequest(controller) {
) { ) {
const firstDescriptor = controller[_pendingPullIntos][0]; const firstDescriptor = controller[_pendingPullIntos][0];
const view = new Uint8Array( const view = new Uint8Array(
// deno-lint-ignore prefer-primordials
firstDescriptor.buffer, firstDescriptor.buffer,
// deno-lint-ignore prefer-primordials
firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteOffset + firstDescriptor.bytesFilled,
// deno-lint-ignore prefer-primordials
firstDescriptor.byteLength - firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled,
); );
const byobRequest = webidl.createBranded(ReadableStreamBYOBRequest); const byobRequest = webidl.createBranded(ReadableStreamBYOBRequest);
@ -1753,7 +1816,7 @@ function readableByteStreamControllerPullInto(
/** @type {PullIntoDescriptor} */ /** @type {PullIntoDescriptor} */
const pullIntoDescriptor = { const pullIntoDescriptor = {
buffer, buffer,
bufferByteLength: buffer.byteLength, bufferByteLength: getArrayBufferByteLength(buffer),
byteOffset, byteOffset,
byteLength, byteLength,
bytesFilled: 0, bytesFilled: 0,
@ -1769,7 +1832,9 @@ function readableByteStreamControllerPullInto(
} }
if (stream[_state] === "closed") { if (stream[_state] === "closed") {
const emptyView = new ctor( const emptyView = new ctor(
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.buffer, pullIntoDescriptor.buffer,
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.byteOffset, pullIntoDescriptor.byteOffset,
0, 0,
); );
@ -1828,11 +1893,13 @@ function readableByteStreamControllerRespond(controller, bytesWritten) {
} }
if ( if (
(firstDescriptor.bytesFilled + bytesWritten) > (firstDescriptor.bytesFilled + bytesWritten) >
// deno-lint-ignore prefer-primordials
firstDescriptor.byteLength firstDescriptor.byteLength
) { ) {
throw new RangeError("bytesWritten out of range"); throw new RangeError("bytesWritten out of range");
} }
} }
// deno-lint-ignore prefer-primordials
firstDescriptor.buffer = transferArrayBuffer(firstDescriptor.buffer); firstDescriptor.buffer = transferArrayBuffer(firstDescriptor.buffer);
readableByteStreamControllerRespondInternal(controller, bytesWritten); readableByteStreamControllerRespondInternal(controller, bytesWritten);
} }
@ -1850,6 +1917,7 @@ function readableByteStreamControllerRespondInReadableState(
) { ) {
assert( assert(
(pullIntoDescriptor.bytesFilled + bytesWritten) <= (pullIntoDescriptor.bytesFilled + bytesWritten) <=
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.byteLength, pullIntoDescriptor.byteLength,
); );
readableByteStreamControllerFillHeadPullIntoDescriptor( readableByteStreamControllerFillHeadPullIntoDescriptor(
@ -1874,10 +1942,12 @@ function readableByteStreamControllerRespondInReadableState(
const remainderSize = pullIntoDescriptor.bytesFilled % const remainderSize = pullIntoDescriptor.bytesFilled %
pullIntoDescriptor.elementSize; pullIntoDescriptor.elementSize;
if (remainderSize > 0) { if (remainderSize > 0) {
// deno-lint-ignore prefer-primordials
const end = pullIntoDescriptor.byteOffset + const end = pullIntoDescriptor.byteOffset +
pullIntoDescriptor.bytesFilled; pullIntoDescriptor.bytesFilled;
readableByteStreamControllerEnqueueClonedChunkToQueue( readableByteStreamControllerEnqueueClonedChunkToQueue(
controller, controller,
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.buffer, pullIntoDescriptor.buffer,
end - remainderSize, end - remainderSize,
remainderSize, remainderSize,
@ -1903,6 +1973,7 @@ function readableByteStreamControllerRespondInternal(
bytesWritten, bytesWritten,
) { ) {
const firstDescriptor = controller[_pendingPullIntos][0]; const firstDescriptor = controller[_pendingPullIntos][0];
// deno-lint-ignore prefer-primordials
assert(canTransferArrayBuffer(firstDescriptor.buffer)); assert(canTransferArrayBuffer(firstDescriptor.buffer));
readableByteStreamControllerInvalidateBYOBRequest(controller); readableByteStreamControllerInvalidateBYOBRequest(controller);
const state = controller[_stream][_state]; const state = controller[_stream][_state];
@ -1994,47 +2065,57 @@ function readableByteStreamControllerCommitPullIntoDescriptor(
*/ */
function readableByteStreamControllerRespondWithNewView(controller, view) { function readableByteStreamControllerRespondWithNewView(controller, view) {
assert(controller[_pendingPullIntos].length !== 0); assert(controller[_pendingPullIntos].length !== 0);
assert(!isDetachedBuffer(view.buffer));
let buffer, byteLength, byteOffset;
if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view));
byteLength = DataViewPrototypeGetByteLength(/** @type {DataView} */ (view));
byteOffset = DataViewPrototypeGetByteOffset(/** @type {DataView} */ (view));
} else {
buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array}} */ (view));
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (view),
);
byteOffset = TypedArrayPrototypeGetByteOffset(
/** @type {Uint8Array} */ (view),
);
}
assert(!isDetachedBuffer(buffer));
const firstDescriptor = controller[_pendingPullIntos][0]; const firstDescriptor = controller[_pendingPullIntos][0];
const state = controller[_stream][_state]; const state = controller[_stream][_state];
if (state === "closed") { if (state === "closed") {
if (view.byteLength !== 0) { if (byteLength !== 0) {
throw new TypeError( throw new TypeError(
"The view's length must be 0 when calling respondWithNewView() on a closed stream", "The view's length must be 0 when calling respondWithNewView() on a closed stream",
); );
} }
} else { } else {
assert(state === "readable"); assert(state === "readable");
if (view.byteLength === 0) { if (byteLength === 0) {
throw new TypeError( throw new TypeError(
"The view's length must be greater than 0 when calling respondWithNewView() on a readable stream", "The view's length must be greater than 0 when calling respondWithNewView() on a readable stream",
); );
} }
} }
if ( // deno-lint-ignore prefer-primordials
(firstDescriptor.byteOffset + firstDescriptor.bytesFilled) !== if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== byteOffset) {
view.byteOffset
) {
throw new RangeError( throw new RangeError(
"The region specified by view does not match byobRequest", "The region specified by view does not match byobRequest",
); );
} }
if (firstDescriptor.bufferByteLength !== view.buffer.byteLength) { if (firstDescriptor.bufferByteLength !== getArrayBufferByteLength(buffer)) {
throw new RangeError( throw new RangeError(
"The buffer of view has different capacity than byobRequest", "The buffer of view has different capacity than byobRequest",
); );
} }
if ( // deno-lint-ignore prefer-primordials
(firstDescriptor.bytesFilled + view.byteLength) > if (firstDescriptor.bytesFilled + byteLength > firstDescriptor.byteLength) {
firstDescriptor.byteLength
) {
throw new RangeError( throw new RangeError(
"The region specified by view is larger than byobRequest", "The region specified by view is larger than byobRequest",
); );
} }
const viewByteLength = view.byteLength; firstDescriptor.buffer = transferArrayBuffer(buffer);
firstDescriptor.buffer = transferArrayBuffer(view.buffer); readableByteStreamControllerRespondInternal(controller, byteLength);
readableByteStreamControllerRespondInternal(controller, viewByteLength);
} }
/** /**
@ -2060,6 +2141,7 @@ function readableByteStreamControllerFillPullIntoDescriptorFromQueue(
(pullIntoDescriptor.bytesFilled % elementSize); (pullIntoDescriptor.bytesFilled % elementSize);
const maxBytesToCopy = MathMin( const maxBytesToCopy = MathMin(
controller[_queueTotalSize], controller[_queueTotalSize],
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled,
); );
const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
@ -2076,23 +2158,29 @@ function readableByteStreamControllerFillPullIntoDescriptorFromQueue(
const headOfQueue = queue[0]; const headOfQueue = queue[0];
const bytesToCopy = MathMin( const bytesToCopy = MathMin(
totalBytesToCopyRemaining, totalBytesToCopyRemaining,
// deno-lint-ignore prefer-primordials
headOfQueue.byteLength, headOfQueue.byteLength,
); );
// deno-lint-ignore prefer-primordials
const destStart = pullIntoDescriptor.byteOffset + const destStart = pullIntoDescriptor.byteOffset +
pullIntoDescriptor.bytesFilled; pullIntoDescriptor.bytesFilled;
const destBuffer = new Uint8Array( const destBuffer = new Uint8Array(
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.buffer, pullIntoDescriptor.buffer,
destStart, destStart,
bytesToCopy, bytesToCopy,
); );
const srcBuffer = new Uint8Array( const srcBuffer = new Uint8Array(
// deno-lint-ignore prefer-primordials
headOfQueue.buffer, headOfQueue.buffer,
// deno-lint-ignore prefer-primordials
headOfQueue.byteOffset, headOfQueue.byteOffset,
bytesToCopy, bytesToCopy,
); );
destBuffer.set(srcBuffer); destBuffer.set(srcBuffer);
// deno-lint-ignore prefer-primordials
if (headOfQueue.byteLength === bytesToCopy) { if (headOfQueue.byteLength === bytesToCopy) {
ArrayPrototypeShift(queue); ArrayPrototypeShift(queue);
} else { } else {
@ -2126,11 +2214,15 @@ function readableByteStreamControllerFillReadRequestFromQueue(
) { ) {
assert(controller[_queueTotalSize] > 0); assert(controller[_queueTotalSize] > 0);
const entry = ArrayPrototypeShift(controller[_queue]); const entry = ArrayPrototypeShift(controller[_queue]);
// deno-lint-ignore prefer-primordials
controller[_queueTotalSize] -= entry.byteLength; controller[_queueTotalSize] -= entry.byteLength;
readableByteStreamControllerHandleQueueDrain(controller); readableByteStreamControllerHandleQueueDrain(controller);
const view = new Uint8Array( const view = new Uint8Array(
// deno-lint-ignore prefer-primordials
entry.buffer, entry.buffer,
// deno-lint-ignore prefer-primordials
entry.byteOffset, entry.byteOffset,
// deno-lint-ignore prefer-primordials
entry.byteLength, entry.byteLength,
); );
readRequest.chunkSteps(view); readRequest.chunkSteps(view);
@ -2164,11 +2256,14 @@ function readableByteStreamControllerConvertPullIntoDescriptor(
) { ) {
const bytesFilled = pullIntoDescriptor.bytesFilled; const bytesFilled = pullIntoDescriptor.bytesFilled;
const elementSize = pullIntoDescriptor.elementSize; const elementSize = pullIntoDescriptor.elementSize;
// deno-lint-ignore prefer-primordials
assert(bytesFilled <= pullIntoDescriptor.byteLength); assert(bytesFilled <= pullIntoDescriptor.byteLength);
assert((bytesFilled % elementSize) === 0); assert((bytesFilled % elementSize) === 0);
// deno-lint-ignore prefer-primordials
const buffer = transferArrayBuffer(pullIntoDescriptor.buffer); const buffer = transferArrayBuffer(pullIntoDescriptor.buffer);
return new pullIntoDescriptor.viewConstructor( return new pullIntoDescriptor.viewConstructor(
buffer, buffer,
// deno-lint-ignore prefer-primordials
pullIntoDescriptor.byteOffset, pullIntoDescriptor.byteOffset,
bytesFilled / elementSize, bytesFilled / elementSize,
); );
@ -3029,7 +3124,17 @@ function readableByteStreamTee(stream) {
readableByteStreamControllerClose(otherBranch[_controller]); readableByteStreamControllerClose(otherBranch[_controller]);
} }
if (chunk !== undefined) { if (chunk !== undefined) {
assert(chunk.byteLength === 0); let byteLength;
if (TypedArrayPrototypeGetSymbolToStringTag(chunk) === undefined) {
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
} else {
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (chunk),
);
}
assert(byteLength === 0);
if (!byobCanceled) { if (!byobCanceled) {
readableByteStreamControllerRespondWithNewView( readableByteStreamControllerRespondWithNewView(
byobBranch[_controller], byobBranch[_controller],
@ -4644,6 +4749,7 @@ function initializeByteLengthSizeFunction(globalObject) {
if (WeakMapPrototypeHas(byteSizeFunctionWeakMap, globalObject)) { if (WeakMapPrototypeHas(byteSizeFunctionWeakMap, globalObject)) {
return; return;
} }
// deno-lint-ignore prefer-primordials
const size = (chunk) => chunk.byteLength; const size = (chunk) => chunk.byteLength;
WeakMapPrototypeSet(byteSizeFunctionWeakMap, globalObject, size); WeakMapPrototypeSet(byteSizeFunctionWeakMap, globalObject, size);
} }
@ -5098,17 +5204,29 @@ class ReadableStreamBYOBReader {
return PromiseReject(err); return PromiseReject(err);
} }
if (view.byteLength === 0) { let buffer, byteLength;
if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view));
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (view),
);
} else {
buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (view));
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (view),
);
}
if (byteLength === 0) {
return PromiseReject( return PromiseReject(
new TypeError("view must have non-zero byteLength"), new TypeError("view must have non-zero byteLength"),
); );
} }
if (view.buffer.byteLength === 0) { if (getArrayBufferByteLength(buffer) === 0) {
return PromiseReject( return PromiseReject(
new TypeError("view's buffer must have non-zero byteLength"), new TypeError("view's buffer must have non-zero byteLength"),
); );
} }
if (isDetachedBuffer(view.buffer)) { if (isDetachedBuffer(buffer)) {
return PromiseReject( return PromiseReject(
new TypeError("view's buffer has been detached"), new TypeError("view's buffer has been detached"),
); );
@ -5213,13 +5331,22 @@ class ReadableStreamBYOBRequest {
if (this[_controller] === undefined) { if (this[_controller] === undefined) {
throw new TypeError("This BYOB request has been invalidated"); throw new TypeError("This BYOB request has been invalidated");
} }
if (isDetachedBuffer(this[_view].buffer)) {
let buffer, byteLength;
if (TypedArrayPrototypeGetSymbolToStringTag(this[_view]) === undefined) {
buffer = DataViewPrototypeGetBuffer(this[_view]);
byteLength = DataViewPrototypeGetByteLength(this[_view]);
} else {
buffer = TypedArrayPrototypeGetBuffer(this[_view]);
byteLength = TypedArrayPrototypeGetByteLength(this[_view]);
}
if (isDetachedBuffer(buffer)) {
throw new TypeError( throw new TypeError(
"The BYOB request's buffer has been detached and so cannot be used as a response", "The BYOB request's buffer has been detached and so cannot be used as a response",
); );
} }
assert(this[_view].byteLength > 0); assert(byteLength > 0);
assert(this[_view].buffer.byteLength > 0); assert(getArrayBufferByteLength(buffer) > 0);
readableByteStreamControllerRespond(this[_controller], bytesWritten); readableByteStreamControllerRespond(this[_controller], bytesWritten);
} }
@ -5236,7 +5363,14 @@ class ReadableStreamBYOBRequest {
if (this[_controller] === undefined) { if (this[_controller] === undefined) {
throw new TypeError("This BYOB request has been invalidated"); throw new TypeError("This BYOB request has been invalidated");
} }
if (isDetachedBuffer(view.buffer)) {
let buffer;
if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) {
buffer = DataViewPrototypeGetBuffer(view);
} else {
buffer = TypedArrayPrototypeGetBuffer(view);
}
if (isDetachedBuffer(buffer)) {
throw new TypeError( throw new TypeError(
"The given view's buffer has been detached and so cannot be used as a response", "The given view's buffer has been detached and so cannot be used as a response",
); );
@ -5320,13 +5454,25 @@ class ReadableByteStreamController {
prefix, prefix,
context: arg1, context: arg1,
}); });
if (chunk.byteLength === 0) { let buffer, byteLength;
if (TypedArrayPrototypeGetSymbolToStringTag(chunk) === undefined) {
buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk));
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
} else {
buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (chunk));
byteLength = TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (chunk),
);
}
if (byteLength === 0) {
throw webidl.makeException(TypeError, "length must be non-zero", { throw webidl.makeException(TypeError, "length must be non-zero", {
prefix, prefix,
context: arg1, context: arg1,
}); });
} }
if (chunk.buffer.byteLength === 0) { if (getArrayBufferByteLength(buffer) === 0) {
throw webidl.makeException( throw webidl.makeException(
TypeError, TypeError,
"buffer length must be non-zero", "buffer length must be non-zero",

View file

@ -14,6 +14,9 @@ const ops = core.ops;
import * as webidl from "ext:deno_webidl/00_webidl.js"; import * as webidl from "ext:deno_webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials; const primordials = globalThis.__bootstrap.primordials;
const { const {
DataViewPrototypeGetBuffer,
DataViewPrototypeGetByteLength,
DataViewPrototypeGetByteOffset,
PromiseReject, PromiseReject,
PromiseResolve, PromiseResolve,
// TODO(lucacasonato): add SharedArrayBuffer to primordials // TODO(lucacasonato): add SharedArrayBuffer to primordials
@ -21,6 +24,10 @@ const {
StringPrototypeCharCodeAt, StringPrototypeCharCodeAt,
StringPrototypeSlice, StringPrototypeSlice,
TypedArrayPrototypeSubarray, TypedArrayPrototypeSubarray,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetSymbolToStringTag,
Uint8Array, Uint8Array,
ObjectPrototypeIsPrototypeOf, ObjectPrototypeIsPrototypeOf,
ArrayBufferIsView, ArrayBufferIsView,
@ -104,13 +111,27 @@ class TextDecoder {
} }
try { 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));
}
}
// Note from spec: implementations are strongly encouraged to use an implementation strategy that avoids this copy. // 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(). // When doing so they will have to make sure that changes to input do not affect future calls to decode().
if ( if (
ObjectPrototypeIsPrototypeOf( ObjectPrototypeIsPrototypeOf(
// deno-lint-ignore prefer-primordials // deno-lint-ignore prefer-primordials
SharedArrayBuffer.prototype, SharedArrayBuffer.prototype,
input || input.buffer, buffer,
) )
) { ) {
// We clone the data into a non-shared ArrayBuffer so we can pass it // We clone the data into a non-shared ArrayBuffer so we can pass it
@ -118,13 +139,27 @@ class TextDecoder {
// `input` is now a Uint8Array, and calling the TypedArray constructor // `input` is now a Uint8Array, and calling the TypedArray constructor
// with a TypedArray argument copies the data. // with a TypedArray argument copies the data.
if (ArrayBufferIsView(input)) { if (ArrayBufferIsView(input)) {
input = new Uint8Array( if (TypedArrayPrototypeGetSymbolToStringTag(input) !== undefined) {
input.buffer, // TypedArray
input.byteOffset, input = new Uint8Array(
input.byteLength, buffer,
); TypedArrayPrototypeGetByteOffset(
/** @type {Uint8Array} */ (input),
),
TypedArrayPrototypeGetByteLength(
/** @type {Uint8Array} */ (input),
),
);
} else {
// DataView
input = new Uint8Array(
buffer,
DataViewPrototypeGetByteOffset(/** @type {DataView} */ (input)),
DataViewPrototypeGetByteLength(/** @type {DataView} */ (input)),
);
}
} else { } else {
input = new Uint8Array(input); input = new Uint8Array(buffer);
} }
} }

View file

@ -18,9 +18,13 @@ const primordials = globalThis.__bootstrap.primordials;
const { const {
ArrayBufferPrototype, ArrayBufferPrototype,
ArrayBufferPrototypeSlice, ArrayBufferPrototypeSlice,
ArrayBufferPrototypeGetByteLength,
ArrayBufferIsView, ArrayBufferIsView,
ArrayPrototypePush, ArrayPrototypePush,
AsyncGeneratorPrototypeNext, AsyncGeneratorPrototypeNext,
DataViewPrototypeGetBuffer,
DataViewPrototypeGetByteLength,
DataViewPrototypeGetByteOffset,
Date, Date,
DatePrototypeGetTime, DatePrototypeGetTime,
FinalizationRegistry, FinalizationRegistry,
@ -37,6 +41,10 @@ const {
Symbol, Symbol,
SymbolFor, SymbolFor,
TypedArrayPrototypeSet, TypedArrayPrototypeSet,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetSymbolToStringTag,
TypeError, TypeError,
Uint8Array, Uint8Array,
} = primordials; } = primordials;
@ -100,6 +108,7 @@ function convertLineEndingsToNative(s) {
/** @param {(BlobReference | Blob)[]} parts */ /** @param {(BlobReference | Blob)[]} parts */
async function* toIterator(parts) { async function* toIterator(parts) {
for (let i = 0; i < parts.length; ++i) { for (let i = 0; i < parts.length; ++i) {
// deno-lint-ignore prefer-primordials
yield* parts[i].stream(); yield* parts[i].stream();
} }
} }
@ -120,15 +129,31 @@ function processBlobParts(parts, endings) {
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, element)) { if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, element)) {
const chunk = new Uint8Array(ArrayBufferPrototypeSlice(element, 0)); const chunk = new Uint8Array(ArrayBufferPrototypeSlice(element, 0));
ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk)); ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
size += element.byteLength; size += ArrayBufferPrototypeGetByteLength(element);
} else if (ArrayBufferIsView(element)) { } else if (ArrayBufferIsView(element)) {
const chunk = new Uint8Array( if (TypedArrayPrototypeGetSymbolToStringTag(element) !== undefined) {
element.buffer, // TypedArray
element.byteOffset, const chunk = new Uint8Array(
element.byteLength, TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (element)),
); TypedArrayPrototypeGetByteOffset(/** @type {Uint8Array} */ (element)),
size += element.byteLength; TypedArrayPrototypeGetByteLength(/** @type {Uint8Array} */ (element)),
ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk)); );
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 (ObjectPrototypeIsPrototypeOf(BlobPrototype, element)) { } else if (ObjectPrototypeIsPrototypeOf(BlobPrototype, element)) {
ArrayPrototypePush(processedParts, element); ArrayPrototypePush(processedParts, element);
size += element.size; size += element.size;
@ -136,7 +161,7 @@ function processBlobParts(parts, endings) {
const chunk = core.encode( const chunk = core.encode(
endings == "native" ? convertLineEndingsToNative(element) : element, endings == "native" ? convertLineEndingsToNative(element) : element,
); );
size += chunk.byteLength; size += TypedArrayPrototypeGetByteLength(chunk);
ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk)); ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
} else { } else {
throw new TypeError("Unreachable code (invalid element type)"); throw new TypeError("Unreachable code (invalid element type)");
@ -341,7 +366,7 @@ class Blob {
partIterator, partIterator,
); );
if (done) return controller.close(); if (done) return controller.close();
if (value.byteLength > 0) { if (TypedArrayPrototypeGetByteLength(value) > 0) {
return controller.enqueue(value); return controller.enqueue(value);
} }
} }
@ -368,7 +393,7 @@ class Blob {
partIterator, partIterator,
); );
if (done) break; if (done) break;
const byteLength = value.byteLength; const byteLength = TypedArrayPrototypeGetByteLength(value);
if (byteLength > 0) { if (byteLength > 0) {
TypedArrayPrototypeSet(bytes, value, offset); TypedArrayPrototypeSet(bytes, value, offset);
offset += byteLength; offset += byteLength;
@ -383,7 +408,7 @@ class Blob {
async arrayBuffer() { async arrayBuffer() {
webidl.assertBranded(this, BlobPrototype); webidl.assertBranded(this, BlobPrototype);
const buf = await this.#u8Array(this.size); const buf = await this.#u8Array(this.size);
return buf.buffer; return TypedArrayPrototypeGetBuffer(buf);
} }
[SymbolFor("Deno.customInspect")](inspect) { [SymbolFor("Deno.customInspect")](inspect) {
@ -554,7 +579,7 @@ class BlobReference {
*/ */
static fromUint8Array(data) { static fromUint8Array(data) {
const id = ops.op_blob_create_part(data); const id = ops.op_blob_create_part(data);
return new BlobReference(id, data.byteLength); return new BlobReference(id, TypedArrayPrototypeGetByteLength(data));
} }
/** /**

View file

@ -27,14 +27,15 @@ const {
MapPrototypeGet, MapPrototypeGet,
MapPrototypeSet, MapPrototypeSet,
ObjectDefineProperty, ObjectDefineProperty,
ObjectPrototypeIsPrototypeOf,
queueMicrotask, queueMicrotask,
SafeArrayIterator, SafeArrayIterator,
Symbol, Symbol,
TypedArrayPrototypeSet, TypedArrayPrototypeSet,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetSymbolToStringTag,
TypeError, TypeError,
Uint8Array, Uint8Array,
Uint8ArrayPrototype,
} = primordials; } = primordials;
const state = Symbol("[[state]]"); const state = Symbol("[[state]]");
@ -119,7 +120,8 @@ class FileReader extends EventTarget {
// and whose value property is a Uint8Array object, run these steps: // and whose value property is a Uint8Array object, run these steps:
if ( if (
!chunk.done && !chunk.done &&
ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, chunk.value) TypedArrayPrototypeGetSymbolToStringTag(chunk.value) ===
"Uint8Array"
) { ) {
ArrayPrototypePush(chunks, chunk.value); ArrayPrototypePush(chunks, chunk.value);
@ -127,7 +129,7 @@ class FileReader extends EventTarget {
{ {
const size = ArrayPrototypeReduce( const size = ArrayPrototypeReduce(
chunks, chunks,
(p, i) => p + i.byteLength, (p, i) => p + TypedArrayPrototypeGetByteLength(i),
0, 0,
); );
const ev = new ProgressEvent("progress", { const ev = new ProgressEvent("progress", {
@ -151,7 +153,7 @@ class FileReader extends EventTarget {
// 2. Let result be the result of package data given bytes, type, blob's type, and encodingName. // 2. Let result be the result of package data given bytes, type, blob's type, and encodingName.
const size = ArrayPrototypeReduce( const size = ArrayPrototypeReduce(
chunks, chunks,
(p, i) => p + i.byteLength, (p, i) => p + TypedArrayPrototypeGetByteLength(i),
0, 0,
); );
const bytes = new Uint8Array(size); const bytes = new Uint8Array(size);
@ -159,11 +161,11 @@ class FileReader extends EventTarget {
for (let i = 0; i < chunks.length; ++i) { for (let i = 0; i < chunks.length; ++i) {
const chunk = chunks[i]; const chunk = chunks[i];
TypedArrayPrototypeSet(bytes, chunk, offs); TypedArrayPrototypeSet(bytes, chunk, offs);
offs += chunk.byteLength; offs += TypedArrayPrototypeGetByteLength(chunk);
} }
switch (readtype.kind) { switch (readtype.kind) {
case "ArrayBuffer": { case "ArrayBuffer": {
this[result] = bytes.buffer; this[result] = TypedArrayPrototypeGetBuffer(bytes);
break; break;
} }
case "BinaryString": case "BinaryString":

View file

@ -19,6 +19,7 @@ import DOMException from "ext:deno_web/01_dom_exception.js";
const primordials = globalThis.__bootstrap.primordials; const primordials = globalThis.__bootstrap.primordials;
const { const {
ArrayBufferPrototype, ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
ArrayPrototypeFilter, ArrayPrototypeFilter,
ArrayPrototypeIncludes, ArrayPrototypeIncludes,
ArrayPrototypePush, ArrayPrototypePush,
@ -249,7 +250,10 @@ function serializeJsMessageData(data, transferables) {
for (let i = 0, j = 0; i < transferables.length; i++) { for (let i = 0, j = 0; i < transferables.length; i++) {
const ab = transferables[i]; const ab = transferables[i];
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) { if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) {
if (ab.byteLength === 0 && ops.op_arraybuffer_was_detached(ab)) { if (
ArrayBufferPrototypeGetByteLength(ab) === 0 &&
ops.op_arraybuffer_was_detached(ab)
) {
throw new DOMException( throw new DOMException(
`ArrayBuffer at index ${j} is already detached`, `ArrayBuffer at index ${j} is already detached`,
"DataCloneError", "DataCloneError",

View file

@ -7,6 +7,10 @@
const core = globalThis.Deno.core; const core = globalThis.Deno.core;
const ops = core.ops; const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials;
const {
TypedArrayPrototypeGetByteLength,
} = primordials;
import * as webidl from "ext:deno_webidl/00_webidl.js"; import * as webidl from "ext:deno_webidl/00_webidl.js";
import { TransformStream } from "ext:deno_web/06_streams.js"; import { TransformStream } from "ext:deno_web/06_streams.js";
@ -113,7 +117,7 @@ class DecompressionStream {
} }
function maybeEnqueue(controller, output) { function maybeEnqueue(controller, output) {
if (output && output.byteLength > 0) { if (output && TypedArrayPrototypeGetByteLength(output) > 0) {
controller.enqueue(output); controller.enqueue(output);
} }
} }

View file

@ -18,6 +18,7 @@ const {
BigInt, BigInt,
BigIntAsIntN, BigIntAsIntN,
BigIntAsUintN, BigIntAsUintN,
DataViewPrototypeGetBuffer,
Float32Array, Float32Array,
Float64Array, Float64Array,
FunctionPrototypeBind, FunctionPrototypeBind,
@ -76,6 +77,7 @@ const {
Symbol, Symbol,
SymbolIterator, SymbolIterator,
SymbolToStringTag, SymbolToStringTag,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetSymbolToStringTag, TypedArrayPrototypeGetSymbolToStringTag,
TypeError, TypeError,
Uint16Array, Uint16Array,
@ -476,7 +478,7 @@ converters.DataView = (V, opts = {}) => {
throw makeException(TypeError, "is not a DataView", opts); throw makeException(TypeError, "is not a DataView", opts);
} }
if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { if (!opts.allowShared && isSharedArrayBuffer(DataViewPrototypeGetBuffer(V))) {
throw makeException( throw makeException(
TypeError, TypeError,
"is backed by a SharedArrayBuffer, which is not allowed", "is backed by a SharedArrayBuffer, which is not allowed",
@ -512,7 +514,10 @@ ArrayPrototypeForEach(
opts, opts,
); );
} }
if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { if (
!opts.allowShared &&
isSharedArrayBuffer(TypedArrayPrototypeGetBuffer(V))
) {
throw makeException( throw makeException(
TypeError, TypeError,
"is a view on a SharedArrayBuffer, which is not allowed", "is a view on a SharedArrayBuffer, which is not allowed",
@ -535,8 +540,13 @@ converters.ArrayBufferView = (V, opts = {}) => {
opts, opts,
); );
} }
let buffer;
if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { if (TypedArrayPrototypeGetSymbolToStringTag(V) !== undefined) {
buffer = TypedArrayPrototypeGetBuffer(V);
} else {
buffer = DataViewPrototypeGetBuffer(V);
}
if (!opts.allowShared && isSharedArrayBuffer(buffer)) {
throw makeException( throw makeException(
TypeError, TypeError,
"is a view on a SharedArrayBuffer, which is not allowed", "is a view on a SharedArrayBuffer, which is not allowed",
@ -549,7 +559,13 @@ converters.ArrayBufferView = (V, opts = {}) => {
converters.BufferSource = (V, opts = {}) => { converters.BufferSource = (V, opts = {}) => {
if (ArrayBufferIsView(V)) { if (ArrayBufferIsView(V)) {
if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) { let buffer;
if (TypedArrayPrototypeGetSymbolToStringTag(V) !== undefined) {
buffer = TypedArrayPrototypeGetBuffer(V);
} else {
buffer = DataViewPrototypeGetBuffer(V);
}
if (!opts.allowShared && isSharedArrayBuffer(buffer)) {
throw makeException( throw makeException(
TypeError, TypeError,
"is a view on a SharedArrayBuffer, which is not allowed", "is a view on a SharedArrayBuffer, which is not allowed",

View file

@ -22,16 +22,19 @@ const primordials = globalThis.__bootstrap.primordials;
const { const {
ArrayBufferPrototype, ArrayBufferPrototype,
ArrayBufferIsView, ArrayBufferIsView,
ArrayBufferPrototypeGetByteLength,
ArrayPrototypeJoin, ArrayPrototypeJoin,
ArrayPrototypeMap, ArrayPrototypeMap,
ArrayPrototypeSome, ArrayPrototypeSome,
DataView, DataView,
DataViewPrototypeGetByteLength,
ErrorPrototypeToString, ErrorPrototypeToString,
ObjectDefineProperties, ObjectDefineProperties,
ObjectPrototypeIsPrototypeOf, ObjectPrototypeIsPrototypeOf,
PromisePrototypeThen, PromisePrototypeThen,
RegExpPrototypeTest, RegExpPrototypeTest,
Set, Set,
SetPrototypeGetSize,
// TODO(lucacasonato): add SharedArrayBuffer to primordials // TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype // SharedArrayBufferPrototype
String, String,
@ -41,6 +44,8 @@ const {
SymbolIterator, SymbolIterator,
PromisePrototypeCatch, PromisePrototypeCatch,
SymbolFor, SymbolFor,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetSymbolToStringTag,
} = primordials; } = primordials;
webidl.converters["sequence<DOMString> or DOMString"] = (V, opts) => { webidl.converters["sequence<DOMString> or DOMString"] = (V, opts) => {
@ -211,9 +216,11 @@ class WebSocket extends EventTarget {
if ( if (
protocols.length !== protocols.length !==
new Set( SetPrototypeGetSize(
ArrayPrototypeMap(protocols, (p) => StringPrototypeToLowerCase(p)), new Set(
).size ArrayPrototypeMap(protocols, (p) => StringPrototypeToLowerCase(p)),
),
)
) { ) {
throw new DOMException( throw new DOMException(
"Can't supply multiple times the same protocol.", "Can't supply multiple times the same protocol.",
@ -298,12 +305,16 @@ class WebSocket extends EventTarget {
throw new DOMException("readyState not OPEN", "InvalidStateError"); throw new DOMException("readyState not OPEN", "InvalidStateError");
} }
const sendTypedArray = (ta) => { /**
this[_bufferedAmount] += ta.byteLength; * @param {ArrayBufferView} view
* @param {number} byteLength
*/
const sendTypedArray = (view, byteLength) => {
this[_bufferedAmount] += byteLength;
PromisePrototypeThen( PromisePrototypeThen(
core.opAsync2("op_ws_send_binary", this[_rid], ta), core.opAsync2("op_ws_send_binary", this[_rid], view),
() => { () => {
this[_bufferedAmount] -= ta.byteLength; this[_bufferedAmount] -= byteLength;
}, },
); );
}; };
@ -311,20 +322,33 @@ class WebSocket extends EventTarget {
if (ObjectPrototypeIsPrototypeOf(BlobPrototype, data)) { if (ObjectPrototypeIsPrototypeOf(BlobPrototype, data)) {
PromisePrototypeThen( PromisePrototypeThen(
data.slice().arrayBuffer(), data.slice().arrayBuffer(),
(ab) => sendTypedArray(new DataView(ab)), (ab) =>
sendTypedArray(
new DataView(ab),
ArrayBufferPrototypeGetByteLength(ab),
),
); );
} else if (ArrayBufferIsView(data)) { } else if (ArrayBufferIsView(data)) {
sendTypedArray(data); if (TypedArrayPrototypeGetSymbolToStringTag(data) === undefined) {
// DataView
sendTypedArray(data, DataViewPrototypeGetByteLength(data));
} else {
// TypedArray
sendTypedArray(data, TypedArrayPrototypeGetByteLength(data));
}
} else if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, data)) { } else if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, data)) {
sendTypedArray(new DataView(data)); sendTypedArray(
new DataView(data),
ArrayBufferPrototypeGetByteLength(data),
);
} else { } else {
const string = String(data); const string = String(data);
const d = core.encode(string); const d = core.encode(string);
this[_bufferedAmount] += d.byteLength; this[_bufferedAmount] += TypedArrayPrototypeGetByteLength(d);
PromisePrototypeThen( PromisePrototypeThen(
core.opAsync2("op_ws_send_text", this[_rid], string), core.opAsync2("op_ws_send_text", this[_rid], string),
() => { () => {
this[_bufferedAmount] -= d.byteLength; this[_bufferedAmount] -= TypedArrayPrototypeGetByteLength(d);
}, },
); );
} }
@ -361,7 +385,10 @@ class WebSocket extends EventTarget {
} }
} }
if (reason !== undefined && core.encode(reason).byteLength > 123) { if (
reason !== undefined &&
TypedArrayPrototypeGetByteLength(core.encode(reason)) > 123
) {
throw new DOMException( throw new DOMException(
"The close reason may not be longer than 123 bytes.", "The close reason may not be longer than 123 bytes.",
"SyntaxError", "SyntaxError",

View file

@ -22,10 +22,12 @@ const {
PromisePrototypeCatch, PromisePrototypeCatch,
PromisePrototypeThen, PromisePrototypeThen,
Set, Set,
SetPrototypeGetSize,
StringPrototypeEndsWith, StringPrototypeEndsWith,
StringPrototypeToLowerCase, StringPrototypeToLowerCase,
Symbol, Symbol,
SymbolFor, SymbolFor,
TypedArrayPrototypeGetByteLength,
TypeError, TypeError,
Uint8ArrayPrototype, Uint8ArrayPrototype,
} = primordials; } = primordials;
@ -115,12 +117,14 @@ class WebSocketStream {
if ( if (
options.protocols.length !== options.protocols.length !==
new Set( SetPrototypeGetSize(
ArrayPrototypeMap( new Set(
options.protocols, ArrayPrototypeMap(
(p) => StringPrototypeToLowerCase(p), options.protocols,
(p) => StringPrototypeToLowerCase(p),
),
), ),
).size )
) { ) {
throw new DOMException( throw new DOMException(
"Can't supply multiple times the same protocol.", "Can't supply multiple times the same protocol.",
@ -394,7 +398,8 @@ class WebSocketStream {
const encoder = new TextEncoder(); const encoder = new TextEncoder();
if ( if (
closeInfo.reason && encoder.encode(closeInfo.reason).byteLength > 123 closeInfo.reason &&
TypedArrayPrototypeGetByteLength(encoder.encode(closeInfo.reason)) > 123
) { ) {
throw new DOMException( throw new DOMException(
"The close reason may not be longer than 123 bytes.", "The close reason may not be longer than 123 bytes.",

View file

@ -7,9 +7,12 @@
import { assert } from "ext:deno_web/00_infra.js"; import { assert } from "ext:deno_web/00_infra.js";
const primordials = globalThis.__bootstrap.primordials; const primordials = globalThis.__bootstrap.primordials;
const { const {
ArrayBufferPrototypeGetByteLength,
TypedArrayPrototypeSubarray, TypedArrayPrototypeSubarray,
TypedArrayPrototypeSlice, TypedArrayPrototypeSlice,
TypedArrayPrototypeSet, TypedArrayPrototypeSet,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
MathFloor, MathFloor,
MathMin, MathMin,
PromiseResolve, PromiseResolve,
@ -28,12 +31,12 @@ const MAX_SIZE = 2 ** 32 - 2;
// from `src`. // from `src`.
// Returns the number of bytes copied. // Returns the number of bytes copied.
function copyBytes(src, dst, off = 0) { function copyBytes(src, dst, off = 0) {
const r = dst.byteLength - off; const r = TypedArrayPrototypeGetByteLength(dst) - off;
if (src.byteLength > r) { if (TypedArrayPrototypeGetByteLength(src) > r) {
src = TypedArrayPrototypeSubarray(src, 0, r); src = TypedArrayPrototypeSubarray(src, 0, r);
} }
TypedArrayPrototypeSet(dst, src, off); TypedArrayPrototypeSet(dst, src, off);
return src.byteLength; return TypedArrayPrototypeGetByteLength(src);
} }
class Buffer { class Buffer {
@ -57,15 +60,17 @@ class Buffer {
} }
empty() { empty() {
return this.#buf.byteLength <= this.#off; return TypedArrayPrototypeGetByteLength(this.#buf) <= this.#off;
} }
get length() { get length() {
return this.#buf.byteLength - this.#off; return TypedArrayPrototypeGetByteLength(this.#buf) - this.#off;
} }
get capacity() { get capacity() {
return this.#buf.buffer.byteLength; return ArrayBufferPrototypeGetByteLength(
TypedArrayPrototypeGetBuffer(this.#buf),
);
} }
truncate(n) { truncate(n) {
@ -85,7 +90,7 @@ class Buffer {
} }
#tryGrowByReslice(n) { #tryGrowByReslice(n) {
const l = this.#buf.byteLength; const l = TypedArrayPrototypeGetByteLength(this.#buf);
if (n <= this.capacity - l) { if (n <= this.capacity - l) {
this.#reslice(l + n); this.#reslice(l + n);
return l; return l;
@ -94,15 +99,16 @@ class Buffer {
} }
#reslice(len) { #reslice(len) {
assert(len <= this.#buf.buffer.byteLength); const ab = TypedArrayPrototypeGetBuffer(this.#buf);
this.#buf = new Uint8Array(this.#buf.buffer, 0, len); assert(len <= ArrayBufferPrototypeGetByteLength(ab));
this.#buf = new Uint8Array(ab, 0, len);
} }
readSync(p) { readSync(p) {
if (this.empty()) { if (this.empty()) {
// Buffer is empty, reset to recover space. // Buffer is empty, reset to recover space.
this.reset(); this.reset();
if (p.byteLength === 0) { if (TypedArrayPrototypeGetByteLength(p) === 0) {
// this edge case is tested in 'bufferReadEmptyAtEOF' test // this edge case is tested in 'bufferReadEmptyAtEOF' test
return 0; return 0;
} }
@ -122,7 +128,7 @@ class Buffer {
} }
writeSync(p) { writeSync(p) {
const m = this.#grow(p.byteLength); const m = this.#grow(TypedArrayPrototypeGetByteLength(p));
return copyBytes(p, this.#buf, m); return copyBytes(p, this.#buf, m);
} }
@ -180,7 +186,7 @@ class Buffer {
// otherwise read directly into the internal buffer // otherwise read directly into the internal buffer
const buf = shouldGrow const buf = shouldGrow
? tmp ? tmp
: new Uint8Array(this.#buf.buffer, this.length); : new Uint8Array(TypedArrayPrototypeGetBuffer(this.#buf), this.length);
const nread = await r.read(buf); const nread = await r.read(buf);
if (nread === null) { if (nread === null) {
@ -205,7 +211,7 @@ class Buffer {
// otherwise read directly into the internal buffer // otherwise read directly into the internal buffer
const buf = shouldGrow const buf = shouldGrow
? tmp ? tmp
: new Uint8Array(this.#buf.buffer, this.length); : new Uint8Array(TypedArrayPrototypeGetBuffer(this.#buf), this.length);
const nread = r.readSync(buf); const nread = r.readSync(buf);
if (nread === null) { if (nread === null) {

View file

@ -411,25 +411,25 @@ function bootstrapMainRuntime(runtimeOptions) {
throw new Error("Worker runtime already bootstrapped"); throw new Error("Worker runtime already bootstrapped");
} }
const [ const {
args, 0: args,
cpuCount, 1: cpuCount,
debugFlag, 2: debugFlag,
denoVersion, 3: denoVersion,
locale, 4: locale,
location_, 5: location_,
noColor, 6: noColor,
isTty, 7: isTty,
tsVersion, 8: tsVersion,
unstableFlag, 9: unstableFlag,
pid, 10: pid,
ppid, 11: ppid,
target, 12: target,
v8Version, 13: v8Version,
userAgent, 14: userAgent,
inspectFlag, 15: inspectFlag,
_, // 16: enableTestingFeaturesFlag
] = runtimeOptions; } = runtimeOptions;
performance.setTimeOrigin(DateNow()); performance.setTimeOrigin(DateNow());
globalThis_ = globalThis; globalThis_ = globalThis;
@ -519,25 +519,25 @@ function bootstrapWorkerRuntime(
throw new Error("Worker runtime already bootstrapped"); throw new Error("Worker runtime already bootstrapped");
} }
const [ const {
args, 0: args,
cpuCount, 1: cpuCount,
debugFlag, 2: debugFlag,
denoVersion, 3: denoVersion,
locale, 4: locale,
location_, 5: location_,
noColor, 6: noColor,
isTty, 7: isTty,
tsVersion, 8: tsVersion,
unstableFlag, 9: unstableFlag,
pid, 10: pid,
_ppid, // 11: ppid,
target, 12: target,
v8Version, 13: v8Version,
_userAgent, // 14: userAgent,
_inspectFlag, // 15: inspectFlag,
enableTestingFeaturesFlag, 16: enableTestingFeaturesFlag,
] = runtimeOptions; } = runtimeOptions;
performance.setTimeOrigin(DateNow()); performance.setTimeOrigin(DateNow());
globalThis_ = globalThis; globalThis_ = globalThis;

View file

@ -25,8 +25,7 @@ if (Deno.args.includes("--rs")) {
if (!didLint) { if (!didLint) {
await Promise.all([ await Promise.all([
dlint(), dlint(),
// todo(dsherret): re-enable dlintPreferPrimordials(),
// dlintPreferPrimordials(),
checkCopyright(), checkCopyright(),
clippy(), clippy(),
]); ]);
@ -96,6 +95,10 @@ async function dlintPreferPrimordials() {
const sourceFiles = await getSources(ROOT_PATH, [ const sourceFiles = await getSources(ROOT_PATH, [
"runtime/**/*.js", "runtime/**/*.js",
"ext/**/*.js", "ext/**/*.js",
// TODO(petamoriken): enable for node polyfills
// "ext/node/polyfills/*.mjs",
// "ext/node/polyfills/*.ts",
// ":!:ext/node/polyfills/*.d.ts",
"core/*.js", "core/*.js",
":!:core/*_test.js", ":!:core/*_test.js",
":!:core/examples/**", ":!:core/examples/**",