mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-01 07:33:12 +08:00
A class extending Error without its own constructor (or one passing options to super) initializes the builtin prefix through the error.ctorOptions helper, whose message and options arguments are dynamic. The int32 slot analysis did not list that helper among the dynamic helpers that never store into a live class view, so a single such class anywhere in a program counted as a dynamic store naming every property: every f64 field of every class exposed to dynamic code lost its int32 storage, and the integer facts of the functions reading those fields went with it. error.ctorOptions runs scr_error_init_options, the same initializer error.newOptions (already listed) runs: it stamps the receiver's runtime-owned error prefix and only reads `options.cause`. In the native tsc-ts self-check, two such classes cost 7% total time and 10% check time. Unit test: int32-slots.test.ts. Corpus: 4596-error-subclass-int-fields pins Error subclasses forwarding message and options beside integer fields.
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
// A request counter keeps integer statistics while request failures are
|
|
// reported through Error subclasses that forward their message and options
|
|
// to Error, as a server's error type does next to its hot bookkeeping.
|
|
class Stats {
|
|
requests: number;
|
|
flags: number;
|
|
bytes: number;
|
|
constructor() {
|
|
this.requests = 0;
|
|
this.flags = 0;
|
|
this.bytes = 0;
|
|
}
|
|
record(size: number, flag: number): void {
|
|
this.requests = this.requests + 1;
|
|
this.flags |= flag;
|
|
this.bytes = (this.bytes + size) | 0;
|
|
}
|
|
}
|
|
|
|
class ServiceError extends Error {}
|
|
|
|
class TimeoutError extends ServiceError {
|
|
constructor(message: string, options: { cause: unknown }) {
|
|
super(`timeout: ${message}`, options);
|
|
}
|
|
}
|
|
|
|
const stats = new Stats();
|
|
const errors: ServiceError[] = [];
|
|
for (let i = 0; i < 12; i++) {
|
|
stats.record(i * 100, 1 << (i % 5));
|
|
if (i % 4 === 3) errors.push(new TimeoutError(`request ${i}`, { cause: `attempt ${stats.requests}` }));
|
|
if (i % 6 === 5) errors.push(new ServiceError(`failed ${i}`));
|
|
}
|
|
console.log(stats);
|
|
for (const error of errors) {
|
|
console.log(error instanceof TimeoutError, error.name, error.message, String(error.cause));
|
|
}
|
|
stats.record(7, 64);
|
|
console.log(stats.requests, stats.flags, stats.bytes);
|
|
try {
|
|
throw new TimeoutError("final", { cause: stats.flags });
|
|
} catch (error) {
|
|
if (error instanceof ServiceError) console.log(error.message, String(error.cause), error instanceof Error);
|
|
}
|