Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: src/js/regexp.js

Issue 2307863003: [regexp] Port RegExpMatch, RegExpSearch, and RegExpTest (Closed)
Patch Set: Rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap-symbols.h ('k') | src/objects.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 ExpandReplacement; 12 var ExpandReplacement;
13 var GlobalArray = global.Array; 13 var GlobalArray = global.Array;
14 var GlobalObject = global.Object; 14 var GlobalObject = global.Object;
15 var GlobalRegExp = global.RegExp; 15 var GlobalRegExp = global.RegExp;
16 var InternalArray = utils.InternalArray; 16 var InternalArray = utils.InternalArray;
17 var InternalPackedArray = utils.InternalPackedArray; 17 var InternalPackedArray = utils.InternalPackedArray;
18 var MaxSimple; 18 var MaxSimple;
19 var MinSimple; 19 var MinSimple;
20 var lastMatchInfoSymbol = utils.ImportNow("regexp_last_match_info_symbol"); 20 var lastMatchInfoSymbol = utils.ImportNow("regexp_last_match_info_symbol");
21 var matchSymbol = utils.ImportNow("match_symbol"); 21 var matchSymbol = utils.ImportNow("match_symbol");
22 var replaceSymbol = utils.ImportNow("replace_symbol"); 22 var replaceSymbol = utils.ImportNow("replace_symbol");
23 var searchSymbol = utils.ImportNow("search_symbol"); 23 var searchSymbol = utils.ImportNow("search_symbol");
24 var speciesSymbol = utils.ImportNow("species_symbol"); 24 var speciesSymbol = utils.ImportNow("species_symbol");
25 var splitSymbol = utils.ImportNow("split_symbol"); 25 var splitSymbol = utils.ImportNow("split_symbol");
26 var SpeciesConstructor; 26 var SpeciesConstructor;
27 var RegExpSubclassExecJS;
27 28
28 utils.Import(function(from) { 29 utils.Import(function(from) {
29 ExpandReplacement = from.ExpandReplacement; 30 ExpandReplacement = from.ExpandReplacement;
30 MaxSimple = from.MaxSimple; 31 MaxSimple = from.MaxSimple;
31 MinSimple = from.MinSimple; 32 MinSimple = from.MinSimple;
32 SpeciesConstructor = from.SpeciesConstructor; 33 SpeciesConstructor = from.SpeciesConstructor;
33 }); 34 });
34 35
35 // ------------------------------------------------------------------- 36 // -------------------------------------------------------------------
36 37
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 if (start != -1) { 96 if (start != -1) {
96 end = MATCHINFO[j]; 97 end = MATCHINFO[j];
97 result[i] = %_SubString(STRING, start, end); 98 result[i] = %_SubString(STRING, start, end);
98 } 99 }
99 j++; 100 j++;
100 } 101 }
101 return result; 102 return result;
102 endmacro 103 endmacro
103 104
104 105
105 function RegExpExecNoTests(regexp, string, start) {
106 // Must be called with RegExp, string and positive integer as arguments.
107 var matchInfo = %_RegExpExec(regexp, string, start, RegExpLastMatchInfo);
108 if (matchInfo !== null) {
109 // ES6 21.2.5.2.2 step 18.
110 if (REGEXP_STICKY(regexp)) regexp.lastIndex = matchInfo[CAPTURE1];
111 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, string);
112 }
113 regexp.lastIndex = 0;
114 return null;
115 }
116
117
118 // ES#sec-regexp.prototype.exec
119 // RegExp.prototype.exec ( string )
120 function RegExpSubclassExecJS(string) {
121 if (!IS_REGEXP(this)) {
122 throw %make_type_error(kIncompatibleMethodReceiver,
123 'RegExp.prototype.exec', this);
124 }
125
126 string = TO_STRING(string);
127 var lastIndex = this.lastIndex;
128
129 // Conversion is required by the ES2015 specification (RegExpBuiltinExec
130 // algorithm, step 4) even if the value is discarded for non-global RegExps.
131 var i = TO_LENGTH(lastIndex);
132
133 var global = TO_BOOLEAN(REGEXP_GLOBAL(this));
134 var sticky = TO_BOOLEAN(REGEXP_STICKY(this));
135 var updateLastIndex = global || sticky;
136 if (updateLastIndex) {
137 if (i > string.length) {
138 this.lastIndex = 0;
139 return null;
140 }
141 } else {
142 i = 0;
143 }
144
145 // matchIndices is either null or the RegExpLastMatchInfo array.
146 // TODO(littledan): Whether a RegExp is sticky is compiled into the RegExp
147 // itself, but ES2015 allows monkey-patching this property to differ from
148 // the internal flags. If it differs, recompile a different RegExp?
149 var matchIndices = %_RegExpExec(this, string, i, RegExpLastMatchInfo);
150
151 if (IS_NULL(matchIndices)) {
152 this.lastIndex = 0;
153 return null;
154 }
155
156 // Successful match.
157 if (updateLastIndex) {
158 this.lastIndex = RegExpLastMatchInfo[CAPTURE1];
159 }
160 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchIndices, string);
161 }
162 %FunctionRemovePrototype(RegExpSubclassExecJS);
163
164
165 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) 106 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
166 // Also takes an optional exec method in case our caller 107 // Also takes an optional exec method in case our caller
167 // has already fetched exec. 108 // has already fetched exec.
168 function RegExpSubclassExec(regexp, string, exec) { 109 function RegExpSubclassExec(regexp, string, exec) {
169 if (IS_UNDEFINED(exec)) { 110 if (IS_UNDEFINED(exec)) {
170 exec = regexp.exec; 111 exec = regexp.exec;
171 } 112 }
172 if (IS_CALLABLE(exec)) { 113 if (IS_CALLABLE(exec)) {
173 var result = %_Call(exec, regexp, string); 114 var result = %_Call(exec, regexp, string);
174 if (!IS_RECEIVER(result) && !IS_NULL(result)) { 115 if (!IS_RECEIVER(result) && !IS_NULL(result)) {
175 throw %make_type_error(kInvalidRegExpExecResult); 116 throw %make_type_error(kInvalidRegExpExecResult);
176 } 117 }
177 return result; 118 return result;
178 } 119 }
179 return %_Call(RegExpSubclassExecJS, regexp, string); 120 return %_Call(RegExpSubclassExecJS, regexp, string);
180 } 121 }
181 %SetForceInlineFlag(RegExpSubclassExec); 122 %SetForceInlineFlag(RegExpSubclassExec);
182 123
183 124
184 // ES#sec-regexp.prototype.test RegExp.prototype.test ( S )
185 function RegExpSubclassTest(string) {
186 if (!IS_RECEIVER(this)) {
187 throw %make_type_error(kIncompatibleMethodReceiver,
188 'RegExp.prototype.test', this);
189 }
190 string = TO_STRING(string);
191 var match = RegExpSubclassExec(this, string);
192 return !IS_NULL(match);
193 }
194 %FunctionRemovePrototype(RegExpSubclassTest);
195
196
197 function AtSurrogatePair(subject, index) { 125 function AtSurrogatePair(subject, index) {
198 if (index + 1 >= subject.length) return false; 126 if (index + 1 >= subject.length) return false;
199 var first = %_StringCharCodeAt(subject, index); 127 var first = %_StringCharCodeAt(subject, index);
200 if (first < 0xD800 || first > 0xDBFF) return false; 128 if (first < 0xD800 || first > 0xDBFF) return false;
201 var second = %_StringCharCodeAt(subject, index + 1); 129 var second = %_StringCharCodeAt(subject, index + 1);
202 return second >= 0xDC00 || second <= 0xDFFF; 130 return second >= 0xDC00 || second <= 0xDFFF;
203 } 131 }
204 132
205 133
206 // Legacy implementation of RegExp.prototype[Symbol.split] which 134 // Legacy implementation of RegExp.prototype[Symbol.split] which
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 } 275 }
348 } 276 }
349 } 277 }
350 %AddElement(array, arrayIndex, 278 %AddElement(array, arrayIndex,
351 %_SubString(string, prevStringIndex, size)); 279 %_SubString(string, prevStringIndex, size));
352 return array; 280 return array;
353 } 281 }
354 %FunctionRemovePrototype(RegExpSubclassSplit); 282 %FunctionRemovePrototype(RegExpSubclassSplit);
355 283
356 284
357 // ES#sec-regexp.prototype-@@match
358 // RegExp.prototype [ @@match ] ( string )
359 function RegExpSubclassMatch(string) {
360 if (!IS_RECEIVER(this)) {
361 throw %make_type_error(kIncompatibleMethodReceiver,
362 "RegExp.prototype.@@match", this);
363 }
364 string = TO_STRING(string);
365 var global = this.global;
366 if (!global) return RegExpSubclassExec(this, string);
367 var unicode = this.unicode;
368 this.lastIndex = 0;
369 var array = new InternalArray();
370 var n = 0;
371 var result;
372 while (true) {
373 result = RegExpSubclassExec(this, string);
374 if (IS_NULL(result)) {
375 if (n === 0) return null;
376 break;
377 }
378 var matchStr = TO_STRING(result[0]);
379 array[n] = matchStr;
380 if (matchStr === "") SetAdvancedStringIndex(this, string, unicode);
381 n++;
382 }
383 var resultArray = [];
384 %MoveArrayContents(array, resultArray);
385 return resultArray;
386 }
387 %FunctionRemovePrototype(RegExpSubclassMatch);
388
389
390 // Legacy implementation of RegExp.prototype[Symbol.replace] which 285 // Legacy implementation of RegExp.prototype[Symbol.replace] which
391 // doesn't properly call the underlying exec method. 286 // doesn't properly call the underlying exec method.
392 287
393 // TODO(lrn): This array will survive indefinitely if replace is never 288 // TODO(lrn): This array will survive indefinitely if replace is never
394 // called again. However, it will be empty, since the contents are cleared 289 // called again. However, it will be empty, since the contents are cleared
395 // in the finally block. 290 // in the finally block.
396 var reusableReplaceArray = new InternalArray(4); 291 var reusableReplaceArray = new InternalArray(4);
397 292
398 // Helper function for replacing regular expressions with the result of a 293 // Helper function for replacing regular expressions with the result of a
399 // function application in String.prototype.replace. 294 // function application in String.prototype.replace.
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 %_SubString(string, nextSourcePosition, position) + replacement; 641 %_SubString(string, nextSourcePosition, position) + replacement;
747 nextSourcePosition = position + matchedLength; 642 nextSourcePosition = position + matchedLength;
748 } 643 }
749 } 644 }
750 if (nextSourcePosition >= length) return accumulatedResult; 645 if (nextSourcePosition >= length) return accumulatedResult;
751 return accumulatedResult + %_SubString(string, nextSourcePosition, length); 646 return accumulatedResult + %_SubString(string, nextSourcePosition, length);
752 } 647 }
753 %FunctionRemovePrototype(RegExpSubclassReplace); 648 %FunctionRemovePrototype(RegExpSubclassReplace);
754 649
755 650
756 // ES#sec-regexp.prototype-@@search
757 // RegExp.prototype [ @@search ] ( string )
758 function RegExpSubclassSearch(string) {
759 if (!IS_RECEIVER(this)) {
760 throw %make_type_error(kIncompatibleMethodReceiver,
761 "RegExp.prototype.@@search", this);
762 }
763 string = TO_STRING(string);
764 var previousLastIndex = this.lastIndex;
765 this.lastIndex = 0;
766 var result = RegExpSubclassExec(this, string);
767 this.lastIndex = previousLastIndex;
768 if (IS_NULL(result)) return -1;
769 return result.index;
770 }
771 %FunctionRemovePrototype(RegExpSubclassSearch);
772
773
774 // ------------------------------------------------------------------- 651 // -------------------------------------------------------------------
775 652
776 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ 653 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [
777 "exec", RegExpSubclassExecJS,
778 "test", RegExpSubclassTest,
779 matchSymbol, RegExpSubclassMatch,
780 replaceSymbol, RegExpSubclassReplace, 654 replaceSymbol, RegExpSubclassReplace,
781 searchSymbol, RegExpSubclassSearch,
782 splitSymbol, RegExpSubclassSplit, 655 splitSymbol, RegExpSubclassSplit,
783 ]); 656 ]);
784 657
785 // Temporary until all RegExpLastMatchInfo accesses are ported to C++. 658 // Temporary until all RegExpLastMatchInfo accesses are ported to C++.
786 SET_PRIVATE(GlobalRegExp, lastMatchInfoSymbol, RegExpLastMatchInfo); 659 SET_PRIVATE(GlobalRegExp, lastMatchInfoSymbol, RegExpLastMatchInfo);
787 660
661 var RegExpSubclassExecJS = GlobalRegExp.prototype.exec;
662
788 // ------------------------------------------------------------------- 663 // -------------------------------------------------------------------
789 // Internal 664 // Internal
790 665
791 var InternalRegExpMatchInfo = { 666 var InternalRegExpMatchInfo = {
792 REGEXP_NUMBER_OF_CAPTURES: 2, 667 REGEXP_NUMBER_OF_CAPTURES: 2,
793 REGEXP_LAST_SUBJECT: "", 668 REGEXP_LAST_SUBJECT: "",
794 REGEXP_LAST_INPUT: UNDEFINED, 669 REGEXP_LAST_INPUT: UNDEFINED,
795 CAPTURE0: 0, 670 CAPTURE0: 0,
796 CAPTURE1: 0 671 CAPTURE1: 0
797 }; 672 };
(...skipping 15 matching lines...) Expand all
813 // Exports 688 // Exports
814 689
815 utils.Export(function(to) { 690 utils.Export(function(to) {
816 to.InternalRegExpMatch = InternalRegExpMatch; 691 to.InternalRegExpMatch = InternalRegExpMatch;
817 to.InternalRegExpReplace = InternalRegExpReplace; 692 to.InternalRegExpReplace = InternalRegExpReplace;
818 to.IsRegExp = IsRegExp; 693 to.IsRegExp = IsRegExp;
819 to.RegExpInitialize = RegExpInitialize; 694 to.RegExpInitialize = RegExpInitialize;
820 }); 695 });
821 696
822 }) 697 })
OLDNEW
« no previous file with comments | « src/heap-symbols.h ('k') | src/objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698