Index: src/regexp.js |
diff --git a/src/regexp.js b/src/regexp.js |
index d8e3ea49bec7e236a0d7dc1dcf4a624b460679eb..0f3dbb630e867bb8f4d635f0ddeda9cb3a229471 100644 |
--- a/src/regexp.js |
+++ b/src/regexp.js |
@@ -22,6 +22,8 @@ function DoConstructRegExp(object, pattern, flags) { |
flags = (pattern.global ? 'g' : '') |
+ (pattern.ignoreCase ? 'i' : '') |
+ (pattern.multiline ? 'm' : ''); |
+ if (harmony_regexps) |
+ flags += (pattern.sticky ? 'y' : ''); |
pattern = pattern.source; |
} |
@@ -31,6 +33,7 @@ function DoConstructRegExp(object, pattern, flags) { |
var global = false; |
var ignoreCase = false; |
var multiline = false; |
+ var sticky = false; |
for (var i = 0; i < flags.length; i++) { |
var c = %_CallFunction(flags, i, StringCharAt); |
switch (c) { |
@@ -52,12 +55,18 @@ function DoConstructRegExp(object, pattern, flags) { |
} |
multiline = true; |
break; |
+ case 'y': |
+ if (!harmony_regexps || sticky) { |
+ throw MakeSyntaxError("invalid_regexp_flags", [flags]); |
+ } |
+ sticky = true; |
+ break; |
default: |
throw MakeSyntaxError("invalid_regexp_flags", [flags]); |
} |
} |
- %RegExpInitializeObject(object, pattern, global, ignoreCase, multiline); |
+ %RegExpInitializeObject(object, pattern, global, ignoreCase, multiline, sticky); |
// Call internal function to compile the pattern. |
%RegExpCompile(object, pattern, flags); |
@@ -159,8 +168,8 @@ function RegExpExec(string) { |
// algorithm, step 5) even if the value is discarded for non-global RegExps. |
var i = TO_INTEGER(lastIndex); |
- var global = this.global; |
- if (global) { |
+ var updateLastIndex = this.global || (harmony_regexps && this.sticky); |
+ if (updateLastIndex) { |
if (i < 0 || i > string.length) { |
this.lastIndex = 0; |
return null; |
@@ -179,7 +188,7 @@ function RegExpExec(string) { |
// Successful match. |
lastMatchInfoOverride = null; |
- if (global) { |
+ if (updateLastIndex) { |
this.lastIndex = lastMatchInfo[CAPTURE1]; |
} |
RETURN_NEW_RESULT_FROM_MATCH_INFO(matchIndices, string); |
@@ -207,7 +216,7 @@ function RegExpTest(string) { |
// algorithm, step 5) even if the value is discarded for non-global RegExps. |
var i = TO_INTEGER(lastIndex); |
- if (this.global) { |
+ if (this.global || (harmony_regexps && this.sticky)) { |
if (i < 0 || i > string.length) { |
this.lastIndex = 0; |
return false; |
@@ -222,12 +231,13 @@ function RegExpTest(string) { |
this.lastIndex = lastMatchInfo[CAPTURE1]; |
return true; |
} else { |
- // Non-global regexp. |
- // Remove irrelevant preceeding '.*' in a non-global test regexp. |
- // The expression checks whether this.source starts with '.*' and |
- // that the third char is not a '?'. |
+ // Non-global, non-sticky regexp. |
+ // Remove irrelevant preceeding '.*' in a test regexp. The expression |
+ // checks whether this.source starts with '.*' and that the third char is |
+ // not a '?'. But see https://code.google.com/p/v8/issues/detail?id=3560 |
var regexp = this; |
- if (%_StringCharCodeAt(regexp.source, 0) == 46 && // '.' |
+ if (regexp.source.length >= 3 && |
+ %_StringCharCodeAt(regexp.source, 0) == 46 && // '.' |
%_StringCharCodeAt(regexp.source, 1) == 42 && // '*' |
%_StringCharCodeAt(regexp.source, 2) != 63) { // '?' |
regexp = TrimRegExp(regexp); |
@@ -264,6 +274,7 @@ function RegExpToString() { |
if (this.global) result += 'g'; |
if (this.ignoreCase) result += 'i'; |
if (this.multiline) result += 'm'; |
+ if (harmony_regexps && this.sticky) result += 'y'; |
return result; |
} |