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

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

Issue 1432683002: Revert of Implement flag and source getters on RegExp.prototype. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@rproto
Patch Set: Created 5 years, 1 month 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/js/prologue.js ('k') | src/js/string.js » ('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 FLAG_harmony_regexps;
12 var FLAG_harmony_tolength; 13 var FLAG_harmony_tolength;
14 var FLAG_harmony_unicode_regexps;
13 var GlobalObject = global.Object; 15 var GlobalObject = global.Object;
14 var GlobalRegExp = global.RegExp; 16 var GlobalRegExp = global.RegExp;
15 var InternalPackedArray = utils.InternalPackedArray; 17 var InternalPackedArray = utils.InternalPackedArray;
16 var MakeTypeError; 18 var MakeTypeError;
17 var regExpFlagsSymbol = utils.ImportNow("regexp_flags_symbol");
18 var regExpSourceSymbol = utils.ImportNow("regexp_source_symbol");
19 19
20 utils.ImportFromExperimental(function(from) { 20 utils.ImportFromExperimental(function(from) {
21 FLAG_harmony_regexps = from.FLAG_harmony_regexps;
21 FLAG_harmony_tolength = from.FLAG_harmony_tolength; 22 FLAG_harmony_tolength = from.FLAG_harmony_tolength;
23 FLAG_harmony_unicode_regexps = from.FLAG_harmony_unicode_regexps;
22 }); 24 });
23 25
24 utils.Import(function(from) { 26 utils.Import(function(from) {
25 MakeTypeError = from.MakeTypeError; 27 MakeTypeError = from.MakeTypeError;
26 }); 28 });
27 29
28 // ------------------------------------------------------------------- 30 // -------------------------------------------------------------------
29 31
30 // Property of the builtins object for recording the result of the last 32 // Property of the builtins object for recording the result of the last
31 // regexp match. The property RegExpLastMatchInfo includes the matchIndices 33 // regexp match. The property RegExpLastMatchInfo includes the matchIndices
(...skipping 10 matching lines...) Expand all
42 ); 44 );
43 45
44 // ------------------------------------------------------------------- 46 // -------------------------------------------------------------------
45 47
46 // A recursive descent parser for Patterns according to the grammar of 48 // A recursive descent parser for Patterns according to the grammar of
47 // ECMA-262 15.10.1, with deviations noted below. 49 // ECMA-262 15.10.1, with deviations noted below.
48 function DoConstructRegExp(object, pattern, flags) { 50 function DoConstructRegExp(object, pattern, flags) {
49 // RegExp : Called as constructor; see ECMA-262, section 15.10.4. 51 // RegExp : Called as constructor; see ECMA-262, section 15.10.4.
50 if (IS_REGEXP(pattern)) { 52 if (IS_REGEXP(pattern)) {
51 if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags); 53 if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags);
52 flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') 54 flags = (pattern.global ? 'g' : '')
53 + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') 55 + (pattern.ignoreCase ? 'i' : '')
54 + (REGEXP_MULTILINE(pattern) ? 'm' : '') 56 + (pattern.multiline ? 'm' : '');
55 + (REGEXP_UNICODE(pattern) ? 'u' : '') 57 if (FLAG_harmony_unicode_regexps)
56 + (REGEXP_STICKY(pattern) ? 'y' : ''); 58 flags += (pattern.unicode ? 'u' : '');
57 pattern = REGEXP_SOURCE(pattern); 59 if (FLAG_harmony_regexps)
60 flags += (pattern.sticky ? 'y' : '');
61 pattern = pattern.source;
58 } 62 }
59 63
60 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern); 64 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern);
61 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags); 65 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags);
62 66
63 %RegExpInitializeAndCompile(object, pattern, flags); 67 %RegExpInitializeAndCompile(object, pattern, flags);
64 } 68 }
65 69
66 70
67 function RegExpConstructor(pattern, flags) { 71 function RegExpConstructor(pattern, flags) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 } 135 }
132 return result; 136 return result;
133 endmacro 137 endmacro
134 138
135 139
136 function RegExpExecNoTests(regexp, string, start) { 140 function RegExpExecNoTests(regexp, string, start) {
137 // Must be called with RegExp, string and positive integer as arguments. 141 // Must be called with RegExp, string and positive integer as arguments.
138 var matchInfo = %_RegExpExec(regexp, string, start, RegExpLastMatchInfo); 142 var matchInfo = %_RegExpExec(regexp, string, start, RegExpLastMatchInfo);
139 if (matchInfo !== null) { 143 if (matchInfo !== null) {
140 // ES6 21.2.5.2.2 step 18. 144 // ES6 21.2.5.2.2 step 18.
141 if (REGEXP_STICKY(regexp)) regexp.lastIndex = matchInfo[CAPTURE1]; 145 if (FLAG_harmony_regexps && regexp.sticky) {
146 regexp.lastIndex = matchInfo[CAPTURE1];
147 }
142 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, string); 148 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, string);
143 } 149 }
144 regexp.lastIndex = 0; 150 regexp.lastIndex = 0;
145 return null; 151 return null;
146 } 152 }
147 153
148 154
149 function RegExpExecJS(string) { 155 function RegExpExecJS(string) {
150 if (!IS_REGEXP(this)) { 156 if (!IS_REGEXP(this)) {
151 throw MakeTypeError(kIncompatibleMethodReceiver, 157 throw MakeTypeError(kIncompatibleMethodReceiver,
152 'RegExp.prototype.exec', this); 158 'RegExp.prototype.exec', this);
153 } 159 }
154 160
155 string = TO_STRING(string); 161 string = TO_STRING(string);
156 var lastIndex = this.lastIndex; 162 var lastIndex = this.lastIndex;
157 163
158 // Conversion is required by the ES2015 specification (RegExpBuiltinExec 164 // Conversion is required by the ES2015 specification (RegExpBuiltinExec
159 // algorithm, step 4) even if the value is discarded for non-global RegExps. 165 // algorithm, step 4) even if the value is discarded for non-global RegExps.
160 var i = TO_LENGTH_OR_INTEGER(lastIndex); 166 var i = TO_LENGTH_OR_INTEGER(lastIndex);
161 167
162 var updateLastIndex = REGEXP_GLOBAL(this) || REGEXP_STICKY(this); 168 var updateLastIndex = this.global || (FLAG_harmony_regexps && this.sticky);
163 if (updateLastIndex) { 169 if (updateLastIndex) {
164 if (i < 0 || i > string.length) { 170 if (i < 0 || i > string.length) {
165 this.lastIndex = 0; 171 this.lastIndex = 0;
166 return null; 172 return null;
167 } 173 }
168 } else { 174 } else {
169 i = 0; 175 i = 0;
170 } 176 }
171 177
172 // matchIndices is either null or the RegExpLastMatchInfo array. 178 // matchIndices is either null or the RegExpLastMatchInfo array.
(...skipping 26 matching lines...) Expand all
199 'RegExp.prototype.test', this); 205 'RegExp.prototype.test', this);
200 } 206 }
201 string = TO_STRING(string); 207 string = TO_STRING(string);
202 208
203 var lastIndex = this.lastIndex; 209 var lastIndex = this.lastIndex;
204 210
205 // Conversion is required by the ES2015 specification (RegExpBuiltinExec 211 // Conversion is required by the ES2015 specification (RegExpBuiltinExec
206 // algorithm, step 4) even if the value is discarded for non-global RegExps. 212 // algorithm, step 4) even if the value is discarded for non-global RegExps.
207 var i = TO_LENGTH_OR_INTEGER(lastIndex); 213 var i = TO_LENGTH_OR_INTEGER(lastIndex);
208 214
209 if (REGEXP_GLOBAL(this) || REGEXP_STICKY(this)) { 215 if (this.global || (FLAG_harmony_regexps && this.sticky)) {
210 if (i < 0 || i > string.length) { 216 if (i < 0 || i > string.length) {
211 this.lastIndex = 0; 217 this.lastIndex = 0;
212 return false; 218 return false;
213 } 219 }
214 // matchIndices is either null or the RegExpLastMatchInfo array. 220 // matchIndices is either null or the RegExpLastMatchInfo array.
215 var matchIndices = %_RegExpExec(this, string, i, RegExpLastMatchInfo); 221 var matchIndices = %_RegExpExec(this, string, i, RegExpLastMatchInfo);
216 if (IS_NULL(matchIndices)) { 222 if (IS_NULL(matchIndices)) {
217 this.lastIndex = 0; 223 this.lastIndex = 0;
218 return false; 224 return false;
219 } 225 }
220 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; 226 this.lastIndex = RegExpLastMatchInfo[CAPTURE1];
221 return true; 227 return true;
222 } else { 228 } else {
223 // Non-global, non-sticky regexp. 229 // Non-global, non-sticky regexp.
224 // Remove irrelevant preceeding '.*' in a test regexp. The expression 230 // Remove irrelevant preceeding '.*' in a test regexp. The expression
225 // checks whether this.source starts with '.*' and that the third char is 231 // checks whether this.source starts with '.*' and that the third char is
226 // not a '?'. But see https://code.google.com/p/v8/issues/detail?id=3560 232 // not a '?'. But see https://code.google.com/p/v8/issues/detail?id=3560
227 var regexp = this; 233 var regexp = this;
228 var source = REGEXP_SOURCE(regexp); 234 if (regexp.source.length >= 3 &&
229 if (regexp.length >= 3 && 235 %_StringCharCodeAt(regexp.source, 0) == 46 && // '.'
230 %_StringCharCodeAt(regexp, 0) == 46 && // '.' 236 %_StringCharCodeAt(regexp.source, 1) == 42 && // '*'
231 %_StringCharCodeAt(regexp, 1) == 42 && // '*' 237 %_StringCharCodeAt(regexp.source, 2) != 63) { // '?'
232 %_StringCharCodeAt(regexp, 2) != 63) { // '?'
233 regexp = TrimRegExp(regexp); 238 regexp = TrimRegExp(regexp);
234 } 239 }
235 // matchIndices is either null or the RegExpLastMatchInfo array. 240 // matchIndices is either null or the RegExpLastMatchInfo array.
236 var matchIndices = %_RegExpExec(regexp, string, 0, RegExpLastMatchInfo); 241 var matchIndices = %_RegExpExec(regexp, string, 0, RegExpLastMatchInfo);
237 if (IS_NULL(matchIndices)) { 242 if (IS_NULL(matchIndices)) {
238 this.lastIndex = 0; 243 this.lastIndex = 0;
239 return false; 244 return false;
240 } 245 }
241 return true; 246 return true;
242 } 247 }
243 } 248 }
244 249
245 function TrimRegExp(regexp) { 250 function TrimRegExp(regexp) {
246 if (!%_ObjectEquals(regexp_key, regexp)) { 251 if (!%_ObjectEquals(regexp_key, regexp)) {
247 regexp_key = regexp; 252 regexp_key = regexp;
248 regexp_val = 253 regexp_val =
249 new GlobalRegExp( 254 new GlobalRegExp(%_SubString(regexp.source, 2, regexp.source.length),
250 %_SubString(REGEXP_SOURCE(regexp), 2, REGEXP_SOURCE(regexp).length), 255 (regexp.ignoreCase ? regexp.multiline ? "im" : "i"
251 (REGEXP_IGNORE_CASE(regexp) ? REGEXP_MULTILINE(regexp) ? "im" : "i" 256 : regexp.multiline ? "m" : ""));
252 : REGEXP_MULTILINE(regexp) ? "m" : ""));
253 } 257 }
254 return regexp_val; 258 return regexp_val;
255 } 259 }
256 260
257 261
258 function RegExpToString() { 262 function RegExpToString() {
259 if (!IS_REGEXP(this)) { 263 if (!IS_REGEXP(this)) {
260 throw MakeTypeError(kIncompatibleMethodReceiver, 264 throw MakeTypeError(kIncompatibleMethodReceiver,
261 'RegExp.prototype.toString', this); 265 'RegExp.prototype.toString', this);
262 } 266 }
263 var result = '/' + REGEXP_SOURCE(this) + '/'; 267 var result = '/' + this.source + '/';
264 if (REGEXP_GLOBAL(this)) result += 'g'; 268 if (this.global) result += 'g';
265 if (REGEXP_IGNORE_CASE(this)) result += 'i'; 269 if (this.ignoreCase) result += 'i';
266 if (REGEXP_MULTILINE(this)) result += 'm'; 270 if (this.multiline) result += 'm';
267 if (REGEXP_UNICODE(this)) result += 'u'; 271 if (FLAG_harmony_unicode_regexps && this.unicode) result += 'u';
268 if (REGEXP_STICKY(this)) result += 'y'; 272 if (FLAG_harmony_regexps && this.sticky) result += 'y';
269 return result; 273 return result;
270 } 274 }
271 275
272 276
273 // Getters for the static properties lastMatch, lastParen, leftContext, and 277 // Getters for the static properties lastMatch, lastParen, leftContext, and
274 // rightContext of the RegExp constructor. The properties are computed based 278 // rightContext of the RegExp constructor. The properties are computed based
275 // on the captures array of the last successful match and the subject string 279 // on the captures array of the last successful match and the subject string
276 // of the last successful match. 280 // of the last successful match.
277 function RegExpGetLastMatch() { 281 function RegExpGetLastMatch() {
278 var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo); 282 var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 return function foo() { 327 return function foo() {
324 var index = n * 2; 328 var index = n * 2;
325 if (index >= NUMBER_OF_CAPTURES(RegExpLastMatchInfo)) return ''; 329 if (index >= NUMBER_OF_CAPTURES(RegExpLastMatchInfo)) return '';
326 var matchStart = RegExpLastMatchInfo[CAPTURE(index)]; 330 var matchStart = RegExpLastMatchInfo[CAPTURE(index)];
327 var matchEnd = RegExpLastMatchInfo[CAPTURE(index + 1)]; 331 var matchEnd = RegExpLastMatchInfo[CAPTURE(index + 1)];
328 if (matchStart == -1 || matchEnd == -1) return ''; 332 if (matchStart == -1 || matchEnd == -1) return '';
329 return %_SubString(LAST_SUBJECT(RegExpLastMatchInfo), matchStart, matchEnd); 333 return %_SubString(LAST_SUBJECT(RegExpLastMatchInfo), matchStart, matchEnd);
330 }; 334 };
331 } 335 }
332 336
333
334 // ES6 21.2.5.4, 21.2.5.5, 21.2.5.7, 21.2.5.12, 21.2.5.15.
335 function GetRegExpFlagGetter(name, mask) {
336 var getter = function() {
337 if (!IS_SPEC_OBJECT(this)) {
338 throw MakeTypeError(kRegExpNonObject, name, TO_STRING(this));
339 }
340 var flags = this[regExpFlagsSymbol];
341 if (IS_UNDEFINED(flags)) {
342 throw MakeTypeError(kRegExpNonRegExp, TO_STRING(this));
343 }
344 return !!(flags & mask);
345 };
346 %FunctionSetName(getter, name);
347 %SetNativeFlag(getter);
348 return getter;
349 }
350
351
352 // ES6 21.2.5.10.
353 function RegExpGetSource() {
354 if (!IS_SPEC_OBJECT(this)) {
355 throw MakeTypeError(kRegExpNonObject, "RegExp.prototype.source",
356 TO_STRING(this));
357 }
358 var source = this[regExpSourceSymbol];
359 if (IS_UNDEFINED(source)) {
360 throw MakeTypeError(kRegExpNonRegExp, TO_STRING(this));
361 }
362 return source;
363 }
364
365 %SetNativeFlag(RegExpGetSource);
366
367 // ------------------------------------------------------------------- 337 // -------------------------------------------------------------------
368 338
369 %FunctionSetInstanceClassName(GlobalRegExp, 'RegExp'); 339 %FunctionSetInstanceClassName(GlobalRegExp, 'RegExp');
370 %FunctionSetPrototype(GlobalRegExp, new GlobalObject()); 340 %FunctionSetPrototype(GlobalRegExp, new GlobalObject());
371 %AddNamedProperty( 341 %AddNamedProperty(
372 GlobalRegExp.prototype, 'constructor', GlobalRegExp, DONT_ENUM); 342 GlobalRegExp.prototype, 'constructor', GlobalRegExp, DONT_ENUM);
373 %SetCode(GlobalRegExp, RegExpConstructor); 343 %SetCode(GlobalRegExp, RegExpConstructor);
374 344
375 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ 345 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [
376 "exec", RegExpExecJS, 346 "exec", RegExpExecJS,
377 "test", RegExpTest, 347 "test", RegExpTest,
378 "toString", RegExpToString, 348 "toString", RegExpToString,
379 "compile", RegExpCompileJS 349 "compile", RegExpCompileJS
380 ]); 350 ]);
381 351
382 %DefineGetterPropertyUnchecked(GlobalRegExp.prototype, "global",
383 GetRegExpFlagGetter("RegExp.prototype.global", REGEXP_GLOBAL_MASK),
384 DONT_ENUM);
385 %DefineGetterPropertyUnchecked(GlobalRegExp.prototype, "ignoreCase",
386 GetRegExpFlagGetter("RegExp.prototype.ignoreCase", REGEXP_IGNORE_CASE_MASK),
387 DONT_ENUM);
388 %DefineGetterPropertyUnchecked(GlobalRegExp.prototype, "multiline",
389 GetRegExpFlagGetter("RegExp.prototype.multiline", REGEXP_MULTILINE_MASK),
390 DONT_ENUM);
391 %DefineGetterPropertyUnchecked(GlobalRegExp.prototype, "source",
392 RegExpGetSource, DONT_ENUM);
393
394 // The length of compile is 1 in SpiderMonkey. 352 // The length of compile is 1 in SpiderMonkey.
395 %FunctionSetLength(GlobalRegExp.prototype.compile, 1); 353 %FunctionSetLength(GlobalRegExp.prototype.compile, 1);
396 354
397 // The properties `input` and `$_` are aliases for each other. When this 355 // The properties `input` and `$_` are aliases for each other. When this
398 // value is set the value it is set to is coerced to a string. 356 // value is set the value it is set to is coerced to a string.
399 // Getter and setter for the input. 357 // Getter and setter for the input.
400 var RegExpGetInput = function() { 358 var RegExpGetInput = function() {
401 var regExpInput = LAST_INPUT(RegExpLastMatchInfo); 359 var regExpInput = LAST_INPUT(RegExpLastMatchInfo);
402 return IS_UNDEFINED(regExpInput) ? "" : regExpInput; 360 return IS_UNDEFINED(regExpInput) ? "" : regExpInput;
403 }; 361 };
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 %DefineAccessorPropertyUnchecked(GlobalRegExp, '$' + i, 415 %DefineAccessorPropertyUnchecked(GlobalRegExp, '$' + i,
458 RegExpMakeCaptureGetter(i), NoOpSetter, 416 RegExpMakeCaptureGetter(i), NoOpSetter,
459 DONT_DELETE); 417 DONT_DELETE);
460 } 418 }
461 %ToFastProperties(GlobalRegExp); 419 %ToFastProperties(GlobalRegExp);
462 420
463 // ------------------------------------------------------------------- 421 // -------------------------------------------------------------------
464 // Exports 422 // Exports
465 423
466 utils.Export(function(to) { 424 utils.Export(function(to) {
467 to.GetRegExpFlagGetter = GetRegExpFlagGetter;
468 to.RegExpExec = DoRegExpExec; 425 to.RegExpExec = DoRegExpExec;
469 to.RegExpExecNoTests = RegExpExecNoTests; 426 to.RegExpExecNoTests = RegExpExecNoTests;
470 to.RegExpLastMatchInfo = RegExpLastMatchInfo; 427 to.RegExpLastMatchInfo = RegExpLastMatchInfo;
471 to.RegExpTest = RegExpTest; 428 to.RegExpTest = RegExpTest;
472 }); 429 });
473 430
474 }) 431 })
OLDNEW
« no previous file with comments | « src/js/prologue.js ('k') | src/js/string.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698