Chromium Code Reviews| Index: src/js/regexp.js |
| diff --git a/src/js/regexp.js b/src/js/regexp.js |
| index 55466dc03dd3a1e323d263e8473ea0c2023474cd..e96c6966f484475aeb9dfb96ae2159078e382f28 100644 |
| --- a/src/js/regexp.js |
| +++ b/src/js/regexp.js |
| @@ -16,6 +16,7 @@ var InternalArray = utils.InternalArray; |
| var InternalPackedArray = utils.InternalPackedArray; |
| var MakeTypeError; |
| var splitSymbol = utils.ImportNow("split_symbol"); |
| +var matchSymbol = utils.ImportNow("match_symbol");; |
| utils.ImportFromExperimental(function(from) { |
| FLAG_harmony_tolength = from.FLAG_harmony_tolength; |
| @@ -43,61 +44,76 @@ var RegExpLastMatchInfo = new InternalPackedArray( |
| // ------------------------------------------------------------------- |
| -// A recursive descent parser for Patterns according to the grammar of |
| -// ECMA-262 15.10.1, with deviations noted below. |
| -function DoConstructRegExp(object, pattern, flags) { |
| - // RegExp : Called as constructor; see ECMA-262, section 15.10.4. |
| - if (IS_REGEXP(pattern)) { |
| - if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags); |
| - flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') |
| - + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') |
| - + (REGEXP_MULTILINE(pattern) ? 'm' : '') |
| - + (REGEXP_UNICODE(pattern) ? 'u' : '') |
| - + (REGEXP_STICKY(pattern) ? 'y' : ''); |
| - pattern = REGEXP_SOURCE(pattern); |
| - } |
| +function IsRegExp(o) { |
| + if (!IS_OBJECT(o)) return false; |
| + var is_regexp = o[matchSymbol]; |
| + if (!IS_UNDEFINED(is_regexp)) return TO_BOOLEAN(is_regexp); |
| + return IS_REGEXP(o); |
| +} |
| + |
| +// ES6 section 21.2.3.2.2 |
| +function RegExpInitialize(object, pattern, flags) { |
| pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern); |
| flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags); |
| - |
| %RegExpInitializeAndCompile(object, pattern, flags); |
| + return object; |
| } |
| function RegExpConstructor(pattern, flags) { |
| - if (%_IsConstructCall()) { |
| - DoConstructRegExp(this, pattern, flags); |
| - } else { |
| - // RegExp : Called as function; see ECMA-262, section 15.10.3.1. |
| - if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) { |
| + var newtarget = new.target; |
| + var pattern_is_regexp = IsRegExp(pattern); |
| + |
| + if (IS_UNDEFINED(newtarget)) { |
| + newtarget = GlobalRegExp; |
| + |
| + // ES6 section 21.2.3.1 step 3.b |
| + if (pattern_is_regexp && IS_UNDEFINED(flags) && |
| + pattern.constructor === newtarget) { |
| return pattern; |
| } |
| - return new GlobalRegExp(pattern, flags); |
| } |
| + |
| + if (IS_REGEXP(pattern)) { |
| + if (IS_UNDEFINED(flags)) { |
| + flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') |
|
Igor Sheludko
2015/11/19 09:30:53
We do this kind of thing in three places already,
|
| + + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') |
| + + (REGEXP_MULTILINE(pattern) ? 'm' : '') |
| + + (REGEXP_UNICODE(pattern) ? 'u' : '') |
| + + (REGEXP_STICKY(pattern) ? 'y' : ''); |
| + } |
| + pattern = REGEXP_SOURCE(pattern); |
| + |
| + } else if (pattern_is_regexp) { |
| + var input_pattern = pattern; |
| + pattern = pattern.source; |
|
Igor Sheludko
2015/11/19 09:30:53
Shouldn't this be a REGEXP_SOURCE(pattern) instead
Toon Verwaest
2015/11/19 09:39:53
We actually have to do Get(..."source") and "flags
|
| + if (IS_UNDEFINED(flags)) flags = input_pattern.flags; |
| + } |
| + |
| + var object = %NewObject(GlobalRegExp, newtarget); |
| + return RegExpInitialize(object, pattern, flags); |
| } |
| -// Deprecated RegExp.prototype.compile method. We behave like the constructor |
| -// were called again. In SpiderMonkey, this method returns the regexp object. |
| -// In JSC, it returns undefined. For compatibility with JSC, we match their |
| -// behavior. |
| + |
| function RegExpCompileJS(pattern, flags) { |
| - // Both JSC and SpiderMonkey treat a missing pattern argument as the |
| - // empty subject string, and an actual undefined value passed as the |
| - // pattern as the string 'undefined'. Note that JSC is inconsistent |
| - // here, treating undefined values differently in |
| - // RegExp.prototype.compile and in the constructor, where they are |
| - // the empty string. For compatibility with JSC, we match their |
| - // behavior. |
| - if (this == GlobalRegExp.prototype) { |
| - // We don't allow recompiling RegExp.prototype. |
| + if (!IS_REGEXP(this)) { |
| throw MakeTypeError(kIncompatibleMethodReceiver, |
| - 'RegExp.prototype.compile', this); |
| + "RegExp.prototype.compile", this); |
| } |
| - if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) { |
| - DoConstructRegExp(this, 'undefined', flags); |
| - } else { |
| - DoConstructRegExp(this, pattern, flags); |
| + |
| + if (IS_REGEXP(pattern)) { |
| + if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags); |
| + |
| + flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') |
| + + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') |
| + + (REGEXP_MULTILINE(pattern) ? 'm' : '') |
| + + (REGEXP_UNICODE(pattern) ? 'u' : '') |
| + + (REGEXP_STICKY(pattern) ? 'y' : ''); |
| + pattern = REGEXP_SOURCE(pattern); |
| } |
| + |
| + return RegExpInitialize(this, pattern, flags); |
| } |