| 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); |
| 50 if (IS_REGEXP(pattern)) { | 51 return IS_REGEXP(o); |
| 51 if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags); | 52 } |
| 52 flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') | |
| 53 + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') | |
| 54 + (REGEXP_MULTILINE(pattern) ? 'm' : '') | |
| 55 + (REGEXP_UNICODE(pattern) ? 'u' : '') | |
| 56 + (REGEXP_STICKY(pattern) ? 'y' : ''); | |
| 57 pattern = REGEXP_SOURCE(pattern); | |
| 58 } | |
| 59 | 53 |
| 54 |
| 55 // ES6 section 21.2.3.2.2 |
| 56 function RegExpInitialize(object, pattern, flags) { |
| 60 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern); | 57 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern); |
| 61 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags); | 58 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags); |
| 59 %RegExpInitializeAndCompile(object, pattern, flags); |
| 60 return object; |
| 61 } |
| 62 | 62 |
| 63 %RegExpInitializeAndCompile(object, pattern, flags); | 63 |
| 64 function PatternFlags(pattern) { |
| 65 return (REGEXP_GLOBAL(pattern) ? 'g' : '') + |
| 66 (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') + |
| 67 (REGEXP_MULTILINE(pattern) ? 'm' : '') + |
| 68 (REGEXP_UNICODE(pattern) ? 'u' : '') + |
| 69 (REGEXP_STICKY(pattern) ? 'y' : ''); |
| 64 } | 70 } |
| 65 | 71 |
| 66 | 72 |
| 67 function RegExpConstructor(pattern, flags) { | 73 function RegExpConstructor(pattern, flags) { |
| 68 if (%_IsConstructCall()) { | 74 var newtarget = new.target; |
| 69 DoConstructRegExp(this, pattern, flags); | 75 var pattern_is_regexp = IsRegExp(pattern); |
| 70 } else { | 76 |
| 71 // RegExp : Called as function; see ECMA-262, section 15.10.3.1. | 77 if (IS_UNDEFINED(newtarget)) { |
| 72 if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) { | 78 newtarget = GlobalRegExp; |
| 79 |
| 80 // ES6 section 21.2.3.1 step 3.b |
| 81 if (pattern_is_regexp && IS_UNDEFINED(flags) && |
| 82 pattern.constructor === newtarget) { |
| 73 return pattern; | 83 return pattern; |
| 74 } | 84 } |
| 75 return new GlobalRegExp(pattern, flags); | |
| 76 } | 85 } |
| 77 } | |
| 78 | 86 |
| 79 // Deprecated RegExp.prototype.compile method. We behave like the constructor | 87 if (IS_REGEXP(pattern)) { |
| 80 // were called again. In SpiderMonkey, this method returns the regexp object. | 88 if (IS_UNDEFINED(flags)) flags = PatternFlags(pattern); |
| 81 // In JSC, it returns undefined. For compatibility with JSC, we match their | 89 pattern = REGEXP_SOURCE(pattern); |
| 82 // behavior. | 90 |
| 83 function RegExpCompileJS(pattern, flags) { | 91 } else if (pattern_is_regexp) { |
| 84 // Both JSC and SpiderMonkey treat a missing pattern argument as the | 92 var input_pattern = pattern; |
| 85 // empty subject string, and an actual undefined value passed as the | 93 pattern = pattern.source; |
| 86 // pattern as the string 'undefined'. Note that JSC is inconsistent | 94 if (IS_UNDEFINED(flags)) flags = input_pattern.flags; |
| 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 } | 95 } |
| 96 if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) { | 96 |
| 97 DoConstructRegExp(this, 'undefined', flags); | 97 var object = %NewObject(GlobalRegExp, newtarget); |
| 98 } else { | 98 return RegExpInitialize(object, pattern, flags); |
| 99 DoConstructRegExp(this, pattern, flags); | |
| 100 } | |
| 101 } | 99 } |
| 102 | 100 |
| 103 | 101 |
| 102 function RegExpCompileJS(pattern, flags) { |
| 103 if (!IS_REGEXP(this)) { |
| 104 throw MakeTypeError(kIncompatibleMethodReceiver, |
| 105 "RegExp.prototype.compile", this); |
| 106 } |
| 107 |
| 108 if (IS_REGEXP(pattern)) { |
| 109 if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags); |
| 110 |
| 111 flags = PatternFlags(pattern); |
| 112 pattern = REGEXP_SOURCE(pattern); |
| 113 } |
| 114 |
| 115 return RegExpInitialize(this, pattern, flags); |
| 116 } |
| 117 |
| 118 |
| 104 function DoRegExpExec(regexp, string, index) { | 119 function DoRegExpExec(regexp, string, index) { |
| 105 var result = %_RegExpExec(regexp, string, index, RegExpLastMatchInfo); | 120 var result = %_RegExpExec(regexp, string, index, RegExpLastMatchInfo); |
| 106 return result; | 121 return result; |
| 107 } | 122 } |
| 108 | 123 |
| 109 | 124 |
| 110 // This is kind of performance sensitive, so we want to avoid unnecessary | 125 // 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 | 126 // type checks on inputs. But we also don't want to inline it several times |
| 112 // manually, so we use a macro :-) | 127 // manually, so we use a macro :-) |
| 113 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING) | 128 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING) |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 // Exports | 532 // Exports |
| 518 | 533 |
| 519 utils.Export(function(to) { | 534 utils.Export(function(to) { |
| 520 to.RegExpExec = DoRegExpExec; | 535 to.RegExpExec = DoRegExpExec; |
| 521 to.RegExpExecNoTests = RegExpExecNoTests; | 536 to.RegExpExecNoTests = RegExpExecNoTests; |
| 522 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 537 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
| 523 to.RegExpTest = RegExpTest; | 538 to.RegExpTest = RegExpTest; |
| 524 }); | 539 }); |
| 525 | 540 |
| 526 }) | 541 }) |
| OLD | NEW |