mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
Throw for DataView targets of borrowed typed array set calls
This commit is contained in:
@@ -927,8 +927,9 @@ function bytesSetIntrinsic(
|
||||
|
||||
/** `Uint8Array.prototype.set.call(target, src, offset?)`, through any typed
|
||||
* array constructor's prototype (they share %TypedArray%.prototype.set). A
|
||||
* typed-array target lowers like `target.set(src, offset)`. Any other
|
||||
* target is checked at run time: a typed array calls its `set`, and
|
||||
* target the checker types as a typed array or Buffer lowers like
|
||||
* `target.set(src, offset)`. Any other target, a DataView included, is
|
||||
* checked at run time: a typed array calls its `set`, and
|
||||
* anything else throws Node's TypeError "this is not a typed array.",
|
||||
* after every argument is evaluated. */
|
||||
export function lowerBytesPrototypeSetCall(
|
||||
@@ -961,7 +962,16 @@ export function lowerBytesPrototypeSetCall(
|
||||
if (argNodes.length < 2 || argNodes.length > 3 || argNodes.some(ts.isSpreadElement)) return null;
|
||||
const loc = locOf(call);
|
||||
const target = lowerer.lowerExpr(argNodes[0]!);
|
||||
if (target.type.kind === "bytes")
|
||||
// A DataView lowers to the same bytes type, so the checker type decides:
|
||||
// only a typed array (or a Buffer) takes the method's path.
|
||||
const targetSymbol = lowerer.typeOf(argNodes[0]!).getSymbol();
|
||||
if (
|
||||
target.type.kind === "bytes" &&
|
||||
targetSymbol !== undefined &&
|
||||
lowerer.isStdlibSymbol(targetSymbol) &&
|
||||
(own(BYTES_CTORS, ts.symbolName(targetSymbol)) !== undefined ||
|
||||
ts.symbolName(targetSymbol) === "Buffer")
|
||||
)
|
||||
return bytesSetIntrinsic(lowerer, target, argNodes.slice(1), loc);
|
||||
const slot = (value: IrExpr): { decl: IrStmt; read: IrExpr } => {
|
||||
const local = lowerer.declareHiddenLocal("%setArg", DYN);
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/8100-typed-array-prototype-set-data-view.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// A borrowed TypedArray.prototype.set over a DataView target throws Node's
|
||||
// TypeError after evaluating its arguments, and leaves the view unchanged.
|
||||
const view = new DataView(new ArrayBuffer(4));
|
||||
const order: string[] = [];
|
||||
function arg<T>(label: string, value: T): T {
|
||||
order.push(label);
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
Uint8Array.prototype.set.call(arg("target", view), arg("source", [1, 2]), arg("offset", 1));
|
||||
console.log("set");
|
||||
} catch (e) {
|
||||
console.log(e instanceof TypeError, (e as Error).message, order.join(","));
|
||||
}
|
||||
console.log(view.getUint8(1), view.getUint8(2));
|
||||
|
||||
function fill(target: DataView | Uint8Array, bytes: number[]): string {
|
||||
try {
|
||||
Uint8Array.prototype.set.call(target, bytes);
|
||||
return "set";
|
||||
} catch (e) {
|
||||
return (e as Error).message;
|
||||
}
|
||||
}
|
||||
console.log(fill(view, [7]), view.getUint8(0));
|
||||
const bytes = new Uint8Array(2);
|
||||
console.log(fill(bytes, [7]), bytes[0]);
|
||||
const buffer = Buffer.alloc(3);
|
||||
Uint8Array.prototype.set.call(buffer, [4, 5], 1);
|
||||
console.log(buffer.toString("hex"));
|
||||
Reference in New Issue
Block a user