mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Support top-level await (#5371)
* 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
This commit is contained in:
parent
b0946c3c60
commit
c4f1fe7132
8 changed files with 45 additions and 19 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -715,13 +715,14 @@
|
|||
constructor(body1) {
|
||||
super();
|
||||
this.body = body1;
|
||||
this.isAsync = (new Code([], this.body)).isAsync;
|
||||
}
|
||||
|
||||
// Wrap everything in a safety closure, unless requested not to. It would be
|
||||
// better not to generate them in the first place, but for now, clean up
|
||||
// obvious double-parentheses.
|
||||
compileNode(o) {
|
||||
var fragments;
|
||||
var fragments, parts;
|
||||
o.indent = o.bare ? '' : TAB;
|
||||
o.level = LEVEL_TOP;
|
||||
o.compiling = true;
|
||||
|
@ -730,7 +731,15 @@
|
|||
if (o.bare) {
|
||||
return fragments;
|
||||
}
|
||||
return [].concat(this.makeCode("(function() {\n"), fragments, this.makeCode("\n}).call(this);\n"));
|
||||
parts = [];
|
||||
parts.push(this.makeCode('('));
|
||||
if (this.isAsync) {
|
||||
parts.push(this.makeCode('async '));
|
||||
}
|
||||
parts.push(this.makeCode('function() {\n'));
|
||||
parts.push(...fragments);
|
||||
parts.push(this.makeCode('\n}).call(this);\n'));
|
||||
return [].concat(...parts);
|
||||
}
|
||||
|
||||
initializeScope(o) {
|
||||
|
@ -7120,7 +7129,9 @@
|
|||
var op, parts, ref1;
|
||||
parts = [];
|
||||
op = this.operator;
|
||||
this.checkContinuation(o);
|
||||
if (!this.isAwait()) {
|
||||
this.checkContinuation(o);
|
||||
}
|
||||
if (indexOf.call(Object.keys(this.first), 'expression') >= 0 && !(this.first instanceof Throw)) {
|
||||
if (this.first.expression != null) {
|
||||
parts.push(this.first.expression.compileToFragments(o, LEVEL_OP));
|
||||
|
@ -7176,7 +7187,7 @@
|
|||
}
|
||||
|
||||
astNode(o) {
|
||||
if (this.isYield() || this.isAwait()) {
|
||||
if (this.isYield()) {
|
||||
this.checkContinuation(o);
|
||||
}
|
||||
this.checkDeleteOperand(o);
|
||||
|
|
|
@ -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
|
||||
|
@ -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 ? []
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
''', '''
|
||||
|
|
Loading…
Reference in a new issue