blob: 6c9aa952a57b69dd697d9049cbb207334b25462a [file] [edit]
// Regression test for a bug where tryConcatOneArgFast fell through to the JSArray
// uncheckedDowncast branch for a non-array object argument, dereferencing a bogus butterfly
// pointer and crashing.
//
// The fix: the non-array-object branch must return the concatAppendOne result directly
// (RELEASE_AND_RETURN), not merely check the exception scope and fall through.
function assert(cond, msg) {
if (!cond)
throw new Error("Bad: " + (msg || ""));
}
noInline(assert);
function objConcat(a, b) { return a.concat(b); }
noInline(objConcat);
function runAll() {
// Plain object (not an array) — hits the non-array non-spreadable branch.
{
const plainObj = { foo: "bar" };
const r = objConcat([1, 2], plainObj);
assert(r.length === 3, "plain-object length " + r.length);
assert(r[0] === 1);
assert(r[1] === 2);
assert(r[2] === plainObj, "plain-object should be single-element-appended");
}
// Object with array-like shape but no Symbol.isConcatSpreadable — also non-spreadable.
{
const arrLike = { 0: "a", 1: "b", length: 2 };
const r = objConcat([10, 20], arrLike);
assert(r.length === 3);
assert(r[2] === arrLike, "array-like without spreadable must be appended, not spread");
}
// Object with prototype set to Array.prototype but not a JSArray — still non-spreadable
// per `arrayMissingIsConcatSpreadable` semantics (its prototype is array-prototype but
// isJSArray returns false, so we treat it as a non-array object).
{
const pseudoArr = Object.create(Array.prototype);
pseudoArr[0] = "x"; pseudoArr[1] = "y"; pseudoArr.length = 2;
const r = objConcat([1], pseudoArr);
assert(r.length === 2);
assert(r[1] === pseudoArr);
}
// Null and undefined arguments — primitives, not objects.
{
const r1 = objConcat([1, 2], null);
assert(r1.length === 3 && r1[2] === null);
const r2 = objConcat([1, 2], undefined);
assert(r2.length === 3 && r2[2] === undefined);
}
}
// Run at LLInt tier first (where the crash originally reproduced), then warm up through
// Baseline/DFG/FTL to exercise every JIT path.
for (let i = 0; i < testLoopCount; i++)
runAll();