mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-01 07:33:12 +08:00
Host the bare compareArray from the upstream assert.js harness
harness/assert.js defines `compareArray(a, b)` beside `assert`: a plain function that RETURNS a boolean, whose throwing counterpart is `assert.compareArray` (already hosted). The adapter now injects the bare name into every prepared test and implements the upstream comparison: read both `.length`s, so a nullish operand throws the same TypeError, return false on a length mismatch, otherwise compare elements by SameValue. That also admits the compareArray.js include when the only use is a direct call. A value reference or property read stays excluded, because it would need the upstream function object and its `format` expando. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
94e921728c
commit
a4c19ae4b4
@@ -250,14 +250,22 @@ test("built-in error assertions are admitted without permitting constructor alia
|
||||
expect(exclusion(alias, metadata(alias), "strict")).toBe("harness:assert-surface");
|
||||
});
|
||||
|
||||
test("the compareArray include only admits the implemented assertion form", () => {
|
||||
test("the compareArray include admits the assertion and the bare call form only", () => {
|
||||
const accepted = source(
|
||||
"includes: [compareArray.js]",
|
||||
"assert.compareArray([1, NaN], [1, NaN]);",
|
||||
);
|
||||
expect(exclusion(accepted, metadata(accepted), "strict")).toBeUndefined();
|
||||
const globalHelper = source("includes: [compareArray.js]", "compareArray([1], [1]);");
|
||||
expect(exclusion(globalHelper, metadata(globalHelper), "strict")).toBe(
|
||||
expect(exclusion(globalHelper, metadata(globalHelper), "strict")).toBeUndefined();
|
||||
// assert.js supplies compareArray, so a test needs no include to call it.
|
||||
const withoutInclude = source("description: intl", "assert(!compareArray([1], [2]));");
|
||||
expect(exclusion(withoutInclude, metadata(withoutInclude), "strict")).toBeUndefined();
|
||||
const valueReference = source(
|
||||
"includes: [compareArray.js]",
|
||||
"const compare = compareArray; assert(compare([1], [1]));",
|
||||
);
|
||||
expect(exclusion(valueReference, metadata(valueReference), "strict")).toBe(
|
||||
"harness:compareArray-surface",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -189,6 +189,26 @@ assert.notSameValue(1, "1");
|
||||
source: "assert.compareArray([1, 2], [1, 3]);",
|
||||
},
|
||||
{ name: "array signed zero mismatch", status: "fail", source: "assert.compareArray([0], [-0]);" },
|
||||
{
|
||||
name: "bare compareArray returns true for matching contents",
|
||||
status: "pass",
|
||||
source: "assert(compareArray([1, NaN, -0], [1, NaN, -0]));",
|
||||
},
|
||||
{
|
||||
name: "bare compareArray returns false for a length or element mismatch",
|
||||
status: "pass",
|
||||
source: "assert(!compareArray([1], [1, 2])); assert(!compareArray([1, 2], [1, 3]));",
|
||||
},
|
||||
{
|
||||
name: "bare compareArray compares operands without a length as equal",
|
||||
status: "pass",
|
||||
source: "assert(compareArray(1, 2)); assert(compareArray({}, {}));",
|
||||
},
|
||||
{
|
||||
name: "bare compareArray does not throw on a mismatch",
|
||||
status: "fail",
|
||||
source: "assert(compareArray([1], [2]));",
|
||||
},
|
||||
{ name: "assert requires true, not truthiness", status: "fail", source: "assert(1);" },
|
||||
{
|
||||
name: "exact built-in exception",
|
||||
|
||||
@@ -60,6 +60,28 @@ export function assert(value: unknown, message?: unknown): void {
|
||||
if (value !== true) throw new Test262Error(text(message, "Expected true"));
|
||||
}
|
||||
|
||||
function lengthOf(value: unknown): unknown {
|
||||
return (value as { length?: unknown }).length;
|
||||
}
|
||||
|
||||
function elementAt(value: unknown, index: number): unknown {
|
||||
return (value as Record<number, unknown>)[index];
|
||||
}
|
||||
|
||||
/** The bare `compareArray(a, b)` the upstream `harness/assert.js` defines
|
||||
* alongside `assert`. It RETURNS a boolean (the throwing assertion is
|
||||
* `assert.compareArray`), and it has no shape checks of its own: it reads
|
||||
* `.length` off both operands, so a null operand throws TypeError there and
|
||||
* here, and two operands without a length of their own compare equal. */
|
||||
export function compareArray(actual: unknown, expected: unknown): boolean {
|
||||
const length = lengthOf(actual);
|
||||
if (lengthOf(expected) !== length) return false;
|
||||
for (let i = 0; typeof length === "number" && i < length; i++) {
|
||||
if (!same(elementAt(expected, i), elementAt(actual, i))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export namespace assert {
|
||||
export function sameValue(actual: unknown, expected: unknown, message?: unknown): void {
|
||||
if (!same(actual, expected)) throw new Test262Error(text(message, "Expected SameValue"));
|
||||
|
||||
@@ -169,7 +169,11 @@ export function exclusion(source, meta, variant) {
|
||||
// Supported assertion calls; aliases, mutations, and reflection stay out.
|
||||
} else reason = "harness:assert-surface";
|
||||
} else if (meta.includes.includes("compareArray.js") && ts.isIdentifier(node) && node.text === "compareArray" &&
|
||||
!(ts.isCallExpression(node.parent) && node.parent.expression === node) &&
|
||||
!(ts.isPropertyAccessExpression(node.parent) && node.parent.name === node && ts.isIdentifier(node.parent.expression) && node.parent.expression.text === "assert")) {
|
||||
// assert.js defines the bare compareArray; only its direct call form is
|
||||
// hosted (a value reference or property read would need the upstream
|
||||
// function object and its format expando).
|
||||
reason = "harness:compareArray-surface";
|
||||
} else if (ts.isIdentifier(node) && node.text === "Test262Error") {
|
||||
if (!ts.isNewExpression(node.parent) || node.parent.expression !== node) reason = "harness:Test262Error-surface";
|
||||
@@ -192,7 +196,9 @@ export function exclusion(source, meta, variant) {
|
||||
}
|
||||
|
||||
export function prepare(source, asyncTest = false, marker = completion, variant = "strict", includes = []) {
|
||||
const names = asyncTest ? "assert, Test262Error, $DONE" : "assert, Test262Error";
|
||||
const names = asyncTest
|
||||
? "assert, compareArray, Test262Error, $DONE"
|
||||
: "assert, compareArray, Test262Error";
|
||||
const end = asyncTest ? "" : `;console.log(${JSON.stringify(marker)});\n`;
|
||||
const helpers =
|
||||
(includes.includes("propertyHelper.js") ? `${propertyHelperSource}\n` : "") +
|
||||
|
||||
Reference in New Issue
Block a user