Skip to content

Commit 7175055

Browse files
helixbassGeoffreyBooth
authored andcommitted
Allow computed class properties (#5206)
* fix broken JS output * static computed properties
1 parent 0574b66 commit 7175055

File tree

10 files changed

+256
-188
lines changed

10 files changed

+256
-188
lines changed

lib/coffeescript/grammar.js

Lines changed: 6 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: 1 addition & 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: 184 additions & 179 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/coffeescript/rewriter.js

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

src/grammar.coffee

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ grammar =
222222
ObjAssignable: [
223223
o 'SimpleObjAssignable'
224224
o '[ Expression ]', -> new Value new ComputedPropertyName $2
225+
o '@ [ Expression ]', -> new Value LOC(1)(new ThisLiteral $1), [LOC(3)(new ComputedPropertyName($3))], 'this'
225226
o 'AlphaNumeric'
226227
]
227228

src/nodes.coffee

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2007,7 +2007,11 @@ exports.ExecutableClassBody = class ExecutableClassBody extends Base
20072007
# The class scope is not available yet, so return the assignment to update later
20082008
assign = @externalCtor = new Assign new Value, value
20092009
else if not assign.variable.this
2010-
name = new (if base.shouldCache() then Index else Access) base
2010+
name =
2011+
if base instanceof ComputedPropertyName
2012+
new Index base.value
2013+
else
2014+
new (if base.shouldCache() then Index else Access) base
20112015
prototype = new Access new PropertyName 'prototype'
20122016
variable = new Value new ThisLiteral(), [ prototype, name ]
20132017

src/rewriter.coffee

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,21 @@ exports.Rewriter = class Rewriter
118118
# The lexer has tagged the opening bracket of an indexing operation call.
119119
# Match it with its paired close.
120120
closeOpenIndexes: ->
121+
startToken = null
121122
condition = (token, i) ->
122123
token[0] in [']', 'INDEX_END']
123124

124125
action = (token, i) ->
125-
token[0] = 'INDEX_END'
126+
if @tokens.length >= i and @tokens[i + 1][0] is ':'
127+
startToken[0] = '['
128+
token[0] = ']'
129+
else
130+
token[0] = 'INDEX_END'
126131

127132
@scanTokens (token, i) ->
128-
@detectEnd i + 1, condition, action if token[0] is 'INDEX_START'
133+
if token[0] is 'INDEX_START'
134+
startToken = token
135+
@detectEnd i + 1, condition, action
129136
1
130137

131138
# Match tags in token stream starting at `i` with `pattern`.
@@ -321,7 +328,12 @@ exports.Rewriter = class Rewriter
321328
if tag is ':'
322329
# Go back to the (implicit) start of the object.
323330
s = switch
324-
when @tag(i - 1) in EXPRESSION_END then start[1]
331+
when @tag(i - 1) in EXPRESSION_END
332+
[startTag, startIndex] = start
333+
if startTag is '[' and startIndex > 0 and @tag(startIndex - 1) is '@' and not tokens[startIndex - 1].spaced
334+
startIndex - 1
335+
else
336+
startIndex
325337
when @tag(i - 2) is '@' then i - 2
326338
else i - 1
327339

test/classes.coffee

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,3 +1935,20 @@ test "#5085: Bug: @ reference to class not maintained in do block", ->
19351935

19361936
eq thisFoo, 'foo assigned in class'
19371937
eq thisBar, 'foo assigned in class'
1938+
1939+
test "#5204: Computed class property", ->
1940+
foo = 'bar'
1941+
class A
1942+
[foo]: 'baz'
1943+
a = new A()
1944+
eq a.bar, 'baz'
1945+
eq A::bar, 'baz'
1946+
1947+
test "#5204: Static computed class property", ->
1948+
foo = 'bar'
1949+
qux = 'quux'
1950+
class A
1951+
@[foo]: 'baz'
1952+
@[qux]: -> 3
1953+
eq A.bar, 'baz'
1954+
eq A.quux(), 3

test/error_messages.coffee

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,13 @@ test "invalid object keys", ->
855855
{a=2}
856856
^
857857
'''
858+
assertErrorFormat '''
859+
@[a]: 1
860+
''', '''
861+
[stdin]:1:1: error: invalid object key
862+
@[a]: 1
863+
^^^^
864+
'''
858865

859866
test "invalid destructuring default target", ->
860867
assertErrorFormat '''

test/objects.coffee

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,3 +903,6 @@ test "#4579: Postfix for/while/until in first line of implicit object literals",
903903
baz: 1337
904904
arrayEq [4, 3, 2, 1, 0], six.foo.bar
905905
eq 1337, six.foo.baz
906+
907+
test "#5204: not parsed as static property", ->
908+
doesNotThrow -> CoffeeScript.compile "@ [b]: 2"

0 commit comments

Comments
 (0)