mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-07 08:33:50 +08:00
Read inherited keys in assert.throws with a shared expected object (#2610)
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/assert-throws-shared-expected.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -2425,18 +2425,29 @@ void scr_assert_loose_deep_result(bool equal, bool negated, ScrStr *msg, bool ha
|
||||
/* Node's expectsError over an error-INSTANCE expected (assert.throws/
|
||||
* rejects second argument): every key of the expected dyn error (the
|
||||
* %error marker skipped; name/message/code is the encoding's surface)
|
||||
* must deep-strict-equal the caught value's — extra ACTUAL keys are fine
|
||||
* (Node walks the expected's keys only). A mismatch fails through the
|
||||
* must be in the caught value (own or inherited) and deep-strict-equal
|
||||
* it — extra ACTUAL keys are fine (Node walks the expected's keys only). A mismatch fails through the
|
||||
* deep-equal report (a mismatched key implies the full comparison
|
||||
* differs, so the diff is honest); a non-object pair falls back to the
|
||||
* full deep comparison outright. */
|
||||
/* actual[key] where `key in actual` holds: an own property or one on the
|
||||
* prototype chain (an error's name, and its message when it is not own,
|
||||
* sit on the prototype). NULL when the key is absent. */
|
||||
static ScrDyn *scr_assert_dyn_key(const ScrDyn *actual, const char *key, size_t key_len) {
|
||||
for (const ScrDyn *o = actual; o != NULL && o->kind == SCR_DYN_OBJ; o = o->prototype) {
|
||||
ScrDyn *v = scr_dyn_obj_get(o, key, key_len);
|
||||
if (v != NULL) return v;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void scr_assert_expects_err_dyn(ScrDyn *actual, ScrDyn *expected, ScrStr *msg, bool has_msg) {
|
||||
if (actual->kind == SCR_DYN_OBJ && expected->kind == SCR_DYN_OBJ) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < scr_dyn_obj_count(expected) && ok; i++) {
|
||||
ScrDynProp e = scr_dyn_obj_prop_at(expected, i);
|
||||
if (e.key_len == 6 && memcmp(e.key, "%error", 6) == 0) continue;
|
||||
ScrDyn *av = scr_dyn_obj_get(actual, e.key, e.key_len);
|
||||
ScrDyn *av = scr_assert_dyn_key(actual, e.key, e.key_len);
|
||||
if (av == NULL || !scr_assert_dyn_deep_eq(av, e.value)) ok = false;
|
||||
}
|
||||
if (ok) return;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// assert.throws and assert.rejects with an expected object held in a
|
||||
// variable compare each of its keys with the thrown error's, own or
|
||||
// inherited: an error's name is on its prototype, so { name, message, code }
|
||||
// matches errors the runtime throws as well as errors the program throws.
|
||||
import assert from "node:assert";
|
||||
|
||||
const invalidUrl = { code: "ERR_INVALID_URL", name: "TypeError", message: "Invalid URL" };
|
||||
const outOfRange = { code: "ERR_OUT_OF_RANGE", name: "RangeError" };
|
||||
const thrownType = { name: "TypeError", message: "bad input" };
|
||||
const wrongName = { name: "RangeError", message: "bad input" };
|
||||
|
||||
function check(label: string, fn: () => void): void {
|
||||
try {
|
||||
fn();
|
||||
console.log(label, "passed");
|
||||
} catch (error) {
|
||||
const e = error as NodeJS.ErrnoException;
|
||||
console.log(label, "failed", e.name, e.code);
|
||||
}
|
||||
}
|
||||
|
||||
check("url", () => assert.throws(() => new URL("not a url"), invalidUrl));
|
||||
check("buffer", () => assert.throws(() => Buffer.alloc(-1), outOfRange));
|
||||
check("thrown", () =>
|
||||
assert.throws(() => {
|
||||
throw new TypeError("bad input");
|
||||
}, thrownType),
|
||||
);
|
||||
check("mismatch", () =>
|
||||
assert.throws(() => {
|
||||
throw new TypeError("bad input");
|
||||
}, wrongName),
|
||||
);
|
||||
|
||||
async function main(): Promise<void> {
|
||||
await assert.rejects(Promise.reject(new TypeError("bad input")), thrownType);
|
||||
console.log("rejects passed");
|
||||
try {
|
||||
await assert.rejects(Promise.reject(new TypeError("bad input")), wrongName);
|
||||
console.log("rejects mismatch passed");
|
||||
} catch (error) {
|
||||
console.log("rejects mismatch failed", (error as NodeJS.ErrnoException).code);
|
||||
}
|
||||
}
|
||||
|
||||
void main();
|
||||
Reference in New Issue
Block a user