Files
scriptc/tests/diagnostics/component-fences.ts
T
Malte UblandClaude Opus 5.5 f4a8511dca Compile maybe-promise unions, unknown[] rest parameters, and function-valued Maps and Sets
A union may now hold one promise beside data members (`T | Promise<T>`,
`Promise<R | void> | R | void`). The union tag is the `instanceof Promise`
test, and every operation keeps Node's microtask timing: `await` awaits the
promise arm or takes the one non-thenable turn, an async `return` (block
bodies, concise arrows, then handlers) adopts the promise arm after the
function's own finally blocks, `Promise.resolve` returns the promise arm as
is, and `typeof (u as any).then` reads the tag. Data arms that declare
`then`, two promise arms, and function arms beside a promise stay refused
with diagnostics. Inferred JavaScript literals that mix promises and values
keep the checked-dynamic array.

Rest parameters typed `unknown[]` or `any[]` in TypeScript use the
checked-dynamic variadic ABI that JavaScript rest parameters already use,
including spread forwarding (`(...args) => handler(...args)`).

Functions are now Map values, Map keys and Set elements, compared by
closure identity.

Two pre-existing bugs in the same area are fixed: an async lambda in a
`Promise<void> | void` slot got a `Promise<union>` ABI and threw when called
through the slot, and `return cb()` of such a callback in an async function
dropped the promise instead of adopting it.

The retired-engine 2251 and 2790 diagnostics fixtures (tagged templates
with `any[]` rest tags) now compile and match Node, so they move to the
corpus as 6248 and 6249.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:58:57 -07:00

47 lines
1.5 KiB
TypeScript

// SC2009: supported shapes over a component type outside its slot — the
// container is not the blocker, and each message names the component.
// Boolean Map keys remain outside the supported key domain.
const byFlag = new Map<boolean, string>();
console.log(byFlag);
// Map values have no slot for Dates.
const stamps = new Map<string, Date>();
console.log(stamps);
// Boolean Set elements remain outside the supported element domain.
const flags = new Set<boolean>();
console.log(flags);
// Arrays hold Map elements; retain the accepted adjacent form.
const rows: Map<string, number>[] = [];
console.log(rows);
// Nullable Maps compile and remain as working context.
function report(maybe: Map<string, number> | undefined): number {
return maybe === undefined ? 0 : maybe.size;
}
console.log(report(undefined));
// Typed rest values now compile; retained here as working context for the
// component-type failures below.
const sum = (...xs: number[]): number => xs.length;
const storedSum = sum;
console.log(storedSum(1, 2));
// A function's return type carries the failure. The value arrives through
// a cast, not an ambient declare (a declare-rooted chain would compile to
// Node's ReferenceError at the root instead).
const makeWeak = (0 as unknown) as () => WeakRef<object>;
const storedMake = makeWeak;
console.log(storedMake());
// A record member's type carries the failure.
interface Holder {
label: string;
cache: WeakRef<object>;
}
const held = (0 as unknown) as Holder;
const kept = held;
console.log(kept.label);