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

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

Issue 1409013006: 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_regexps;
13 var FLAG_harmony_tolength; 13 var FLAG_harmony_tolength;
14 var FLAG_harmony_unicode_regexps; 14 var FLAG_harmony_unicode_regexps;
15 var GlobalObject = global.Object; 15 var GlobalObject = global.Object;
16 var GlobalRegExp = global.RegExp; 16 var GlobalRegExp = global.RegExp;
17 var InternalPackedArray = utils.InternalPackedArray; 17 var InternalPackedArray = utils.InternalPackedArray;
18 var MakeTypeError; 18 var MakeTypeError;
19 var regExpFlagsSymbol = utils.ImportNow("regexp_flags_symbol");
20 var regExpSourceSymbol = utils.ImportNow("regexp_source_symbol");
21 19
22 utils.ImportFromExperimental(function(from) { 20 utils.ImportFromExperimental(function(from) {
23 FLAG_harmony_regexps = from.FLAG_harmony_regexps; 21 FLAG_harmony_regexps = from.FLAG_harmony_regexps;
24 FLAG_harmony_tolength = from.FLAG_harmony_tolength; 22 FLAG_harmony_tolength = from.FLAG_harmony_tolength;
25 FLAG_harmony_unicode_regexps = from.FLAG_harmony_unicode_regexps; 23 FLAG_harmony_unicode_regexps = from.FLAG_harmony_unicode_regexps;
26 }); 24 });
27 25
28 utils.Import(function(from) { 26 utils.Import(function(from) {
29 MakeTypeError = from.MakeTypeError; 27 MakeTypeError = from.MakeTypeError;
30 }); 28 });
(...skipping 15 matching lines...) Expand all
46 ); 44 );
47 45
48 // ------------------------------------------------------------------- 46 // -------------------------------------------------------------------
49 47
50 // A recursive descent parser for Patterns according to the grammar of 48 // A recursive descent parser for Patterns according to the grammar of
51 // ECMA-262 15.10.1, with deviations noted below. 49 // ECMA-262 15.10.1, with deviations noted below.
52 function DoConstructRegExp(object, pattern, flags) { 50 function DoConstructRegExp(object, pattern, flags) {
53 // RegExp : Called as constructor; see ECMA-262, section 15.10.4. 51 // RegExp : Called as constructor; see ECMA-262, section 15.10.4.
54 if (IS_REGEXP(pattern)) { 52 if (IS_REGEXP(pattern)) {
55 if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags); 53 if (!IS_UNDEFINED(flags)) throw MakeTypeError(kRegExpFlags);
56 flags = (REGEXP_GLOBAL(pattern) ? 'g' : '') 54 flags = (pattern.global ? 'g' : '')
57 + (REGEXP_IGNORE_CASE(pattern) ? 'i' : '') 55 + (pattern.ignoreCase ? 'i' : '')
58 + (REGEXP_MULTILINE(pattern) ? 'm' : ''); 56 + (pattern.multiline ? 'm' : '');
59 if (FLAG_harmony_unicode_regexps) 57 if (FLAG_harmony_unicode_regexps)
60 flags += (REGEXP_UNICODE(pattern) ? 'u' : ''); 58 flags += (pattern.unicode ? 'u' : '');
61 if (FLAG_harmony_regexps) 59 if (FLAG_harmony_regexps)
62 flags += (REGEXP_STICKY(pattern) ? 'y' : ''); 60 flags += (pattern.sticky ? 'y' : '');
63 pattern = REGEXP_SOURCE(pattern); 61 pattern = pattern.source;
64 } 62 }
65 63
66 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern); 64 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern);
67 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags); 65 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags);
68 66
69 %RegExpInitializeAndCompile(object, pattern, flags); 67 %RegExpInitializeAndCompile(object, pattern, flags);
70 } 68 }
71 69
72 70
73 function RegExpConstructor(pattern, flags) { 71 function RegExpConstructor(pattern, flags) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 'RegExp.prototype.exec', this); 158 'RegExp.prototype.exec', this);
161 } 159 }
162 160
163 string = TO_STRING(string); 161 string = TO_STRING(string);
164 var lastIndex = this.lastIndex; 162 var lastIndex = this.lastIndex;
165 163
166 // Conversion is required by the ES2015 specification (RegExpBuiltinExec 164 // Conversion is required by the ES2015 specification (RegExpBuiltinExec
167 // 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.
168 var i = TO_LENGTH_OR_INTEGER(lastIndex); 166 var i = TO_LENGTH_OR_INTEGER(lastIndex);
169 167
170 var updateLastIndex = REGEXP_GLOBAL(this) || 168 var updateLastIndex = this.global || (FLAG_harmony_regexps && this.sticky);
171 (FLAG_harmony_regexps && REGEXP_STICKY(this));
172 if (updateLastIndex) { 169 if (updateLastIndex) {
173 if (i < 0 || i > string.length) { 170 if (i < 0 || i > string.length) {
174 this.lastIndex = 0; 171 this.lastIndex = 0;
175 return null; 172 return null;
176 } 173 }
177 } else { 174 } else {
178 i = 0; 175 i = 0;
179 } 176 }
180 177
181 // matchIndices is either null or the RegExpLastMatchInfo array. 178 // matchIndices is either null or the RegExpLastMatchInfo array.
(...skipping 26 matching lines...) Expand all
208 'RegExp.prototype.test', this); 205 'RegExp.prototype.test', this);
209 } 206 }
210 string = TO_STRING(string); 207 string = TO_STRING(string);
211 208
212 var lastIndex = this.lastIndex; 209 var lastIndex = this.lastIndex;
213 210
214 // Conversion is required by the ES2015 specification (RegExpBuiltinExec 211 // Conversion is required by the ES2015 specification (RegExpBuiltinExec
215 // 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.
216 var i = TO_LENGTH_OR_INTEGER(lastIndex); 213 var i = TO_LENGTH_OR_INTEGER(lastIndex);
217 214
218 if (REGEXP_GLOBAL(this) || (FLAG_harmony_regexps && REGEXP_STICKY(this))) { 215 if (this.global || (FLAG_harmony_regexps && this.sticky)) {
219 if (i < 0 || i > string.length) { 216 if (i < 0 || i > string.length) {
220 this.lastIndex = 0; 217 this.lastIndex = 0;
221 return false; 218 return false;
222 } 219 }
223 // matchIndices is either null or the RegExpLastMatchInfo array. 220 // matchIndices is either null or the RegExpLastMatchInfo array.
224 var matchIndices = %_RegExpExec(this, string, i, RegExpLastMatchInfo); 221 var matchIndices = %_RegExpExec(this, string, i, RegExpLastMatchInfo);
225 if (IS_NULL(matchIndices)) { 222 if (IS_NULL(matchIndices)) {
226 this.lastIndex = 0; 223 this.lastIndex = 0;
227 return false; 224 return false;
228 } 225 }
229 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; 226 this.lastIndex = RegExpLastMatchInfo[CAPTURE1];
230 return true; 227 return true;
231 } else { 228 } else {
232 // Non-global, non-sticky regexp. 229 // Non-global, non-sticky regexp.
233 // Remove irrelevant preceeding '.*' in a test regexp. The expression 230 // Remove irrelevant preceeding '.*' in a test regexp. The expression
234 // 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
235 // 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
236 var regexp = this; 233 var regexp = this;
237 var source = REGEXP_SOURCE(regexp); 234 if (regexp.source.length >= 3 &&
238 if (regexp.length >= 3 && 235 %_StringCharCodeAt(regexp.source, 0) == 46 && // '.'
239 %_StringCharCodeAt(regexp, 0) == 46 && // '.' 236 %_StringCharCodeAt(regexp.source, 1) == 42 && // '*'
240 %_StringCharCodeAt(regexp, 1) == 42 && // '*' 237 %_StringCharCodeAt(regexp.source, 2) != 63) { // '?'
241 %_StringCharCodeAt(regexp, 2) != 63) { // '?'
242 regexp = TrimRegExp(regexp); 238 regexp = TrimRegExp(regexp);
243 } 239 }
244 // matchIndices is either null or the RegExpLastMatchInfo array. 240 // matchIndices is either null or the RegExpLastMatchInfo array.
245 var matchIndices = %_RegExpExec(regexp, string, 0, RegExpLastMatchInfo); 241 var matchIndices = %_RegExpExec(regexp, string, 0, RegExpLastMatchInfo);
246 if (IS_NULL(matchIndices)) { 242 if (IS_NULL(matchIndices)) {
247 this.lastIndex = 0; 243 this.lastIndex = 0;
248 return false; 244 return false;
249 } 245 }
250 return true; 246 return true;
251 } 247 }
252 } 248 }
253 249
254 function TrimRegExp(regexp) { 250 function TrimRegExp(regexp) {
255 if (!%_ObjectEquals(regexp_key, regexp)) { 251 if (!%_ObjectEquals(regexp_key, regexp)) {
256 regexp_key = regexp; 252 regexp_key = regexp;
257 regexp_val = 253 regexp_val =
258 new GlobalRegExp( 254 new GlobalRegExp(%_SubString(regexp.source, 2, regexp.source.length),
259 %_SubString(REGEXP_SOURCE(regexp), 2, REGEXP_SOURCE(regexp).length), 255 (regexp.ignoreCase ? regexp.multiline ? "im" : "i"
260 (REGEXP_IGNORE_CASE(regexp) ? REGEXP_MULTILINE(regexp) ? "im" : "i" 256 : regexp.multiline ? "m" : ""));
261 : REGEXP_MULTILINE(regexp) ? "m" : ""));
262 } 257 }
263 return regexp_val; 258 return regexp_val;
264 } 259 }
265 260
266 261
267 function RegExpToString() { 262 function RegExpToString() {
268 if (!IS_REGEXP(this)) { 263 if (!IS_REGEXP(this)) {
269 throw MakeTypeError(kIncompatibleMethodReceiver, 264 throw MakeTypeError(kIncompatibleMethodReceiver,
270 'RegExp.prototype.toString', this); 265 'RegExp.prototype.toString', this);
271 } 266 }
272 var result = '/' + REGEXP_SOURCE(this) + '/'; 267 var result = '/' + this.source + '/';
273 if (REGEXP_GLOBAL(this)) result += 'g'; 268 if (this.global) result += 'g';
274 if (REGEXP_IGNORE_CASE(this)) result += 'i'; 269 if (this.ignoreCase) result += 'i';
275 if (REGEXP_MULTILINE(this)) result += 'm'; 270 if (this.multiline) result += 'm';
276 if (FLAG_harmony_unicode_regexps && REGEXP_UNICODE(this)) result += 'u'; 271 if (FLAG_harmony_unicode_regexps && this.unicode) result += 'u';
277 if (FLAG_harmony_regexps && REGEXP_STICKY(this)) result += 'y'; 272 if (FLAG_harmony_regexps && this.sticky) result += 'y';
278 return result; 273 return result;
279 } 274 }
280 275
281 276
282 // Getters for the static properties lastMatch, lastParen, leftContext, and 277 // Getters for the static properties lastMatch, lastParen, leftContext, and
283 // rightContext of the RegExp constructor. The properties are computed based 278 // rightContext of the RegExp constructor. The properties are computed based
284 // 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
285 // of the last successful match. 280 // of the last successful match.
286 function RegExpGetLastMatch() { 281 function RegExpGetLastMatch() {
287 var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo); 282 var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 return function foo() { 327 return function foo() {
333 var index = n * 2; 328 var index = n * 2;
334 if (index >= NUMBER_OF_CAPTURES(RegExpLastMatchInfo)) return ''; 329 if (index >= NUMBER_OF_CAPTURES(RegExpLastMatchInfo)) return '';
335 var matchStart = RegExpLastMatchInfo[CAPTURE(index)]; 330 var matchStart = RegExpLastMatchInfo[CAPTURE(index)];
336 var matchEnd = RegExpLastMatchInfo[CAPTURE(index + 1)]; 331 var matchEnd = RegExpLastMatchInfo[CAPTURE(index + 1)];
337 if (matchStart == -1 || matchEnd == -1) return ''; 332 if (matchStart == -1 || matchEnd == -1) return '';
338 return %_SubString(LAST_SUBJECT(RegExpLastMatchInfo), matchStart, matchEnd); 333 return %_SubString(LAST_SUBJECT(RegExpLastMatchInfo), matchStart, matchEnd);
339 }; 334 };
340 } 335 }
341 336
342
343 // ES6 21.2.5.4, 21.2.5.5, 21.2.5.7, 21.2.5.12, 21.2.5.15.
344 function GetRegExpFlagGetter(name, mask) {
345 var getter = function() {
346 if (!IS_SPEC_OBJECT(this)) {
347 throw MakeTypeError(kRegExpNonObject, name, TO_STRING(this));
348 }
349 var flags = this[regExpFlagsSymbol];
350 if (IS_UNDEFINED(flags)) {
351 throw MakeTypeError(kRegExpNonRegExp, TO_STRING(this));
352 }
353 return !!(flags & mask);
354 };
355 %FunctionSetName(getter, name);
356 %SetNativeFlag(getter);
357 return getter;
358 }
359
360
361 // ES6 21.2.5.10.
362 function RegExpGetSource() {
363 if (!IS_SPEC_OBJECT(this)) {
364 throw MakeTypeError(kRegExpNonObject, "RegExp.prototype.source",
365 TO_STRING(this));
366 }
367 var source = this[regExpSourceSymbol];
368 if (IS_UNDEFINED(source)) {
369 throw MakeTypeError(kRegExpNonRegExp, TO_STRING(this));
370 }
371 return source;
372 }
373
374 %SetNativeFlag(RegExpGetSource);
375
376 // ------------------------------------------------------------------- 337 // -------------------------------------------------------------------
377 338
378 %FunctionSetInstanceClassName(GlobalRegExp, 'RegExp'); 339 %FunctionSetInstanceClassName(GlobalRegExp, 'RegExp');
379 %FunctionSetPrototype(GlobalRegExp, new GlobalObject()); 340 %FunctionSetPrototype(GlobalRegExp, new GlobalObject());
380 %AddNamedProperty( 341 %AddNamedProperty(
381 GlobalRegExp.prototype, 'constructor', GlobalRegExp, DONT_ENUM); 342 GlobalRegExp.prototype, 'constructor', GlobalRegExp, DONT_ENUM);
382 %SetCode(GlobalRegExp, RegExpConstructor); 343 %SetCode(GlobalRegExp, RegExpConstructor);
383 344
384 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ 345 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [
385 "exec", RegExpExecJS, 346 "exec", RegExpExecJS,
386 "test", RegExpTest, 347 "test", RegExpTest,
387 "toString", RegExpToString, 348 "toString", RegExpToString,
388 "compile", RegExpCompileJS 349 "compile", RegExpCompileJS
389 ]); 350 ]);
390 351
391 %DefineGetterPropertyUnchecked(GlobalRegExp.prototype, "global",
392 GetRegExpFlagGetter("RegExp.prototype.global", REGEXP_GLOBAL_MASK),
393 DONT_ENUM);
394 %DefineGetterPropertyUnchecked(GlobalRegExp.prototype, "ignoreCase",
395 GetRegExpFlagGetter("RegExp.prototype.ignoreCase", REGEXP_IGNORE_CASE_MASK),
396 DONT_ENUM);
397 %DefineGetterPropertyUnchecked(GlobalRegExp.prototype, "multiline",
398 GetRegExpFlagGetter("RegExp.prototype.multiline", REGEXP_MULTILINE_MASK),
399 DONT_ENUM);
400 %DefineGetterPropertyUnchecked(GlobalRegExp.prototype, "source",
401 RegExpGetSource, DONT_ENUM);
402
403 // The length of compile is 1 in SpiderMonkey. 352 // The length of compile is 1 in SpiderMonkey.
404 %FunctionSetLength(GlobalRegExp.prototype.compile, 1); 353 %FunctionSetLength(GlobalRegExp.prototype.compile, 1);
405 354
406 // The properties `input` and `$_` are aliases for each other. When this 355 // The properties `input` and `$_` are aliases for each other. When this
407 // 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.
408 // Getter and setter for the input. 357 // Getter and setter for the input.
409 var RegExpGetInput = function() { 358 var RegExpGetInput = function() {
410 var regExpInput = LAST_INPUT(RegExpLastMatchInfo); 359 var regExpInput = LAST_INPUT(RegExpLastMatchInfo);
411 return IS_UNDEFINED(regExpInput) ? "" : regExpInput; 360 return IS_UNDEFINED(regExpInput) ? "" : regExpInput;
412 }; 361 };
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 %DefineAccessorPropertyUnchecked(GlobalRegExp, '$' + i, 415 %DefineAccessorPropertyUnchecked(GlobalRegExp, '$' + i,
467 RegExpMakeCaptureGetter(i), NoOpSetter, 416 RegExpMakeCaptureGetter(i), NoOpSetter,
468 DONT_DELETE); 417 DONT_DELETE);
469 } 418 }
470 %ToFastProperties(GlobalRegExp); 419 %ToFastProperties(GlobalRegExp);
471 420
472 // ------------------------------------------------------------------- 421 // -------------------------------------------------------------------
473 // Exports 422 // Exports
474 423
475 utils.Export(function(to) { 424 utils.Export(function(to) {
476 to.GetRegExpFlagGetter = GetRegExpFlagGetter;
477 to.RegExpExec = DoRegExpExec; 425 to.RegExpExec = DoRegExpExec;
478 to.RegExpExecNoTests = RegExpExecNoTests; 426 to.RegExpExecNoTests = RegExpExecNoTests;
479 to.RegExpLastMatchInfo = RegExpLastMatchInfo; 427 to.RegExpLastMatchInfo = RegExpLastMatchInfo;
480 to.RegExpTest = RegExpTest; 428 to.RegExpTest = RegExpTest;
481 }); 429 });
482 430
483 }) 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