Files
scriptc/tests/corpus/3086-error-constructor-options.ts
Chris Tate ffe5e27563 feat(compiler): run the IR validator natively (#493)
- Compile the production validator and exercise native IR construction and validation on C and LLVM.
- Preserve Error causes, wider callbacks, and discriminated JSON layouts in static programs.
- Version the IR and runtime ABI and cover the new compiler paths with differential and sanitizer tests.
2026-09-27 13:11:56 -05:00

67 lines
2.9 KiB
TypeScript

export {};
class CompilerError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message, options);
this.name = "CompilerError";
}
}
class Derived extends CompilerError {}
class Inherited extends TypeError {}
class DeepInherited extends Inherited {}
function report(label: string, error: Error): void {
console.log(label, error.name, JSON.stringify(error.message), "cause" in error, error.cause);
}
function make(message?: string, options?: ErrorOptions): CompilerError {
return new CompilerError(message, options);
}
report("absent", make());
report("empty", make("", {}));
report("explicit undefined", make(undefined, { cause: undefined }));
report("null", make("null cause", { cause: null }));
report("number", make("number cause", { cause: 42 }));
report("boolean", make("boolean cause", { cause: false }));
report("string", make("string cause", { cause: "root" }));
report("derived", new Derived("inherited", { cause: 7 }));
report("builtin chain", new DeepInherited(undefined, { cause: "root" }));
report("default chain", new DeepInherited());
report("Error", new Error("message", { cause: "error" }));
report("TypeError", new TypeError("message", { cause: "type" }));
report("RangeError", new RangeError("message", { cause: "range" }));
report("SyntaxError", new SyntaxError("message", { cause: "syntax" }));
// Forwarding the standard library interface keeps missing and undefined
// distinct even when the options travel through nullable control flow.
function forward(flag: number): Error {
let options: ErrorOptions | undefined;
if (flag === 1) options = {};
if (flag === 2) options = { cause: undefined };
if (flag === 3) options = { cause: "present" };
return new Derived(undefined, options);
}
for (let flag = 0; flag < 4; flag++) report("forward " + flag, forward(flag));
const original: Error = new RangeError("underlying");
const wrapped = new CompilerError("wrapper", { cause: original });
const cause = wrapped.cause;
console.log("identity", cause instanceof Error && cause === original);
if (cause instanceof Error) console.log("cause class", cause.name, cause.message, cause instanceof RangeError);
console.log("class", wrapped instanceof Error, wrapped instanceof CompilerError, wrapped.toString());
// Constructor arguments run exactly once, left-to-right, before super's
// field initializers and the rest of the subclass body.
let events = "";
function message(): string { events += "message;"; return "value"; }
function options(): ErrorOptions { events += "options;"; return { cause: 5 }; }
function field(): number { events += "field;"; return 9; }
class Ordered extends Error {
value = field();
constructor(message?: string, options?: ErrorOptions) {
super(message, options);
events += "body;";
}
}
const ordered = new Ordered(message(), options());
console.log("order", events, ordered.message, ordered.cause, ordered.value);