Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support top-level await #5371

Merged
merged 7 commits into from
Sep 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/v2/browser-compiler-legacy/coffeescript.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/v2/browser-compiler-modern/coffeescript.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/coffeescript-browser-compiler-legacy/coffeescript.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/coffeescript-browser-compiler-modern/coffeescript.js

Large diffs are not rendered by default.

19 changes: 15 additions & 4 deletions lib/coffeescript/nodes.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 11 additions & 3 deletions src/nodes.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ exports.Root = class Root extends Base
constructor: (@body) ->
super()

@isAsync = (new Code [], @body).isAsync

children: ['body']

# Wrap everything in a safety closure, unless requested not to. It would be
Expand All @@ -525,7 +527,13 @@ exports.Root = class Root extends Base
@initializeScope o
fragments = @body.compileRoot o
return fragments if o.bare
[].concat @makeCode("(function() {\n"), fragments, @makeCode("\n}).call(this);\n")
parts = []
parts.push @makeCode '('
parts.push @makeCode 'async ' if @isAsync
parts.push @makeCode 'function() {\n'
parts.push ...fragments
parts.push @makeCode '\n}).call(this);\n'
[].concat ...parts

initializeScope: (o) ->
o.scope = new Scope null, @body, null, o.referencedVars ? []
Expand Down Expand Up @@ -4782,7 +4790,7 @@ exports.Op = class Op extends Base
compileContinuation: (o) ->
parts = []
op = @operator
@checkContinuation o
@checkContinuation o unless @isAwait()
if 'expression' in Object.keys(@first) and not (@first instanceof Throw)
parts.push @first.expression.compileToFragments o, LEVEL_OP if @first.expression?
else
Expand Down Expand Up @@ -4817,7 +4825,7 @@ exports.Op = class Op extends Base
@error 'delete operand may not be argument or var'

astNode: (o) ->
@checkContinuation o if @isYield() or @isAwait()
@checkContinuation o if @isYield()
@checkDeleteOperand o
super o

Expand Down
14 changes: 14 additions & 0 deletions test/async.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,17 @@ test "#3199: await multiline implicit object", ->
type: 'a'
msg: 'b'
eq undefined, y

test "top-level await", ->
eqJS 'await null', 'await null;'

test "top-level wrapper has correct async attribute", ->
starts = (code, prefix) ->
compiled = CoffeeScript.compile code
unless compiled.startsWith prefix
fail """Expected generated JavaScript to start with:
#{reset}#{prefix}#{red}
but instead it was:
#{reset}#{compiled}#{red}"""
starts 'await null', '(async function'
starts 'do -> await null', '(function'
9 changes: 1 addition & 8 deletions test/error_messages.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -1257,14 +1257,7 @@ test "CoffeeScript keywords cannot be used as local names in import list aliases
^^^^^^
'''

test "cannot have `await` outside a function", ->
assertErrorFormat '''
await 1
''', '''
[stdin]:1:1: error: await can only occur inside functions
await 1
^^^^^^^
'''
test "cannot have `await return` outside a function", ->
assertErrorFormat '''
await return
''', '''
Expand Down