| 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;
|
| }
|
|
|
|
|