mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-01 07:33:12 +08:00
Read only value slots in lastIndexOf with an element-typed needle
lastIndexOf with a needle of the element type read every non-hole index as the element type. An undefined or foreign element written through a dynamic view (or a hole that toSorted turned into undefined) has no element-typed payload, so the read aborted with "array index N is undefined". The search now reads an index only when it holds a value, and skips undefined and foreign elements, as Node's strict equality does for a string or number needle.
This commit is contained in:
@@ -1788,17 +1788,27 @@ function arraySearchHelper(
|
||||
},
|
||||
loc,
|
||||
};
|
||||
const visitPresent: IrStmt[] = [
|
||||
{ kind: "varDecl", localId: "value.0", init: value, loc },
|
||||
{
|
||||
kind: "if",
|
||||
cond: match,
|
||||
then: [{ kind: "return", value: method === "includes" ? boolLit(true, loc) : indexRef, loc }],
|
||||
else_: null,
|
||||
loc,
|
||||
},
|
||||
advance,
|
||||
];
|
||||
const found: IrStmt = {
|
||||
kind: "if",
|
||||
cond: directNeedle ? equal : match,
|
||||
then: [{ kind: "return", value: method === "includes" ? boolLit(true, loc) : indexRef, loc }],
|
||||
else_: null,
|
||||
loc,
|
||||
};
|
||||
// A direct needle reads only value slots: an undefined or foreign
|
||||
// element written through a dynamic view has no element-typed payload.
|
||||
const visitPresent: IrStmt[] = directNeedle
|
||||
? [
|
||||
{
|
||||
kind: "if",
|
||||
cond: { kind: "bin", op: "===", left: stateRef, right: numLit(1, loc), type: BOOL, loc },
|
||||
then: [{ kind: "varDecl", localId: "value.0", init: value, loc }, found],
|
||||
else_: null,
|
||||
loc,
|
||||
},
|
||||
advance,
|
||||
]
|
||||
: [{ kind: "varDecl", localId: "value.0", init: value, loc }, found, advance];
|
||||
const skipHole: IrStmt[] =
|
||||
method === "lastIndexOf"
|
||||
? [advance]
|
||||
|
||||
@@ -177,3 +177,26 @@ holderView.push({
|
||||
},
|
||||
});
|
||||
console.log(JSON.stringify(holder), JSON.stringify(holder));
|
||||
|
||||
// toSorted keeps the full length and reads holes as undefined; indexOf,
|
||||
// lastIndexOf and includes skip the undefined and foreign elements.
|
||||
const searched: string[] = ["b", "a"];
|
||||
const searchedView: unknown[] = searched;
|
||||
searchedView[9] = 4;
|
||||
searchedView[5] = undefined;
|
||||
console.log(searched.indexOf("b"), searched.lastIndexOf("b"), searched.lastIndexOf("a", 8));
|
||||
console.log(searched.includes("a"), searched.lastIndexOf("z"));
|
||||
const searchedSorted = searched.toSorted();
|
||||
console.log(searchedSorted.length, searchedSorted.slice(0, 4), searchedSorted.lastIndexOf("b"));
|
||||
console.log(searchedSorted.indexOf("a"), searchedSorted.includes("b"));
|
||||
const counts: number[] = [3, 1];
|
||||
const countsView: unknown[] = counts;
|
||||
countsView[6] = "x";
|
||||
countsView[4] = 2;
|
||||
const countsSorted = counts.toSorted();
|
||||
console.log(countsSorted.length, countsSorted, countsSorted.lastIndexOf(3), counts.lastIndexOf(2));
|
||||
const far: number[] = [5];
|
||||
const farView: unknown[] = far;
|
||||
farView[70000] = "z";
|
||||
const farSorted = far.toSorted();
|
||||
console.log(farSorted.length, farSorted.slice(0, 3), farSorted.slice(69999), farSorted.lastIndexOf(5));
|
||||
|
||||
Reference in New Issue
Block a user