Skip to content

fix(parser): object-literal async shorthand methods now track async-function context (#129) - #134

Merged
nooga merged 3 commits into
mainfrom
fix/129-object-literal-async-shorthand
Aug 31, 2026
Merged

fix(parser): object-literal async shorthand methods now track async-function context (#129)#134
nooga merged 3 commits into
mainfrom
fix/129-object-literal-async-shorthand

Conversation

@nooga

@nooga nooga commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #129.

The async-method-shorthand branch in parseObjectLiteral (async foo() {...} and async *foo() {...} inside an object literal) never saved/incremented/restored p.inAsyncFunction around its own body parse, unlike the four reference sites: parser.go:2898 (parseFunctionLiteral), parser.go:5175 (parseArrowFunctionBodyAndFinish), and the class-method equivalents (parse_class.go:869, parse_class.go:1470).

Without it, await inside the method's body resolved against whatever async/non-async depth the enclosing function had left behind, not the method's own (always-async) context. Defining such an object literal inside a plain, non-async function made await mis-parse as a plain identifier and throw await is not defined instead of awaiting.

Fix

Copied the save/increment/restore pattern from the reference sites. One deviation, called out in the code comment: this branch has an early return nil between the body parse and the rest of the function (on a malformed body), so the restore happens before that check rather than unconditionally after, to avoid leaking the incremented depth into whatever the parser recovers into.

Testing

🤖 Generated with Claude Code

nooga added 2 commits August 30, 2026 22:24
…unction context (#129)

The async-method-shorthand branch in parseObjectLiteral (async foo() {...}
and async *foo() {...} inside an object literal) never saved, incremented,
or restored p.inAsyncFunction/p.inNonAsyncFunction around its own body
parse, unlike every other async body (parseFunctionLiteral,
parseArrowFunctionBodyAndFinish, and the class-method equivalents).

Without it, 'await' inside the method's body was resolved against
whatever async/non-async depth the *enclosing* function had left behind,
not the method's own (always-async) context. Defining such an object
literal inside a plain, non-async function made 'await' mis-parse as a
plain identifier instead of an await-expression, throwing "await is not
defined" instead of awaiting.

Fixed by copying the save/increment/restore pattern from the reference
call sites. Restoration happens before checking the parsed body for nil
(rather than after, like the reference sites do unconditionally) since
this branch, unlike those, has an early-return between the parse call and
the rest of the function - restoring first avoids leaking the incremented
depth into whatever the parser recovers into on a malformed body.

Added tests/scripts/async_method_object_literal_nested.ts and
tests/scripts/async_generator_method_object_literal_nested.ts (kept
separate: combining both methods in one object literal and awaiting them
sequentially trips an unrelated, pre-existing VM panic, filed as #133).
…oadFrame

All PRs currently fail CI's golangci-lint job on this pre-existing issue,
unrelated to any of their own changes (confirmed: main itself fails lint
with these same 14 findings before this fix).

Seven identical proxy-trap-error-handling sites set code/constants (along
with frame/closure/function/registers/ip) just before `goto reloadFrame`.
The reloadFrame: label unconditionally re-derives all seven of those same
variables from vm.frames[vm.frameCount-1] immediately after the jump, so
the code/constants assignments right before the goto are always
overwritten before being read - ineffassign correctly flags them as dead.
Removed the 14 dead lines; behavior is identical since reloadFrame
already does this work.
…e' into fix/129-object-literal-async-shorthand
@nooga
nooga merged commit f49b07e into main Aug 31, 2026
8 checks passed
@nooga
nooga deleted the fix/129-object-literal-async-shorthand branch August 31, 2026 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

parser: parenthesized await inside an object-literal shorthand async method mis-parses as an arrow-function parameter

1 participant