mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
Allow computed class properties (#5206)
* fix broken JS output * static computed properties
This commit is contained in:
committed by
Geoffrey Booth
parent
0574b664e8
commit
71750554c3
@@ -298,6 +298,12 @@
|
||||
function() {
|
||||
return new Value(new ComputedPropertyName($2));
|
||||
}),
|
||||
o('@ [ Expression ]',
|
||||
function() {
|
||||
return new Value(LOC(1)(new ThisLiteral($1)),
|
||||
[LOC(3)(new ComputedPropertyName($3))],
|
||||
'this');
|
||||
}),
|
||||
o('AlphaNumeric')
|
||||
],
|
||||
// Object literal spread properties.
|
||||
|
||||
@@ -2993,7 +2993,7 @@
|
||||
// The class scope is not available yet, so return the assignment to update later
|
||||
assign = this.externalCtor = new Assign(new Value, value);
|
||||
} else if (!assign.variable.this) {
|
||||
name = new (base.shouldCache() ? Index : Access)(base);
|
||||
name = base instanceof ComputedPropertyName ? new Index(base.value) : new (base.shouldCache() ? Index : Access)(base);
|
||||
prototype = new Access(new PropertyName('prototype'));
|
||||
variable = new Value(new ThisLiteral(), [prototype, name]);
|
||||
assign.variable = variable;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -196,16 +196,23 @@
|
||||
// The lexer has tagged the opening bracket of an indexing operation call.
|
||||
// Match it with its paired close.
|
||||
closeOpenIndexes() {
|
||||
var action, condition;
|
||||
var action, condition, startToken;
|
||||
startToken = null;
|
||||
condition = function(token, i) {
|
||||
var ref;
|
||||
return (ref = token[0]) === ']' || ref === 'INDEX_END';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return token[0] = 'INDEX_END';
|
||||
if (this.tokens.length >= i && this.tokens[i + 1][0] === ':') {
|
||||
startToken[0] = '[';
|
||||
return token[0] = ']';
|
||||
} else {
|
||||
return token[0] = 'INDEX_END';
|
||||
}
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'INDEX_START') {
|
||||
startToken = token;
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
@@ -281,7 +288,7 @@
|
||||
stack = [];
|
||||
start = null;
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, inControlFlow, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackItem, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
|
||||
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, inControlFlow, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackItem, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startIndex, startTag, startsLine, tag;
|
||||
[tag] = token;
|
||||
[prevTag] = prevToken = i > 0 ? tokens[i - 1] : [];
|
||||
[nextTag] = nextToken = i < tokens.length - 1 ? tokens[i + 1] : [];
|
||||
@@ -481,7 +488,13 @@
|
||||
var ref1;
|
||||
switch (false) {
|
||||
case ref1 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref1) < 0:
|
||||
return start[1];
|
||||
[startTag, startIndex] = start;
|
||||
if (startTag === '[' && startIndex > 0 && this.tag(startIndex - 1) === '@' && !tokens[startIndex - 1].spaced) {
|
||||
return startIndex - 1;
|
||||
} else {
|
||||
return startIndex;
|
||||
}
|
||||
break;
|
||||
case this.tag(i - 2) !== '@':
|
||||
return i - 2;
|
||||
default:
|
||||
|
||||
@@ -222,6 +222,7 @@ grammar =
|
||||
ObjAssignable: [
|
||||
o 'SimpleObjAssignable'
|
||||
o '[ Expression ]', -> new Value new ComputedPropertyName $2
|
||||
o '@ [ Expression ]', -> new Value LOC(1)(new ThisLiteral $1), [LOC(3)(new ComputedPropertyName($3))], 'this'
|
||||
o 'AlphaNumeric'
|
||||
]
|
||||
|
||||
|
||||
@@ -2007,7 +2007,11 @@ exports.ExecutableClassBody = class ExecutableClassBody extends Base
|
||||
# The class scope is not available yet, so return the assignment to update later
|
||||
assign = @externalCtor = new Assign new Value, value
|
||||
else if not assign.variable.this
|
||||
name = new (if base.shouldCache() then Index else Access) base
|
||||
name =
|
||||
if base instanceof ComputedPropertyName
|
||||
new Index base.value
|
||||
else
|
||||
new (if base.shouldCache() then Index else Access) base
|
||||
prototype = new Access new PropertyName 'prototype'
|
||||
variable = new Value new ThisLiteral(), [ prototype, name ]
|
||||
|
||||
|
||||
@@ -118,14 +118,21 @@ exports.Rewriter = class Rewriter
|
||||
# The lexer has tagged the opening bracket of an indexing operation call.
|
||||
# Match it with its paired close.
|
||||
closeOpenIndexes: ->
|
||||
startToken = null
|
||||
condition = (token, i) ->
|
||||
token[0] in [']', 'INDEX_END']
|
||||
|
||||
action = (token, i) ->
|
||||
token[0] = 'INDEX_END'
|
||||
if @tokens.length >= i and @tokens[i + 1][0] is ':'
|
||||
startToken[0] = '['
|
||||
token[0] = ']'
|
||||
else
|
||||
token[0] = 'INDEX_END'
|
||||
|
||||
@scanTokens (token, i) ->
|
||||
@detectEnd i + 1, condition, action if token[0] is 'INDEX_START'
|
||||
if token[0] is 'INDEX_START'
|
||||
startToken = token
|
||||
@detectEnd i + 1, condition, action
|
||||
1
|
||||
|
||||
# Match tags in token stream starting at `i` with `pattern`.
|
||||
@@ -321,7 +328,12 @@ exports.Rewriter = class Rewriter
|
||||
if tag is ':'
|
||||
# Go back to the (implicit) start of the object.
|
||||
s = switch
|
||||
when @tag(i - 1) in EXPRESSION_END then start[1]
|
||||
when @tag(i - 1) in EXPRESSION_END
|
||||
[startTag, startIndex] = start
|
||||
if startTag is '[' and startIndex > 0 and @tag(startIndex - 1) is '@' and not tokens[startIndex - 1].spaced
|
||||
startIndex - 1
|
||||
else
|
||||
startIndex
|
||||
when @tag(i - 2) is '@' then i - 2
|
||||
else i - 1
|
||||
|
||||
|
||||
@@ -1935,3 +1935,20 @@ test "#5085: Bug: @ reference to class not maintained in do block", ->
|
||||
|
||||
eq thisFoo, 'foo assigned in class'
|
||||
eq thisBar, 'foo assigned in class'
|
||||
|
||||
test "#5204: Computed class property", ->
|
||||
foo = 'bar'
|
||||
class A
|
||||
[foo]: 'baz'
|
||||
a = new A()
|
||||
eq a.bar, 'baz'
|
||||
eq A::bar, 'baz'
|
||||
|
||||
test "#5204: Static computed class property", ->
|
||||
foo = 'bar'
|
||||
qux = 'quux'
|
||||
class A
|
||||
@[foo]: 'baz'
|
||||
@[qux]: -> 3
|
||||
eq A.bar, 'baz'
|
||||
eq A.quux(), 3
|
||||
|
||||
@@ -855,6 +855,13 @@ test "invalid object keys", ->
|
||||
{a=2}
|
||||
^
|
||||
'''
|
||||
assertErrorFormat '''
|
||||
@[a]: 1
|
||||
''', '''
|
||||
[stdin]:1:1: error: invalid object key
|
||||
@[a]: 1
|
||||
^^^^
|
||||
'''
|
||||
|
||||
test "invalid destructuring default target", ->
|
||||
assertErrorFormat '''
|
||||
|
||||
@@ -903,3 +903,6 @@ test "#4579: Postfix for/while/until in first line of implicit object literals",
|
||||
baz: 1337
|
||||
arrayEq [4, 3, 2, 1, 0], six.foo.bar
|
||||
eq 1337, six.foo.baz
|
||||
|
||||
test "#5204: not parsed as static property", ->
|
||||
doesNotThrow -> CoffeeScript.compile "@ [b]: 2"
|
||||
|
||||
Reference in New Issue
Block a user