mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Fix import/export list bug with aliased keywords (#4744)
This commit is contained in:
parent
4d4e47bfb2
commit
063c2d1f56
4 changed files with 58 additions and 31 deletions
|
@ -111,7 +111,7 @@
|
|||
// referenced as property names here, so you can still do `jQuery.is()` even
|
||||
// though `is` means `===` otherwise.
|
||||
identifierToken() {
|
||||
var alias, colon, colonOffset, colonToken, id, idLength, inCSXTag, input, match, poppedToken, prev, prevprev, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, regExSuper, regex, sup, tag, tagToken;
|
||||
var alias, colon, colonOffset, colonToken, id, idLength, inCSXTag, input, match, poppedToken, prev, prevprev, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, regExSuper, regex, sup, tag, tagToken;
|
||||
inCSXTag = this.atCSXTag();
|
||||
regex = inCSXTag ? CSX_ATTRIBUTE : IDENTIFIER;
|
||||
if (!(match = regex.exec(this.chunk))) {
|
||||
|
@ -132,19 +132,28 @@
|
|||
if (id === 'as' && this.seenImport) {
|
||||
if (this.value() === '*') {
|
||||
this.tokens[this.tokens.length - 1][0] = 'IMPORT_ALL';
|
||||
} else if (ref = this.value(), indexOf.call(COFFEE_KEYWORDS, ref) >= 0) {
|
||||
this.tokens[this.tokens.length - 1][0] = 'IDENTIFIER';
|
||||
} else if (ref = this.value(true), indexOf.call(COFFEE_KEYWORDS, ref) >= 0) {
|
||||
prev = this.prev();
|
||||
[prev[0], prev[1]] = ['IDENTIFIER', this.value(true)];
|
||||
}
|
||||
if ((ref1 = this.tag()) === 'DEFAULT' || ref1 === 'IMPORT_ALL' || ref1 === 'IDENTIFIER') {
|
||||
this.token('AS', id);
|
||||
return id.length;
|
||||
}
|
||||
}
|
||||
if (id === 'as' && this.seenExport && ((ref2 = this.tag()) === 'IDENTIFIER' || ref2 === 'DEFAULT')) {
|
||||
this.token('AS', id);
|
||||
return id.length;
|
||||
if (id === 'as' && this.seenExport) {
|
||||
if ((ref2 = this.tag()) === 'IDENTIFIER' || ref2 === 'DEFAULT') {
|
||||
this.token('AS', id);
|
||||
return id.length;
|
||||
}
|
||||
if (ref3 = this.value(true), indexOf.call(COFFEE_KEYWORDS, ref3) >= 0) {
|
||||
prev = this.prev();
|
||||
[prev[0], prev[1]] = ['IDENTIFIER', this.value(true)];
|
||||
this.token('AS', id);
|
||||
return id.length;
|
||||
}
|
||||
}
|
||||
if (id === 'default' && this.seenExport && ((ref3 = this.tag()) === 'EXPORT' || ref3 === 'AS')) {
|
||||
if (id === 'default' && this.seenExport && ((ref4 = this.tag()) === 'EXPORT' || ref4 === 'AS')) {
|
||||
this.token('DEFAULT', id);
|
||||
return id.length;
|
||||
}
|
||||
|
@ -156,10 +165,10 @@
|
|||
return sup.length + 3;
|
||||
}
|
||||
prev = this.prev();
|
||||
tag = colon || (prev != null) && (((ref4 = prev[0]) === '.' || ref4 === '?.' || ref4 === '::' || ref4 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
|
||||
tag = colon || (prev != null) && (((ref5 = prev[0]) === '.' || ref5 === '?.' || ref5 === '::' || ref5 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
|
||||
if (tag === 'IDENTIFIER' && (indexOf.call(JS_KEYWORDS, id) >= 0 || indexOf.call(COFFEE_KEYWORDS, id) >= 0) && !(this.exportSpecifierList && indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
tag = id.toUpperCase();
|
||||
if (tag === 'WHEN' && (ref5 = this.tag(), indexOf.call(LINE_BREAK, ref5) >= 0)) {
|
||||
if (tag === 'WHEN' && (ref6 = this.tag(), indexOf.call(LINE_BREAK, ref6) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
} else if (tag === 'FOR') {
|
||||
this.seenFor = true;
|
||||
|
@ -190,11 +199,11 @@
|
|||
// what CoffeeScript would normally interpret as calls to functions named
|
||||
// `get` or `set`, i.e. `get({foo: function () {}})`.
|
||||
} else if (tag === 'PROPERTY' && prev) {
|
||||
if (prev.spaced && (ref6 = prev[0], indexOf.call(CALLABLE, ref6) >= 0) && /^[gs]et$/.test(prev[1]) && this.tokens[this.tokens.length - 2][0] !== '.') {
|
||||
if (prev.spaced && (ref7 = prev[0], indexOf.call(CALLABLE, ref7) >= 0) && /^[gs]et$/.test(prev[1]) && this.tokens[this.tokens.length - 2][0] !== '.') {
|
||||
this.error(`'${prev[1]}' cannot be used as a keyword, or as a function call without parentheses`, prev[2]);
|
||||
} else {
|
||||
prevprev = this.tokens[this.tokens.length - 2];
|
||||
if (((ref7 = prev[0]) === '@' || ref7 === 'THIS') && prevprev && prevprev.spaced && /^[gs]et$/.test(prevprev[1]) && this.tokens[this.tokens.length - 3][0] !== '.') {
|
||||
if (((ref8 = prev[0]) === '@' || ref8 === 'THIS') && prevprev && prevprev.spaced && /^[gs]et$/.test(prevprev[1]) && this.tokens[this.tokens.length - 3][0] !== '.') {
|
||||
this.error(`'${prevprev[1]}' cannot be used as a keyword, or as a function call without parentheses`, prevprev[2]);
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +213,7 @@
|
|||
length: id.length
|
||||
});
|
||||
}
|
||||
if (tag !== 'PROPERTY') {
|
||||
if (!(tag === 'PROPERTY' || this.exportSpecifierList)) {
|
||||
if (indexOf.call(COFFEE_ALIASES, id) >= 0) {
|
||||
alias = id;
|
||||
id = COFFEE_ALIAS_MAP[id];
|
||||
|
@ -1275,10 +1284,14 @@
|
|||
}
|
||||
|
||||
// Peek at the last value in the token stream.
|
||||
value() {
|
||||
var ref, token;
|
||||
value(useOrigin = false) {
|
||||
var ref, ref1, token;
|
||||
ref = this.tokens, token = ref[ref.length - 1];
|
||||
return token != null ? token[1] : void 0;
|
||||
if (useOrigin && ((token != null ? token.origin : void 0) != null)) {
|
||||
return (ref1 = token.origin) != null ? ref1[1] : void 0;
|
||||
} else {
|
||||
return token != null ? token[1] : void 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the previous token in the token stream.
|
||||
|
|
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "coffeescript",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -116,7 +116,6 @@ exports.Lexer = class Lexer
|
|||
# Preserve length of id for location data
|
||||
idLength = id.length
|
||||
poppedToken = undefined
|
||||
|
||||
if id is 'own' and @tag() is 'FOR'
|
||||
@token 'OWN', id
|
||||
return id.length
|
||||
|
@ -126,14 +125,21 @@ exports.Lexer = class Lexer
|
|||
if id is 'as' and @seenImport
|
||||
if @value() is '*'
|
||||
@tokens[@tokens.length - 1][0] = 'IMPORT_ALL'
|
||||
else if @value() in COFFEE_KEYWORDS
|
||||
@tokens[@tokens.length - 1][0] = 'IDENTIFIER'
|
||||
else if @value(yes) in COFFEE_KEYWORDS
|
||||
prev = @prev()
|
||||
[prev[0], prev[1]] = ['IDENTIFIER', @value(yes)]
|
||||
if @tag() in ['DEFAULT', 'IMPORT_ALL', 'IDENTIFIER']
|
||||
@token 'AS', id
|
||||
return id.length
|
||||
if id is 'as' and @seenExport and @tag() in ['IDENTIFIER', 'DEFAULT']
|
||||
@token 'AS', id
|
||||
return id.length
|
||||
if id is 'as' and @seenExport
|
||||
if @tag() in ['IDENTIFIER', 'DEFAULT']
|
||||
@token 'AS', id
|
||||
return id.length
|
||||
if @value(yes) in COFFEE_KEYWORDS
|
||||
prev = @prev()
|
||||
[prev[0], prev[1]] = ['IDENTIFIER', @value(yes)]
|
||||
@token 'AS', id
|
||||
return id.length
|
||||
if id is 'default' and @seenExport and @tag() in ['EXPORT', 'AS']
|
||||
@token 'DEFAULT', id
|
||||
return id.length
|
||||
|
@ -197,7 +203,7 @@ exports.Lexer = class Lexer
|
|||
if tag is 'IDENTIFIER' and id in RESERVED
|
||||
@error "reserved word '#{id}'", length: id.length
|
||||
|
||||
unless tag is 'PROPERTY'
|
||||
unless tag is 'PROPERTY' or @exportSpecifierList
|
||||
if id in COFFEE_ALIASES
|
||||
alias = id
|
||||
id = COFFEE_ALIAS_MAP[id]
|
||||
|
@ -965,9 +971,12 @@ exports.Lexer = class Lexer
|
|||
token?[0]
|
||||
|
||||
# Peek at the last value in the token stream.
|
||||
value: ->
|
||||
value: (useOrigin = no) ->
|
||||
[..., token] = @tokens
|
||||
token?[1]
|
||||
if useOrigin and token?.origin?
|
||||
token.origin?[1]
|
||||
else
|
||||
token?[1]
|
||||
|
||||
# Get the previous token in the token stream.
|
||||
prev: ->
|
||||
|
|
|
@ -171,6 +171,7 @@ test "multiline simple import", ->
|
|||
bar as baz
|
||||
} from 'lib';"""
|
||||
|
||||
|
||||
test "multiline complex import", ->
|
||||
eqJS """
|
||||
import foo, {
|
||||
|
@ -497,18 +498,21 @@ test "export as aliases members imported from another module", ->
|
|||
} from 'lib';"""
|
||||
|
||||
test "export list can contain CoffeeScript keywords", ->
|
||||
eqJS "export { unless } from 'lib'",
|
||||
eqJS "export { unless, and } from 'lib'",
|
||||
"""
|
||||
export {
|
||||
unless
|
||||
unless,
|
||||
and
|
||||
} from 'lib';"""
|
||||
|
||||
test "export list can contain CoffeeScript keywords when aliasing", ->
|
||||
eqJS "export { when as bar, baz as unless } from 'lib'",
|
||||
eqJS "export { when as bar, baz as unless, and as foo, booze as not } from 'lib'",
|
||||
"""
|
||||
export {
|
||||
when as bar,
|
||||
baz as unless
|
||||
baz as unless,
|
||||
and as foo,
|
||||
booze as not
|
||||
} from 'lib';"""
|
||||
|
||||
|
||||
|
@ -602,11 +606,12 @@ test "`as` can be used as an alias name", ->
|
|||
|
||||
test "CoffeeScript keywords can be used as imported names in import lists", ->
|
||||
eqJS """
|
||||
import { unless as bar } from 'lib'
|
||||
import { unless as bar, and as computedAnd } from 'lib'
|
||||
bar.barMethod()""",
|
||||
"""
|
||||
import {
|
||||
unless as bar
|
||||
unless as bar,
|
||||
and as computedAnd
|
||||
} from 'lib';
|
||||
|
||||
bar.barMethod();"""
|
||||
|
|
Loading…
Reference in a new issue