Skip to content

Commit 2fd9ee4

Browse files
Support import.meta and import.meta.* (#5319)
Co-authored-by: Geoffrey Booth <[email protected]>
1 parent 389ce89 commit 2fd9ee4

12 files changed

+351
-161
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
name: Build and Test
44

5-
on:
6-
push
5+
on: [push, pull_request]
76

87
jobs:
98
ci:

lib/coffeescript/grammar.js

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

lib/coffeescript/lexer.js

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

lib/coffeescript/nodes.js

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

lib/coffeescript/parser.js

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

src/grammar.coffee

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ o = (patternString, action, options) ->
3434
patternString = patternString.replace /\s{2,}/g, ' '
3535
patternCount = patternString.split(' ').length
3636
if action
37+
# This code block does string replacements in the generated `parser.js`
38+
# file, replacing the calls to the `LOC` function and other strings as
39+
# listed below.
3740
action = if match = unwrap.exec action then match[1] else "(#{action}())"
3841

3942
# All runtime functions we need are defined on `yy`
@@ -47,8 +50,33 @@ o = (patternString, action, options) ->
4750
getAddDataToNodeFunctionString = (first, last, forceUpdateLocation = yes) ->
4851
"yy.addDataToNode(yy, @#{first}, #{if first[0] is '$' then '$$' else '$'}#{first}, #{if last then "@#{last}, #{if last[0] is '$' then '$$' else '$'}#{last}" else 'null, null'}, #{if forceUpdateLocation then 'true' else 'false'})"
4952

53+
# This code replaces the calls to `LOC` with the `yy.addDataToNode` string
54+
# defined above. The `LOC` function, when used below in the grammar rules,
55+
# is used to make sure that newly created node class objects get correct
56+
# location data assigned to them. By default, the grammar will assign the
57+
# location data spanned by *all* of the tokens on the left (e.g. a string
58+
# such as `'Body TERMINATOR Line'`) to the “top-level” node returned by
59+
# the grammar rule (the function on the right). But for “inner” node class
60+
# objects created by grammar rules, they won’t get correct location data
61+
# assigned to them without adding `LOC`.
62+
63+
# For example, consider the grammar rule `'NEW_TARGET . Property'`, which
64+
# is handled by a function that returns
65+
# `new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)`.
66+
# The `1` in `LOC(1)` refers to the first token (`NEW_TARGET`) and the `3`
67+
# in `LOC(3)` refers to the third token (`Property`). In order for the
68+
# `new IdentifierLiteral` to get assigned the location data corresponding
69+
# to `new` in the source code, we use
70+
# `LOC(1)(new IdentifierLiteral ...)` to mean “assign the location data of
71+
# the *first* token of this grammar rule (`NEW_TARGET`) to this
72+
# `new IdentifierLiteral`”. The `LOC(3)` means “assign the location data of
73+
# the *third* token of this grammar rule (`Property`) to this
74+
# `new Access`”.
5075
returnsLoc = /^LOC/.test action
5176
action = action.replace /LOC\(([0-9]*)\)/g, getAddDataToNodeFunctionString('$1')
77+
# A call to `LOC` with two arguments, e.g. `LOC(2,4)`, sets the location
78+
# data for the generated node on both of the referenced tokens (the second
79+
# and fourth in this example).
5280
action = action.replace /LOC\(([0-9]*),\s*([0-9]*)\)/g, getAddDataToNodeFunctionString('$1', '$2')
5381
performActionFunctionString = "$$ = #{getAddDataToNodeFunctionString(1, patternCount, not returnsLoc)}(#{action});"
5482
else
@@ -396,6 +424,7 @@ grammar =
396424
# A "meta-property" access e.g. `new.target`
397425
MetaProperty: [
398426
o 'NEW_TARGET . Property', -> new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)
427+
o 'IMPORT_META . Property', -> new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)
399428
]
400429

401430
# The general group of accessors into an object, by property, by prototype

src/lexer.coffee

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ exports.Lexer = class Lexer
214214
without parentheses", prev[2]
215215
else if prev[0] is '.' and @tokens.length > 1 and (prevprev = @tokens[@tokens.length - 2])[0] is 'UNARY' and prevprev[1] is 'new'
216216
prevprev[0] = 'NEW_TARGET'
217+
else if prev[0] is '.' and @tokens.length > 1 and (prevprev = @tokens[@tokens.length - 2])[0] is 'IMPORT' and prevprev[1] is 'import'
218+
@seenImport = no
219+
prevprev[0] = 'IMPORT_META'
217220
else if @tokens.length > 2
218221
prevprev = @tokens[@tokens.length - 2]
219222
if prev[0] in ['@', 'THIS'] and prevprev and prevprev.spaced and

src/nodes.coffee

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,9 @@ exports.MetaProperty = class MetaProperty extends Base
15761576
@error "new.target can only occur inside functions"
15771577
else
15781578
@error "the only valid meta property for new is new.target"
1579+
else if @meta.value is 'import'
1580+
unless @property instanceof Access and @property.name.value is 'meta'
1581+
@error "the only valid meta property for import is import.meta"
15791582

15801583
compileNode: (o) ->
15811584
@checkValid o

test/abstract_syntax_tree.coffee

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4041,7 +4041,7 @@ test "AST as expected for If node", ->
40414041
inverted: no
40424042
]
40434043

4044-
test "AST as expected for MetaProperty node", ->
4044+
test "AST as expected for `new.target` MetaProperty node", ->
40454045
testExpression '''
40464046
-> new.target
40474047
''',
@@ -4074,6 +4074,25 @@ test "AST as expected for MetaProperty node", ->
40744074
computed: no
40754075
]
40764076

4077+
test "AST as expected for `import.meta` MetaProperty node", ->
4078+
testExpression '''
4079+
import.meta
4080+
''',
4081+
type: 'MetaProperty'
4082+
meta: ID 'import'
4083+
property: ID 'meta'
4084+
4085+
testExpression '''
4086+
import.meta.name
4087+
''',
4088+
type: 'MemberExpression'
4089+
object:
4090+
type: 'MetaProperty'
4091+
meta: ID 'import'
4092+
property: ID 'meta'
4093+
property: ID 'name'
4094+
computed: no
4095+
40774096
test "AST as expected for dynamic import", ->
40784097
testExpression '''
40794098
import('a')

test/abstract_syntax_tree_location_data.coffee

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6006,7 +6006,7 @@ test "AST as expected for While node", ->
60066006
line: 3
60076007
column: 5
60086008

6009-
test "AST location data as expected for MetaProperty node", ->
6009+
test "AST location data as expected for `new.target` MetaProperty node", ->
60106010
testAstLocationData '''
60116011
-> new.target
60126012
''',
@@ -6058,6 +6058,44 @@ test "AST location data as expected for MetaProperty node", ->
60586058
line: 1
60596059
column: 13
60606060

6061+
test "AST location data as expected for `import.meta` MetaProperty node", ->
6062+
testAstLocationData '''
6063+
import.meta
6064+
''',
6065+
type: 'MetaProperty'
6066+
meta:
6067+
start: 0
6068+
end: 6
6069+
range: [0, 6]
6070+
loc:
6071+
start:
6072+
line: 1
6073+
column: 0
6074+
end:
6075+
line: 1
6076+
column: 6
6077+
property:
6078+
start: 7
6079+
end: 11
6080+
range: [7, 11]
6081+
loc:
6082+
start:
6083+
line: 1
6084+
column: 7
6085+
end:
6086+
line: 1
6087+
column: 11
6088+
start: 0
6089+
end: 11
6090+
range: [0, 11]
6091+
loc:
6092+
start:
6093+
line: 1
6094+
column: 0
6095+
end:
6096+
line: 1
6097+
column: 11
6098+
60616099
test "AST location data as expected for For node", ->
60626100
testAstLocationData 'for x, i in arr when x? then return',
60636101
type: 'For'

0 commit comments

Comments
 (0)