Skip to content

Commit

Permalink
Support top-level await (#5371)
Browse files Browse the repository at this point in the history
* Support top-level await

* Remove code duplication

* Avoid use of trimEnd so tests pass in old Node

* Proposed rewrite of tests

* startsWith tests; revert eqJS

* build:browser
  • Loading branch information
edemaine authored Sep 15, 2021
1 parent b0946c3 commit c4f1fe7
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 19 deletions.
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

0 comments on commit c4f1fe7

Please sign in to comment.