Make regexes always uncallable

No matter if they have interpolations or not.
This commit is contained in:
Simon Lydell 2015-01-15 19:44:14 +01:00
parent fce502ac98
commit 3db029f2c1
6 changed files with 42 additions and 11 deletions

View File

@ -288,7 +288,7 @@
};
Lexer.prototype.regexToken = function() {
var closed, end, flags, index, match, prev, re, regex, tokens, _ref2, _ref3, _ref4;
var closed, end, flags, index, match, prev, re, regex, rparen, tokens, _ref2, _ref3, _ref4;
switch (false) {
case !(match = REGEX_ILLEGAL.exec(this.chunk)):
this.error("regular expressions cannot begin with " + match[2], match.index + match[1].length);
@ -301,7 +301,7 @@
index = regex.length;
prev = last(this.tokens);
if (prev) {
if (prev.spaced && (_ref3 = prev[0], __indexOf.call(CALLABLE, _ref3) >= 0) && !prev.stringEnd) {
if (prev.spaced && (_ref3 = prev[0], __indexOf.call(CALLABLE, _ref3) >= 0) && !prev.stringEnd && !prev.regexEnd) {
if (!closed || POSSIBLY_DIVISION.test(regex)) {
return 0;
}
@ -345,7 +345,8 @@
this.token(',', ',', index, 0);
this.token('STRING', '"' + flags + '"', index, flags.length);
}
this.token(')', ')', end, 0);
rparen = this.token(')', ')', end, 0);
rparen.regexEnd = true;
}
return end;
};
@ -505,7 +506,7 @@
} else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
tag = 'LOGIC';
} else if (prev && !prev.spaced) {
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0) && !prev.stringEnd) {
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0) && !prev.stringEnd && !prev.regexEnd) {
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}

View File

@ -257,14 +257,14 @@
}
stack.pop();
}
if ((__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced && !token.stringEnd || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (__indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || __indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((_ref = tokens[i + 1]) != null ? _ref.spaced : void 0) && !((_ref1 = tokens[i + 1]) != null ? _ref1.newLine : void 0))) {
if ((__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced && !token.stringEnd && !token.regexEnd || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (__indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || __indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((_ref = tokens[i + 1]) != null ? _ref.spaced : void 0) && !((_ref1 = tokens[i + 1]) != null ? _ref1.newLine : void 0))) {
if (tag === '?') {
tag = token[0] = 'FUNC_EXIST';
}
startImplicitCall(i + 1);
return forward(2);
}
if (__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && !token.stringEnd && this.matchTags(i + 1, 'INDENT', null, ':') && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
if (__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && !token.stringEnd && !token.regexEnd && this.matchTags(i + 1, 'INDENT', null, ':') && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
startImplicitCall(i + 1);
stack.push(['INDENT', i + 2]);
return forward(3);

View File

@ -263,7 +263,7 @@ exports.Lexer = class Lexer
index = regex.length
prev = last @tokens
if prev
if prev.spaced and prev[0] in CALLABLE and not prev.stringEnd
if prev.spaced and prev[0] in CALLABLE and not prev.stringEnd and not prev.regexEnd
return 0 if not closed or POSSIBLY_DIVISION.test regex
else if prev[0] in NOT_REGEX
return 0
@ -289,7 +289,8 @@ exports.Lexer = class Lexer
if flags
@token ',', ',', index, 0
@token 'STRING', '"' + flags + '"', index, flags.length
@token ')', ')', end, 0
rparen = @token ')', ')', end, 0
rparen.regexEnd = true
end
@ -417,7 +418,7 @@ exports.Lexer = class Lexer
else if value in SHIFT then tag = 'SHIFT'
else if value in LOGIC or value is '?' and prev?.spaced then tag = 'LOGIC'
else if prev and not prev.spaced
if value is '(' and prev[0] in CALLABLE and not prev.stringEnd
if value is '(' and prev[0] in CALLABLE and not prev.stringEnd and not prev.regexEnd
prev[0] = 'FUNC_EXIST' if prev[0] is '?'
tag = 'CALL_START'
else if value is '[' and prev[0] in INDEXABLE

View File

@ -209,7 +209,7 @@ class exports.Rewriter
# Recognize standard implicit calls like
# f a, f() b, f? c, h[0] d etc.
if (tag in IMPLICIT_FUNC and token.spaced and not token.stringEnd or
if (tag in IMPLICIT_FUNC and token.spaced and not token.stringEnd and not token.regexEnd or
tag is '?' and i > 0 and not tokens[i - 1].spaced) and
(nextTag in IMPLICIT_CALL or
nextTag in IMPLICIT_UNSPACED_CALL and
@ -243,7 +243,7 @@ class exports.Rewriter
# which is probably always unintended.
# Furthermore don't allow this in literal arrays, as
# that creates grammatical ambiguities.
if tag in IMPLICIT_FUNC and not token.stringEnd and
if tag in IMPLICIT_FUNC and not token.stringEnd and not token.regexEnd and
@matchTags(i + 1, 'INDENT', null, ':') and
not @findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH',
'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])

View File

@ -91,3 +91,19 @@ test "#3194: string interpolation in array", ->
eq 2, arr.length
eq 'ab', arr[0]
eq 'value', arr[1].key
test "regex interpolation in array", ->
arr = [ /a/
key: 'value'
]
eq 2, arr.length
eq 'a', arr[0].source
eq 'value', arr[1].key
b = 'b'
arr = [ ///a#{b}///
key: 'value'
]
eq 2, arr.length
eq 'ab', arr[0].source
eq 'value', arr[1].key

View File

@ -252,3 +252,16 @@ test '#2388: `///` in heregex interpolations', ->
scan = (regex) -> regex.exec('\t foo')[0]
eq '/\t /', /// #{scan /// [#{ws}]* ///} /// + ''
test "regexes are not callable", ->
throws -> CoffeeScript.compile '/a/()'
throws -> CoffeeScript.compile '///a#{b}///()'
throws -> CoffeeScript.compile '/a/ 1'
throws -> CoffeeScript.compile '///a#{b}/// 1'
throws -> CoffeeScript.compile '''
/a/
k: v
'''
throws -> CoffeeScript.compile '''
///a#{b}///
k: v
'''