Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 (function(global, utils) { | 5 (function(global, utils) { |
| 6 | 6 |
| 7 %CheckIsBootstrapping(); | 7 %CheckIsBootstrapping(); |
| 8 | 8 |
| 9 // ------------------------------------------------------------------- | 9 // ------------------------------------------------------------------- |
| 10 // Imports | 10 // Imports |
| 11 | 11 |
| 12 var FLAG_harmony_tolength; | 12 var FLAG_harmony_tolength; |
| 13 var GlobalObject = global.Object; | 13 var GlobalObject = global.Object; |
| 14 var GlobalRegExp = global.RegExp; | 14 var GlobalRegExp = global.RegExp; |
| 15 var InternalArray = utils.InternalArray; | 15 var InternalArray = utils.InternalArray; |
| 16 var InternalPackedArray = utils.InternalPackedArray; | 16 var InternalPackedArray = utils.InternalPackedArray; |
| 17 var MakeTypeError; | 17 var MakeTypeError; |
| 18 var splitSymbol = utils.ImportNow("split_symbol"); | 18 var splitSymbol = utils.ImportNow("split_symbol"); |
| 19 var matchSymbol = utils.ImportNow("match_symbol");; | |
| 19 | 20 |
| 20 utils.ImportFromExperimental(function(from) { | 21 utils.ImportFromExperimental(function(from) { |
| 21 FLAG_harmony_tolength = from.FLAG_harmony_tolength; | 22 FLAG_harmony_tolength = from.FLAG_harmony_tolength; |
| 22 }); | 23 }); |
| 23 | 24 |
| 24 utils.Import(function(from) { | 25 utils.Import(function(from) { |
| 25 MakeTypeError = from.MakeTypeError; | 26 MakeTypeError = from.MakeTypeError; |
| 26 }); | 27 }); |
| 27 | 28 |
| 28 // ------------------------------------------------------------------- | 29 // ------------------------------------------------------------------- |
| 29 | 30 |
| 30 // Property of the builtins object for recording the result of the last | 31 // Property of the builtins object for recording the result of the last |
| 31 // regexp match. The property RegExpLastMatchInfo includes the matchIndices | 32 // regexp match. The property RegExpLastMatchInfo includes the matchIndices |
| 32 // array of the last successful regexp match (an array of start/end index | 33 // array of the last successful regexp match (an array of start/end index |
| 33 // pairs for the match and all the captured substrings), the invariant is | 34 // pairs for the match and all the captured substrings), the invariant is |
| 34 // that there are at least two capture indeces. The array also contains | 35 // that there are at least two capture indeces. The array also contains |
| 35 // the subject string for the last successful match. | 36 // the subject string for the last successful match. |
| 36 var RegExpLastMatchInfo = new InternalPackedArray( | 37 var RegExpLastMatchInfo = new InternalPackedArray( |
| 37 2, // REGEXP_NUMBER_OF_CAPTURES | 38 2, // REGEXP_NUMBER_OF_CAPTURES |
| 38 "", // Last subject. | 39 "", // Last subject. |
| 39 UNDEFINED, // Last input - settable with RegExpSetInput. | 40 UNDEFINED, // Last input - settable with RegExpSetInput. |
| 40 0, // REGEXP_FIRST_CAPTURE + 0 | 41 0, // REGEXP_FIRST_CAPTURE + 0 |
| 41 0 // REGEXP_FIRST_CAPTURE + 1 | 42 0 // REGEXP_FIRST_CAPTURE + 1 |
| 42 ); | 43 ); |
| 43 | 44 |
| 44 // ------------------------------------------------------------------- | 45 // ------------------------------------------------------------------- |
| 45 | 46 |
| 46 // A recursive descent parser for Patterns according to the grammar of | 47 function IsRegExp(o) { |
| 47 // ECMA-262 15.10.1, with deviations noted below. | 48 if (!IS_OBJECT(o)) return false; |
| 48 function DoConstructRegExp(object, pattern, flags) { | 49 var is_regexp = o[matchSymbol]; |
| 49 // RegExp : Called as constructor; see ECMA-262, section 15.10.4. | 50 if (!IS_UNDEFINED(is_regexp)) return TO_BOOLEAN(is_regexp); |
| 51 return IS_REGEXP(o); | |
| 52 } | |
| 53 | |
| 54 | |
| 55 // ES6 section 21.2.3.2.2 | |
| 56 function RegExpInitialize(object, pattern, flags) { | |
| 57 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern); | |
| 58 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags); | |
| 59 %RegExpInitializeAndCompile(object, pattern, flags); | |
| 60 return object; | |
| 61 } | |
| 62 | |
| 63 | |
| 64 function RegExpConstructor(pattern, flags) { | |
| 65 var newtarget = new.target; | |
| 66 var pattern_is_regexp = IsRegExp(pattern); | |
| 67 | |
| 68 if (IS_UNDEFINED(newtarget)) { | |
| 69 newtarget = GlobalRegExp; | |
| 70 | |
| 71 // ES6 section 21.2.3.1 step 3.b | |
| 72 if (pattern_is_regexp && IS_UNDEFINED(flags) && | |
| 73 pattern.constructor === newtarget) { | |
| 74 return pattern; | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 if (IS_REGEXP(pattern)) { | |
| 79 if (IS_UNDEFINED(flags)) { | |
| 80 flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') | |
|
Igor Sheludko
2015/11/19 09:30:53
We do this kind of thing in three places already,
| |
| 81 + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') | |
| 82 + (REGEXP_MULTILINE(pattern) ? 'm' : '') | |
| 83 + (REGEXP_UNICODE(pattern) ? 'u' : '') | |
| 84 + (REGEXP_STICKY(pattern) ? 'y' : ''); | |
| 85 } | |
| 86 pattern = REGEXP_SOURCE(pattern); | |
| 87 | |
| 88 } else if (pattern_is_regexp) { | |
| 89 var input_pattern = pattern; | |
| 90 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
| |
| 91 if (IS_UNDEFINED(flags)) flags = input_pattern.flags; | |
| 92 } | |
| 93 | |
| 94 var object = %NewObject(GlobalRegExp, newtarget); | |
| 95 return RegExpInitialize(object, pattern, flags); | |
| 96 } | |
| 97 | |
| 98 | |
| 99 function RegExpCompileJS(pattern, flags) { | |
| 100 if (!IS_REGEXP(this)) { | |
| 101 throw MakeTypeError(kIncompatibleMethodReceiver, | |
| 102 "RegExp.prototype.compile", this); | |
| 103 } | |
| 104 | |
| 50 if (IS_REGEXP(pattern)) { | 105 if (IS_REGEXP(pattern)) { |
| 51 if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags); | 106 if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags); |
| 107 | |
| 52 flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') | 108 flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') |
| 53 + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') | 109 + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') |
| 54 + (REGEXP_MULTILINE(pattern) ? 'm' : '') | 110 + (REGEXP_MULTILINE(pattern) ? 'm' : '') |
| 55 + (REGEXP_UNICODE(pattern) ? 'u' : '') | 111 + (REGEXP_UNICODE(pattern) ? 'u' : '') |
| 56 + (REGEXP_STICKY(pattern) ? 'y' : ''); | 112 + (REGEXP_STICKY(pattern) ? 'y' : ''); |
| 57 pattern = REGEXP_SOURCE(pattern); | 113 pattern = REGEXP_SOURCE(pattern); |
| 58 } | 114 } |
| 59 | 115 |
| 60 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern); | 116 return RegExpInitialize(this, pattern, flags); |
| 61 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags); | |
| 62 | |
| 63 %RegExpInitializeAndCompile(object, pattern, flags); | |
| 64 } | 117 } |
| 65 | 118 |
| 66 | 119 |
| 67 function RegExpConstructor(pattern, flags) { | |
| 68 if (%_IsConstructCall()) { | |
| 69 DoConstructRegExp(this, pattern, flags); | |
| 70 } else { | |
| 71 // RegExp : Called as function; see ECMA-262, section 15.10.3.1. | |
| 72 if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) { | |
| 73 return pattern; | |
| 74 } | |
| 75 return new GlobalRegExp(pattern, flags); | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 // Deprecated RegExp.prototype.compile method. We behave like the constructor | |
| 80 // were called again. In SpiderMonkey, this method returns the regexp object. | |
| 81 // In JSC, it returns undefined. For compatibility with JSC, we match their | |
| 82 // behavior. | |
| 83 function RegExpCompileJS(pattern, flags) { | |
| 84 // Both JSC and SpiderMonkey treat a missing pattern argument as the | |
| 85 // empty subject string, and an actual undefined value passed as the | |
| 86 // pattern as the string 'undefined'. Note that JSC is inconsistent | |
| 87 // here, treating undefined values differently in | |
| 88 // RegExp.prototype.compile and in the constructor, where they are | |
| 89 // the empty string. For compatibility with JSC, we match their | |
| 90 // behavior. | |
| 91 if (this == GlobalRegExp.prototype) { | |
| 92 // We don't allow recompiling RegExp.prototype. | |
| 93 throw MakeTypeError(kIncompatibleMethodReceiver, | |
| 94 'RegExp.prototype.compile', this); | |
| 95 } | |
| 96 if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) { | |
| 97 DoConstructRegExp(this, 'undefined', flags); | |
| 98 } else { | |
| 99 DoConstructRegExp(this, pattern, flags); | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 | |
| 104 function DoRegExpExec(regexp, string, index) { | 120 function DoRegExpExec(regexp, string, index) { |
| 105 var result = %_RegExpExec(regexp, string, index, RegExpLastMatchInfo); | 121 var result = %_RegExpExec(regexp, string, index, RegExpLastMatchInfo); |
| 106 return result; | 122 return result; |
| 107 } | 123 } |
| 108 | 124 |
| 109 | 125 |
| 110 // This is kind of performance sensitive, so we want to avoid unnecessary | 126 // This is kind of performance sensitive, so we want to avoid unnecessary |
| 111 // type checks on inputs. But we also don't want to inline it several times | 127 // type checks on inputs. But we also don't want to inline it several times |
| 112 // manually, so we use a macro :-) | 128 // manually, so we use a macro :-) |
| 113 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING) | 129 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING) |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 // Exports | 533 // Exports |
| 518 | 534 |
| 519 utils.Export(function(to) { | 535 utils.Export(function(to) { |
| 520 to.RegExpExec = DoRegExpExec; | 536 to.RegExpExec = DoRegExpExec; |
| 521 to.RegExpExecNoTests = RegExpExecNoTests; | 537 to.RegExpExecNoTests = RegExpExecNoTests; |
| 522 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 538 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
| 523 to.RegExpTest = RegExpTest; | 539 to.RegExpTest = RegExpTest; |
| 524 }); | 540 }); |
| 525 | 541 |
| 526 }) | 542 }) |
| OLD | NEW |