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

Side by Side Diff: src/regexp.js

Issue 567313003: RegExp: Add support for the ES6-proposed sticky flag (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add tests Created 6 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 | Annotate | Revision Log
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 // This file relies on the fact that the following declaration has been made 5 // This file relies on the fact that the following declaration has been made
6 // in runtime.js: 6 // in runtime.js:
7 // var $Object = global.Object; 7 // var $Object = global.Object;
8 // var $Array = global.Array; 8 // var $Array = global.Array;
9 9
10 var $RegExp = global.RegExp; 10 var $RegExp = global.RegExp;
11 11
12 // ------------------------------------------------------------------- 12 // -------------------------------------------------------------------
13 13
14 // A recursive descent parser for Patterns according to the grammar of 14 // A recursive descent parser for Patterns according to the grammar of
15 // ECMA-262 15.10.1, with deviations noted below. 15 // ECMA-262 15.10.1, with deviations noted below.
16 function DoConstructRegExp(object, pattern, flags) { 16 function DoConstructRegExp(object, pattern, flags) {
17 // RegExp : Called as constructor; see ECMA-262, section 15.10.4. 17 // RegExp : Called as constructor; see ECMA-262, section 15.10.4.
18 if (IS_REGEXP(pattern)) { 18 if (IS_REGEXP(pattern)) {
19 if (!IS_UNDEFINED(flags)) { 19 if (!IS_UNDEFINED(flags)) {
20 throw MakeTypeError('regexp_flags', []); 20 throw MakeTypeError('regexp_flags', []);
21 } 21 }
22 flags = (pattern.global ? 'g' : '') 22 flags = (pattern.global ? 'g' : '')
23 + (pattern.ignoreCase ? 'i' : '') 23 + (pattern.ignoreCase ? 'i' : '')
24 + (pattern.multiline ? 'm' : ''); 24 + (pattern.multiline ? 'm' : '');
25 if (%HarmonyRegExps())
Yang 2014/09/15 09:23:16 While I'm fine with this (will be removed eventual
Erik Corry 2014/09/16 17:49:40 Done.
26 flags += (pattern.sticky ? 'y' : '');
25 pattern = pattern.source; 27 pattern = pattern.source;
26 } 28 }
27 29
28 pattern = IS_UNDEFINED(pattern) ? '' : ToString(pattern); 30 pattern = IS_UNDEFINED(pattern) ? '' : ToString(pattern);
29 flags = IS_UNDEFINED(flags) ? '' : ToString(flags); 31 flags = IS_UNDEFINED(flags) ? '' : ToString(flags);
30 32
31 var global = false; 33 var global = false;
32 var ignoreCase = false; 34 var ignoreCase = false;
33 var multiline = false; 35 var multiline = false;
36 var sticky = false;
34 for (var i = 0; i < flags.length; i++) { 37 for (var i = 0; i < flags.length; i++) {
35 var c = %_CallFunction(flags, i, StringCharAt); 38 var c = %_CallFunction(flags, i, StringCharAt);
36 switch (c) { 39 switch (c) {
37 case 'g': 40 case 'g':
38 if (global) { 41 if (global) {
39 throw MakeSyntaxError("invalid_regexp_flags", [flags]); 42 throw MakeSyntaxError("invalid_regexp_flags", [flags]);
40 } 43 }
41 global = true; 44 global = true;
42 break; 45 break;
43 case 'i': 46 case 'i':
44 if (ignoreCase) { 47 if (ignoreCase) {
45 throw MakeSyntaxError("invalid_regexp_flags", [flags]); 48 throw MakeSyntaxError("invalid_regexp_flags", [flags]);
46 } 49 }
47 ignoreCase = true; 50 ignoreCase = true;
48 break; 51 break;
49 case 'm': 52 case 'm':
50 if (multiline) { 53 if (multiline) {
51 throw MakeSyntaxError("invalid_regexp_flags", [flags]); 54 throw MakeSyntaxError("invalid_regexp_flags", [flags]);
52 } 55 }
53 multiline = true; 56 multiline = true;
54 break; 57 break;
58 case 'y':
59 if (!%HarmonyRegExps() || sticky) {
60 throw MakeSyntaxError("invalid_regexp_flags", [flags]);
61 }
62 sticky = true;
63 break;
55 default: 64 default:
56 throw MakeSyntaxError("invalid_regexp_flags", [flags]); 65 throw MakeSyntaxError("invalid_regexp_flags", [flags]);
57 } 66 }
58 } 67 }
59 68
60 %RegExpInitializeObject(object, pattern, global, ignoreCase, multiline); 69 %RegExpInitializeObject(object, pattern, global, ignoreCase, multiline, sticky );
61 70
62 // Call internal function to compile the pattern. 71 // Call internal function to compile the pattern.
63 %RegExpCompile(object, pattern, flags); 72 %RegExpCompile(object, pattern, flags);
64 } 73 }
65 74
66 75
67 function RegExpConstructor(pattern, flags) { 76 function RegExpConstructor(pattern, flags) {
68 if (%_IsConstructCall()) { 77 if (%_IsConstructCall()) {
69 DoConstructRegExp(this, pattern, flags); 78 DoConstructRegExp(this, pattern, flags);
70 } else { 79 } else {
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 } 229 }
221 lastMatchInfoOverride = null; 230 lastMatchInfoOverride = null;
222 this.lastIndex = lastMatchInfo[CAPTURE1]; 231 this.lastIndex = lastMatchInfo[CAPTURE1];
223 return true; 232 return true;
224 } else { 233 } else {
225 // Non-global regexp. 234 // Non-global regexp.
226 // Remove irrelevant preceeding '.*' in a non-global test regexp. 235 // Remove irrelevant preceeding '.*' in a non-global test regexp.
227 // The expression checks whether this.source starts with '.*' and 236 // The expression checks whether this.source starts with '.*' and
228 // that the third char is not a '?'. 237 // that the third char is not a '?'.
229 var regexp = this; 238 var regexp = this;
230 if (%_StringCharCodeAt(regexp.source, 0) == 46 && // '.' 239 if (!this.sticky &&
Yang 2014/09/15 09:23:16 We also need to record .lastIndex for sticky. If I
Erik Corry 2014/09/16 17:49:40 Done, and also added string length check.
240 %_StringCharCodeAt(regexp.source, 0) == 46 && // '.'
231 %_StringCharCodeAt(regexp.source, 1) == 42 && // '*' 241 %_StringCharCodeAt(regexp.source, 1) == 42 && // '*'
232 %_StringCharCodeAt(regexp.source, 2) != 63) { // '?' 242 %_StringCharCodeAt(regexp.source, 2) != 63) { // '?'
233 regexp = TrimRegExp(regexp); 243 regexp = TrimRegExp(regexp);
234 } 244 }
235 // matchIndices is either null or the lastMatchInfo array. 245 // matchIndices is either null or the lastMatchInfo array.
236 var matchIndices = %_RegExpExec(regexp, string, 0, lastMatchInfo); 246 var matchIndices = %_RegExpExec(regexp, string, 0, lastMatchInfo);
237 if (IS_NULL(matchIndices)) { 247 if (IS_NULL(matchIndices)) {
238 this.lastIndex = 0; 248 this.lastIndex = 0;
239 return false; 249 return false;
240 } 250 }
(...skipping 16 matching lines...) Expand all
257 267
258 function RegExpToString() { 268 function RegExpToString() {
259 if (!IS_REGEXP(this)) { 269 if (!IS_REGEXP(this)) {
260 throw MakeTypeError('incompatible_method_receiver', 270 throw MakeTypeError('incompatible_method_receiver',
261 ['RegExp.prototype.toString', this]); 271 ['RegExp.prototype.toString', this]);
262 } 272 }
263 var result = '/' + this.source + '/'; 273 var result = '/' + this.source + '/';
264 if (this.global) result += 'g'; 274 if (this.global) result += 'g';
265 if (this.ignoreCase) result += 'i'; 275 if (this.ignoreCase) result += 'i';
266 if (this.multiline) result += 'm'; 276 if (this.multiline) result += 'm';
277 if (%HarmonyRegExps() && this.sticky) result += 'y';
267 return result; 278 return result;
268 } 279 }
269 280
270 281
271 // Getters for the static properties lastMatch, lastParen, leftContext, and 282 // Getters for the static properties lastMatch, lastParen, leftContext, and
272 // rightContext of the RegExp constructor. The properties are computed based 283 // rightContext of the RegExp constructor. The properties are computed based
273 // on the captures array of the last successful match and the subject string 284 // on the captures array of the last successful match and the subject string
274 // of the last successful match. 285 // of the last successful match.
275 function RegExpGetLastMatch() { 286 function RegExpGetLastMatch() {
276 if (lastMatchInfoOverride !== null) { 287 if (lastMatchInfoOverride !== null) {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 466
456 for (var i = 1; i < 10; ++i) { 467 for (var i = 1; i < 10; ++i) {
457 %DefineAccessorPropertyUnchecked($RegExp, '$' + i, 468 %DefineAccessorPropertyUnchecked($RegExp, '$' + i,
458 RegExpMakeCaptureGetter(i), NoOpSetter, 469 RegExpMakeCaptureGetter(i), NoOpSetter,
459 DONT_DELETE); 470 DONT_DELETE);
460 } 471 }
461 %ToFastProperties($RegExp); 472 %ToFastProperties($RegExp);
462 } 473 }
463 474
464 SetUpRegExp(); 475 SetUpRegExp();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698