mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-02 08:35:07 +08:00
Support JavaScript async class methods in static mode (#515)
This commit is contained in:
@@ -1714,6 +1714,9 @@ export class CEmitter {
|
||||
* every type that cannot hold undefined (tsc's SPI guards those) and for
|
||||
* record shapes' construction paths, which write every field. */
|
||||
undefFieldInitLineC(name: string, t: IrType): string[] {
|
||||
// Error.cause uses NULL for absence; only the options constructor may
|
||||
// install a present value (including undefined) in this runtime slot.
|
||||
if (name === "%cause") return [];
|
||||
if (t.kind === "dyn") {
|
||||
return [` o->${mangleField(name)} = scr_dyn_undefined(); /* ${cCommentText(name)} starts undefined */`];
|
||||
}
|
||||
|
||||
@@ -205,6 +205,9 @@ export interface ClassHost extends ShapeHost {
|
||||
function undefFieldInits(host: ClassHost, meta: LlClassMeta): string[] {
|
||||
const out: string[] = [];
|
||||
meta.def.fields.forEach((f, i) => {
|
||||
// Error.cause uses NULL for absence; an options constructor installs
|
||||
// a value only when the cause property is present.
|
||||
if (f.name === "%cause") return;
|
||||
const { index } = classFieldIndex(meta, f.name);
|
||||
if (f.type.kind === "jsval" || f.type.kind === "dyn") {
|
||||
const undefinedFn = f.type.kind === "dyn" ? "scr_dyn_undefined" : "scr_jsval_undefined";
|
||||
|
||||
@@ -1797,22 +1797,9 @@ export function collectClassShapeInner(lowerer: Lowerer, decl: ts.ClassLikeDecla
|
||||
collectGenericMember(member, false);
|
||||
continue;
|
||||
}
|
||||
// Async METHODS in JS classes simply do not COLLECT — each call
|
||||
// fences at its own site (the JS deferral stance, the
|
||||
// async-static precedent above), so a class whose driven
|
||||
// surface is synchronous still compiles (commander: parse()
|
||||
// works, parseAsync() traps where called). TS async methods
|
||||
// collect below like any method: the body is an async
|
||||
// IrFunction (fiber spawn wrapper, `this` as param 0), calls
|
||||
// dispatch STATICALLY — override chains fence (the vtable slot
|
||||
// machinery has no fiber-spawn story), so every call site is a
|
||||
// direct call the emitter routes through the spawn wrapper.
|
||||
if (
|
||||
member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
|
||||
isJsSourceFile(decl.getSourceFile())
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
// Async methods collect with the same direct-call spawn wrapper
|
||||
// for JavaScript and TypeScript classes. Override chains remain
|
||||
// fenced below because vtable slots cannot enter that wrapper.
|
||||
// IMPLICIT-ANY monomorphization (npm-static JS): a method whose
|
||||
// signature carries bindable untyped params collects like a
|
||||
// GENERIC method — into genericMethods, no vtable slot, one
|
||||
|
||||
@@ -7619,6 +7619,12 @@
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/3122-js-async-class-methods.js": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/3122-js-async-class-methods.js"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/400-fib.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/400-fib.ts"
|
||||
|
||||
@@ -16,6 +16,7 @@ report("uri", new URIError("uri"));
|
||||
report("child reference", new ChildReferenceError("child"));
|
||||
report("child eval", new ChildEvalError("child"));
|
||||
report("child uri", new ChildURIError("child"));
|
||||
report("child cause", new ChildReferenceError("present", { cause: undefined }));
|
||||
|
||||
try {
|
||||
throw new ReferenceError("caught");
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
class Source {
|
||||
value = 4;
|
||||
|
||||
async doubled() {
|
||||
await Promise.resolve();
|
||||
return this.value * 2;
|
||||
}
|
||||
|
||||
async *steps() {
|
||||
yield this.value;
|
||||
await Promise.resolve();
|
||||
yield this.value + 1;
|
||||
}
|
||||
}
|
||||
|
||||
var Pair = class {
|
||||
async *values([first, second]) {
|
||||
yield first;
|
||||
yield second;
|
||||
}
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const source = new Source();
|
||||
console.log(await source.doubled());
|
||||
const steps = source.steps();
|
||||
console.log((await steps.next()).value, (await steps.next()).value, (await steps.next()).done);
|
||||
const pair = new Pair().values([7, 8]);
|
||||
console.log((await pair.next()).value, (await pair.next()).value, (await pair.next()).done);
|
||||
}
|
||||
|
||||
void main();
|
||||
Reference in New Issue
Block a user