Escaped whitespace and slashes in Heregexes

* Resolves #3059: Don't remove escaped whitespace.
* Fixes #2238: Prevent escaping slashes that are already escaped.
* Fix detection of end of heregex with escaped slashes.
This commit is contained in:
Marc Häfner 2013-10-21 21:52:36 +02:00
parent c22707cd53
commit 91ac3fa031
3 changed files with 23 additions and 8 deletions

View File

@ -275,7 +275,7 @@
var body, flags, flagsOffset, heregex, plusToken, prev, re, tag, token, tokens, value, _i, _len, _ref2, _ref3, _ref4;
heregex = match[0], body = match[1], flags = match[2];
if (0 > body.indexOf('#{')) {
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
re = body.replace(HEREGEX_OMIT, '$1$2').replace(/\//g, '\\/');
if (re.match(/^\*/)) {
this.error('regular expressions cannot begin with `*`');
}
@ -294,7 +294,7 @@
if (tag === 'TOKENS') {
tokens.push.apply(tokens, value);
} else if (tag === 'NEOSTRING') {
if (!(value = value.replace(HEREGEX_OMIT, ''))) {
if (!(value = value.replace(HEREGEX_OMIT, '$1$2'))) {
continue;
}
value = value.replace(/\\/g, '\\\\');
@ -858,9 +858,9 @@
REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/;
HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
HEREGEX = /^\/{3}((?:\\?[\s\S])+?)\/{3}([imgy]{0,4})(?!\w)/;
HEREGEX_OMIT = /\s+(?:#.*)?/g;
HEREGEX_OMIT = /((?:\\\\)+)|\\([^\n\S]|\/)|\s+(?:#.*)?/g;
MULTILINER = /\n/g;

View File

@ -255,7 +255,7 @@ exports.Lexer = class Lexer
heregexToken: (match) ->
[heregex, body, flags] = match
if 0 > body.indexOf '#{'
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/')
re = body.replace(HEREGEX_OMIT, '$1$2').replace(/\//g, '\\/')
if re.match /^\*/ then @error 'regular expressions cannot begin with `*`'
@token 'REGEX', "/#{ re or '(?:)' }/#{flags}", 0, heregex.length
return heregex.length
@ -267,7 +267,7 @@ exports.Lexer = class Lexer
if tag is 'TOKENS'
tokens.push value...
else if tag is 'NEOSTRING'
continue unless value = value.replace HEREGEX_OMIT, ''
continue unless value = value.replace HEREGEX_OMIT, '$1$2'
# Convert NEOSTRING into STRING
value = value.replace /\\/g, '\\\\'
token[0] = 'STRING'
@ -806,9 +806,13 @@ REGEX = /// ^
/) ([imgy]{0,4}) (?!\w)
///
HEREGEX = /// ^ /{3} ([\s\S]+?) /{3} ([imgy]{0,4}) (?!\w) ///
HEREGEX = /// ^ /{3} ((?:\\?[\s\S])+?) /{3} ([imgy]{0,4}) (?!\w) ///
HEREGEX_OMIT = /\s+(?:#.*)?/g
HEREGEX_OMIT = ///
((?:\\\\)+) # consume (and preserve) an even number of backslashes
| \\([^\n\S]|/) # preserve escaped spaces and "de-escape" slashes
| \s+(?:#.*)? # remove whitespace and comments
///g
# Token cleaning regexes.
MULTILINER = /\n/g

View File

@ -61,3 +61,14 @@ test "empty regular expressions with flags", ->
a = "" + //i
fn ""
eq '/(?:)/i', a
test "#3059: don't remove escaped whitespace", ->
eq /// One\ cannot [\ ] escape \ \destiny. ///.source,
/One cannot[ ]escape \destiny./.source
test "#2238: don't escape already escaped slashes", ->
eq /// \\\/ \/ ///.source, /\\\/\//.source
test "escaped slashes don't close heregex", ->
eq /// \/// ///.source, /\/\/\//.source
eq /// \\\////.source, /\\\//.source