Skip to content

Compiled async delegation loses rejection identity for nested iterator-result helper #3668

Open

Description

@nickna

A valid iterator-result object produced by a nested helper during async-generator delegation causes the compiled engine to lose the original rejected value. Both Node v22.23.2 and the interpreted engine print true 0; a saved standalone compiled assembly prints false 0.

async function check(request, final, getter) {
    const marker = {};
    let first = true, returns = 0;
    function step() {
        return {
            get done() { if (getter === "done") throw marker; return final; },
            get value() { if (getter === "value") throw marker; return Promise.reject(marker); }
        };
    }
    const iterator = {
        next() {
            if (request !== "next" && first) { first = false; return { value: 1, done: false }; }
            return step();
        },
        throw() { return step(); },
        return() { console.log("return", ++returns, arguments.length); return step(); }
    };
    async function* run() { yield* { [Symbol.iterator]() { return iterator; } }; }
    const generator = run();
    if (request !== "next") await generator.next();
    try {
        if (request === "return") await generator.return(9);
        else if (request === "throw") await generator.throw("injected");
        else await generator.next();
    } catch (error) { console.log(error === marker, returns); }
}
async function main() { await check("next", true, "none"); }
main();

Verified with compiler source unchanged from PR #3663 baseline a1b016466 (verification binary includes the interpreter-only correction 774f626b4):

dotnet SharpTS.dll --compile source.ts --standalone --verify -o repro.dll
Compiled to repro.dll
IL verification passed.
dotnet repro.dll
false 0

Moving step, its captured configuration, and the iterator to top-level storage makes the corresponding eight exclusion controls pass in both engines. This report preserves the original failing shape; the exact compiler cause has not been established. The result is a valid object, unlike the deliberately invalid result cases in #3661. done is true here, so no rejection cleanup is required, unlike #3666.

Discovered while verifying PR review comment 4546709732. This unchanged compiled path was kept separate from the scoped interpreter fix. Artifact fixtures are retained at artifacts/rejection-close/exclusion-0.ts in the isolated review worktree.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions