mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-07 08:33:50 +08:00
Convert checked-dynamic expected errors in assert.throws and assert.match (#2066)
This commit is contained in:
@@ -1355,7 +1355,7 @@ function lowerAssertMatch(
|
||||
lowerer.noLowering(`${surface} with ${expr.arguments.nodes.length} arguments`, expr);
|
||||
}
|
||||
const s = lowerer.lowerExprExpecting(expr.arguments.nodes[0]!, STRING);
|
||||
const re = lowerer.lowerExpr(expr.arguments.nodes[1]!);
|
||||
const re = lowerExpectedValue(lowerer, expr.arguments.nodes[1]!);
|
||||
if (re.type.kind !== "regex") {
|
||||
lowerer.noLowering(
|
||||
`${surface} with a non-regex pattern`,
|
||||
@@ -1420,6 +1420,18 @@ function inErrorHierarchy(lowerer: Lowerer, className: string): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** An expected string or regex: a value JavaScript stores checked-dynamic
|
||||
* (an object literal's field, an untyped binding) converts to the string
|
||||
* or regex its checker type names, so the comparison takes that arm. */
|
||||
function lowerExpectedValue(lowerer: Lowerer, node: ts.Expression): IrExpr {
|
||||
const value = lowerer.lowerExpr(node);
|
||||
if (value.type.kind !== "dyn") return value;
|
||||
const expected = lowerer.mapTypeOf(lowerer.typeOf(node));
|
||||
return expected?.kind === "string" || expected?.kind === "regex"
|
||||
? lowerer.coerceToExpected(value, expected)
|
||||
: value;
|
||||
}
|
||||
|
||||
/** Classify the expected argument: string → message, regex value → the
|
||||
* regex test over String(error), an error-class identifier → instanceof,
|
||||
* an object LITERAL over name/message/code (string or regex values) →
|
||||
@@ -1436,7 +1448,7 @@ function classifyThrowsExpected(
|
||||
return { form: "message", msg: m.msg, hasMsg: m.hasMsg };
|
||||
}
|
||||
if (expectedT?.kind === "regex") {
|
||||
return { form: "regex", value: lowerer.lowerExpr(node) };
|
||||
return { form: "regex", value: lowerExpectedValue(lowerer, node) };
|
||||
}
|
||||
const sym = ts.isIdentifier(node) ? lowerer.resolveValueSymbol(node) : null;
|
||||
const info =
|
||||
@@ -1509,7 +1521,7 @@ function classifyThrowsExpected(
|
||||
);
|
||||
}
|
||||
const valueNode = ts.isPropertyAssignment(named) ? named.initializer : named.name;
|
||||
const value = lowerer.lowerExpr(valueNode);
|
||||
const value = lowerExpectedValue(lowerer, valueNode);
|
||||
if (value.type.kind === "string") {
|
||||
byId.set(id, { id, kind: "str", value, enameBake: null });
|
||||
} else if (value.type.kind === "regex") {
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/8160-assert-expected-from-fields.cjs"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Expected errors stored in an object literal's fields: a JavaScript
|
||||
// object keeps its fields checked-dynamic, and assert.throws, assert.match
|
||||
// and the expected-object form convert them to the regex or string the
|
||||
// fields hold.
|
||||
"use strict";
|
||||
const assert = require("assert");
|
||||
|
||||
const errMessages = {
|
||||
auth: / auth/,
|
||||
state: / state/,
|
||||
length: /Invalid initialization vector/,
|
||||
code: "ERR_CRYPTO_INVALID_IV",
|
||||
};
|
||||
|
||||
const error = (message, code) => {
|
||||
const e = new Error(message);
|
||||
if (code) e.code = code;
|
||||
return e;
|
||||
};
|
||||
|
||||
assert.throws(() => {
|
||||
throw error("Unsupported state or unable to authenticate data");
|
||||
}, errMessages.auth);
|
||||
assert.throws(() => {
|
||||
throw error("Invalid state for operation getAuthTag");
|
||||
}, errMessages.state);
|
||||
assert.throws(
|
||||
() => {
|
||||
throw error("Invalid initialization vector", "ERR_CRYPTO_INVALID_IV");
|
||||
},
|
||||
{ code: errMessages.code, message: errMessages.length },
|
||||
);
|
||||
assert.match("unable to auth", errMessages.auth);
|
||||
assert.doesNotMatch("no match here", errMessages.state);
|
||||
|
||||
const report = (label, run) => {
|
||||
try {
|
||||
run();
|
||||
console.log(label, "passed");
|
||||
} catch (error) {
|
||||
console.log(label, error.name, error.code, error.message.split("\n")[0]);
|
||||
}
|
||||
};
|
||||
report("wrong message", () =>
|
||||
assert.throws(() => {
|
||||
throw error("something else");
|
||||
}, errMessages.length),
|
||||
);
|
||||
report("wrong code", () =>
|
||||
assert.throws(
|
||||
() => {
|
||||
throw error("Invalid initialization vector", "ERR_OTHER");
|
||||
},
|
||||
{ code: errMessages.code },
|
||||
),
|
||||
);
|
||||
report("match", () => assert.match("plain text", errMessages.auth));
|
||||
console.log("done");
|
||||
@@ -0,0 +1 @@
|
||||
{ "plain": 2656, "san": 5234 }
|
||||
Reference in New Issue
Block a user