Skip to content

Commit ff24e5c

Browse files
helixbassGeoffreyBooth
authored andcommitted
Dynamic import (#5169)
* dynamic import * updated grammar * specify callable * DynamicImportCall * Fix from code review Co-Authored-By: helixbass <[email protected]> * recompile
1 parent ca275c2 commit ff24e5c

File tree

10 files changed

+292
-186
lines changed

10 files changed

+292
-186
lines changed

lib/coffeescript/grammar.js

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/coffeescript/lexer.js

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/coffeescript/nodes.js

Lines changed: 18 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/coffeescript/parser.js

Lines changed: 185 additions & 181 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/grammar.coffee

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ grammar =
240240
o 'Super'
241241
o 'This'
242242
o 'SUPER Arguments', -> new SuperCall LOC(1)(new Super), $2, no, $1
243+
o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
243244
o 'SimpleObjAssignable Arguments', -> new Call (new Value $1), $2
244245
o 'ObjSpreadExpr Arguments', -> new Call $1, $2
245246
]
@@ -485,6 +486,7 @@ grammar =
485486
o 'Value OptFuncExist String', -> new TaggedTemplateCall $1, $3, $2
486487
o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2
487488
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2, $1
489+
o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
488490
]
489491

490492
# An optional existence check on a function.
@@ -891,7 +893,7 @@ operators = [
891893
['right', 'YIELD']
892894
['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS']
893895
['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN']
894-
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT']
896+
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT', 'DYNAMIC_IMPORT']
895897
['left', 'POST_IF']
896898
]
897899

src/lexer.coffee

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,9 @@ exports.Lexer = class Lexer
667667
@error message, origin[2] if message
668668
return value.length if skipToken
669669

670+
if value is '(' and prev?[0] is 'IMPORT'
671+
prev[0] = 'DYNAMIC_IMPORT'
672+
670673
if value is '{' and @seenImport
671674
@importSpecifierList = yes
672675
else if @importSpecifierList and value is '}'
@@ -1356,7 +1359,7 @@ BOOL = ['TRUE', 'FALSE']
13561359
# Tokens which could legitimately be invoked or indexed. An opening
13571360
# parentheses or bracket following these tokens will be recorded as the start
13581361
# of a function invocation or indexing operation.
1359-
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER']
1362+
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER', 'DYNAMIC_IMPORT']
13601363
INDEXABLE = CALLABLE.concat [
13611364
'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END'
13621365
'BOOL', 'NULL', 'UNDEFINED', '}', '::'

src/nodes.coffee

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,6 +2172,16 @@ exports.ExportSpecifier = class ExportSpecifier extends ModuleSpecifier
21722172
constructor: (local, exported) ->
21732173
super local, exported, 'export'
21742174

2175+
exports.DynamicImport = class DynamicImport extends Base
2176+
compileNode: ->
2177+
[@makeCode 'import']
2178+
2179+
exports.DynamicImportCall = class DynamicImportCall extends Call
2180+
compileNode: (o) ->
2181+
unless @args.length is 1
2182+
@error 'import() requires exactly one argument'
2183+
super o
2184+
21752185
#### Assign
21762186

21772187
# The **Assign** is used to assign a local variable to value, or to set the

test/error_messages.coffee

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,3 +1925,29 @@ test "`new.target` is only allowed meta property", ->
19251925
-> new.something
19261926
^^^^^^^^^^^^^
19271927
'''
1928+
1929+
test "#4834: dynamic import requires exactly one argument", ->
1930+
assertErrorFormat '''
1931+
import()
1932+
''', '''
1933+
[stdin]:1:1: error: import() requires exactly one argument
1934+
import()
1935+
^^^^^^^^
1936+
'''
1937+
1938+
assertErrorFormat '''
1939+
import('x', {})
1940+
''', '''
1941+
[stdin]:1:1: error: import() requires exactly one argument
1942+
import('x', {})
1943+
^^^^^^^^^^^^^^^
1944+
'''
1945+
1946+
test "#4834: dynamic import requires explicit call parentheses", ->
1947+
assertErrorFormat '''
1948+
promise = import 'foo'
1949+
''', '''
1950+
[stdin]:1:23: error: unexpected end of input
1951+
promise = import 'foo'
1952+
^
1953+
'''

test/modules.coffee

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,3 +920,24 @@ test "#4874: backslash `export`", ->
920920
min
921921
} from 'underscore';
922922
"""
923+
924+
test "#4834: dynamic import", ->
925+
eqJS """
926+
import('module').then ->
927+
""",
928+
"""
929+
import('module').then(function() {});
930+
"""
931+
932+
eqJS """
933+
foo = ->
934+
bar = await import('bar')
935+
""",
936+
"""
937+
var foo;
938+
939+
foo = async function() {
940+
var bar;
941+
return bar = (await import('bar'));
942+
};
943+
"""

test/object_rest_spread.coffee

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,13 @@ test "#4673: complex destructured object spread variables", ->
418418
g = ({@y...}) ->
419419
eq @y.b, 1
420420
g b: 1
421+
422+
test "#4834: dynamic import can technically be object spread", ->
423+
eqJS """
424+
x = {...import('module')}
425+
""",
426+
"""
427+
var x;
428+
429+
x = {...import('module')};
430+
"""

0 commit comments

Comments
 (0)