mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
Answer in on typed arrays held as any (#1473)
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/6407-dyn-bytes-in.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/6408-dyn-bytes-in-js.js"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -2122,6 +2122,70 @@ static bool scr_dyn_array_proto_name(const ScrStr *key) {
|
||||
return scr_dyn_name_in(key, names, sizeof names / sizeof names[0]);
|
||||
}
|
||||
|
||||
/* Own string keys of %TypedArray%.prototype, plus BYTES_PER_ELEMENT from
|
||||
* each typed array's own prototype. */
|
||||
static bool scr_dyn_typed_array_proto_name(const ScrStr *key) {
|
||||
static const char *const names[] = {
|
||||
"constructor", "buffer", "byteLength", "byteOffset", "length", "entries", "keys", "values",
|
||||
"at", "copyWithin", "every", "fill", "filter", "find", "findIndex", "findLast",
|
||||
"findLastIndex", "forEach", "includes", "indexOf", "join", "lastIndexOf", "map", "reverse",
|
||||
"reduce", "reduceRight", "set", "slice", "some", "sort", "subarray", "toReversed", "toSorted",
|
||||
"with", "toLocaleString", "toString", "BYTES_PER_ELEMENT"
|
||||
};
|
||||
return scr_dyn_name_in(key, names, sizeof names / sizeof names[0]);
|
||||
}
|
||||
|
||||
/* Own string keys of Buffer.prototype that %TypedArray%.prototype lacks. */
|
||||
static bool scr_dyn_buffer_proto_name(const ScrStr *key) {
|
||||
static const char *const names[] = {
|
||||
"readBigUInt64LE", "readBigUInt64BE", "readBigUint64LE", "readBigUint64BE", "readBigInt64LE",
|
||||
"readBigInt64BE", "writeBigUInt64LE", "writeBigUInt64BE", "writeBigUint64LE",
|
||||
"writeBigUint64BE", "writeBigInt64LE", "writeBigInt64BE", "readUIntLE", "readUInt32LE",
|
||||
"readUInt16LE", "readUInt8", "readUIntBE", "readUInt32BE", "readUInt16BE", "readUintLE",
|
||||
"readUint32LE", "readUint16LE", "readUint8", "readUintBE", "readUint32BE", "readUint16BE",
|
||||
"readIntLE", "readInt32LE", "readInt16LE", "readInt8", "readIntBE", "readInt32BE",
|
||||
"readInt16BE", "writeUIntLE", "writeUInt32LE", "writeUInt16LE", "writeUInt8", "writeUIntBE",
|
||||
"writeUInt32BE", "writeUInt16BE", "writeUintLE", "writeUint32LE", "writeUint16LE",
|
||||
"writeUint8", "writeUintBE", "writeUint32BE", "writeUint16BE", "writeIntLE", "writeInt32LE",
|
||||
"writeInt16LE", "writeInt8", "writeIntBE", "writeInt32BE", "writeInt16BE", "readFloatLE",
|
||||
"readFloatBE", "readDoubleLE", "readDoubleBE", "writeFloatLE", "writeFloatBE", "writeDoubleLE",
|
||||
"writeDoubleBE", "asciiSlice", "base64Slice", "base64urlSlice", "latin1Slice", "hexSlice",
|
||||
"ucs2Slice", "utf8Slice", "asciiWrite", "base64Write", "base64urlWrite", "latin1Write",
|
||||
"hexWrite", "ucs2Write", "utf8Write", "parent", "offset", "copy", "equals", "inspect",
|
||||
"compare", "write", "toJSON", "swap16", "swap32", "swap64"
|
||||
};
|
||||
return scr_dyn_name_in(key, names, sizeof names / sizeof names[0]);
|
||||
}
|
||||
|
||||
/* Own string keys of DataView.prototype. */
|
||||
static bool scr_dyn_data_view_proto_name(const ScrStr *key) {
|
||||
static const char *const names[] = {
|
||||
"constructor", "buffer", "byteLength", "byteOffset", "getInt8", "setInt8", "getUint8",
|
||||
"setUint8", "getInt16", "setInt16", "getUint16", "setUint16", "getInt32", "setInt32",
|
||||
"getUint32", "setUint32", "getFloat32", "setFloat32", "getFloat64", "setFloat64",
|
||||
"getBigInt64", "setBigInt64", "getBigUint64", "setBigUint64", "getFloat16", "setFloat16"
|
||||
};
|
||||
return scr_dyn_name_in(key, names, sizeof names / sizeof names[0]);
|
||||
}
|
||||
|
||||
/* `in` on a typed array, Buffer or DataView. On a typed array, a canonical
|
||||
* numeric key (one that ToString(ToNumber(key)) reproduces, or "-0")
|
||||
* answers by bounds alone: an integral index, not -0, below the length.
|
||||
* Other keys name members of %TypedArray%.prototype, Buffer.prototype for a
|
||||
* Buffer, or Object.prototype. A DataView has no indexed elements: its keys
|
||||
* name members of DataView.prototype or Object.prototype. */
|
||||
static bool scr_dyn_bytes_in(const ScrDyn *v, const ScrStr *key) {
|
||||
if (v->v.bytes->is_data_view) return scr_dyn_data_view_proto_name(key) || scr_dyn_object_proto_name(key);
|
||||
if (key->len == 2 && memcmp(key->data, "-0", 2) == 0) return false;
|
||||
double index = scr_string_to_number(key);
|
||||
ScrStr *canonical = scr_f64_to_scrstr(index);
|
||||
bool numeric = canonical->len == key->len && memcmp(canonical->data, key->data, key->len) == 0;
|
||||
scr_str_release(canonical);
|
||||
if (numeric) return index >= 0 && index == floor(index) && index < (double)v->v.bytes->len;
|
||||
return scr_dyn_typed_array_proto_name(key) || (v->buffer && scr_dyn_buffer_proto_name(key)) ||
|
||||
scr_dyn_object_proto_name(key);
|
||||
}
|
||||
|
||||
static bool scr_dyn_object_proto_key(const ScrDyn *target, const ScrStr *key) {
|
||||
return !target->null_proto && scr_dyn_object_proto_name(key);
|
||||
}
|
||||
@@ -7911,6 +7975,7 @@ bool scr_dyn_in(const ScrDyn *v, const ScrStr *key) {
|
||||
return out;
|
||||
}
|
||||
if (v->kind == SCR_DYN_PROXY) return scr_dyn_proxy_has(v, key);
|
||||
if (v->kind == SCR_DYN_BYTES) return scr_dyn_bytes_in(v, key);
|
||||
if (scr_dyn_has_key(v, key)) return true;
|
||||
if (scr_exc_pending()) return false;
|
||||
if (v->kind == SCR_DYN_OBJ) return scr_dyn_builtin_inherited(v, key);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// `in` on typed arrays, Buffers and DataViews held as `any` matches Node's.
|
||||
// On a typed array a canonical numeric key answers by bounds (integral,
|
||||
// not -0, below the length), and "1.5", "-0", "NaN", "Infinity", "01" and
|
||||
// "1e0" answer false. Other keys name members of %TypedArray%.prototype,
|
||||
// Buffer.prototype for a Buffer, each constructor's BYTES_PER_ELEMENT, or
|
||||
// Object.prototype. A DataView has no indexed elements and answers its own
|
||||
// prototype's members.
|
||||
|
||||
const bytes: any = new Uint8Array([1, 2, 255]);
|
||||
const floats: any = new Float64Array(2);
|
||||
const buf: any = Buffer.from("ab");
|
||||
for (const [label, v] of [["u8", bytes], ["f64", floats], ["buffer", buf]] as [string, any][]) {
|
||||
const keys: any[] = [0, 1, 2, 3, -1, "0", "1.5", "-0", "length", "byteLength", "buffer", "map", "set", "toString", "nope", "write"];
|
||||
console.log(label, keys.map((k) => `${String(k)}:${k in v}`).join(" "));
|
||||
}
|
||||
const k: any = JSON.parse("1");
|
||||
console.log("computed", k in bytes, "length" in bytes, "map" in bytes);
|
||||
const view: any = new DataView(new ArrayBuffer(4));
|
||||
console.log("dataview", [0, "getInt8", "setUint16", "byteLength", "buffer", "length", "map", "toString"].map((k) => `${String(k)}:${k in view}`).join(" "));
|
||||
const clamped: any = new Uint8ClampedArray(3);
|
||||
|
||||
console.log("clamped", 2 in clamped, 3 in clamped, "BYTES_PER_ELEMENT" in clamped);
|
||||
const sub: any = new Uint8Array([1, 2, 3, 4]).subarray(1, 3);
|
||||
console.log("subarray", 0 in sub, 1 in sub, 2 in sub);
|
||||
console.log("hasOwn", Object.hasOwn(bytes, 0), Object.hasOwn(bytes, 3), Object.hasOwn(bytes, "length"), bytes.hasOwnProperty(1));
|
||||
console.log("symbol", Symbol.iterator in bytes);
|
||||
const empty: any = new Uint8Array(0);
|
||||
console.log("empty", 0 in empty, "Infinity" in bytes, "NaN" in bytes, "1e0" in bytes, "01" in bytes);
|
||||
@@ -0,0 +1,35 @@
|
||||
// In JavaScript sources, `in` on typed arrays, Buffers and DataViews
|
||||
// matches Node's. On a typed array a canonical numeric key answers by
|
||||
// bounds (integral, not -0, below the length), and "1.5", "-0", "NaN",
|
||||
// "Infinity", "01" and "1e0" answer false. Other keys name members of
|
||||
// %TypedArray%.prototype, Buffer.prototype for a Buffer, each
|
||||
// constructor's BYTES_PER_ELEMENT, or Object.prototype. A DataView has no
|
||||
// indexed elements and answers its own prototype's members.
|
||||
|
||||
function dyn(value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const bytes = dyn(new Uint8Array([1, 2, 255]));
|
||||
const floats = dyn(new Float64Array(2));
|
||||
const buf = dyn(Buffer.from("ab"));
|
||||
function row(label, v) {
|
||||
const keys = [0, 1, 2, 3, -1, "0", "1.5", "-0", "length", "byteLength", "buffer", "map", "set", "toString", "nope", "write"];
|
||||
console.log(label, keys.map((k) => `${String(k)}:${k in v}`).join(" "));
|
||||
}
|
||||
row("u8", bytes);
|
||||
row("f64", floats);
|
||||
row("buffer", buf);
|
||||
const k = dyn(JSON.parse("1"));
|
||||
console.log("computed", k in bytes, "length" in bytes, "map" in bytes);
|
||||
const view = dyn(new DataView(new ArrayBuffer(4)));
|
||||
console.log("dataview", [0, "getInt8", "setUint16", "byteLength", "buffer", "length", "map", "toString"].map((k) => `${String(k)}:${k in view}`).join(" "));
|
||||
const clamped = dyn(new Uint8ClampedArray(3));
|
||||
|
||||
console.log("clamped", 2 in clamped, 3 in clamped, "BYTES_PER_ELEMENT" in clamped);
|
||||
const sub = dyn(new Uint8Array([1, 2, 3, 4]).subarray(1, 3));
|
||||
console.log("subarray", 0 in sub, 1 in sub, 2 in sub);
|
||||
console.log("hasOwn", Object.hasOwn(bytes, 0), Object.hasOwn(bytes, 3), Object.hasOwn(bytes, "length"), bytes.hasOwnProperty(1));
|
||||
console.log("symbol", Symbol.iterator in bytes);
|
||||
const empty = dyn(new Uint8Array(0));
|
||||
console.log("empty", 0 in empty, "Infinity" in bytes, "NaN" in bytes, "1e0" in bytes, "01" in bytes);
|
||||
@@ -0,0 +1 @@
|
||||
{ "plain": 3590, "san": 4401 }
|
||||
@@ -0,0 +1 @@
|
||||
{ "plain": 3076, "san": 4009 }
|
||||
Reference in New Issue
Block a user