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 |