OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 result += 'm'; | 337 result += 'm'; |
338 return result; | 338 return result; |
339 } | 339 } |
340 | 340 |
341 | 341 |
342 // Getters for the static properties lastMatch, lastParen, leftContext, and | 342 // Getters for the static properties lastMatch, lastParen, leftContext, and |
343 // rightContext of the RegExp constructor. The properties are computed based | 343 // rightContext of the RegExp constructor. The properties are computed based |
344 // on the captures array of the last successful match and the subject string | 344 // on the captures array of the last successful match and the subject string |
345 // of the last successful match. | 345 // of the last successful match. |
346 function RegExpGetLastMatch() { | 346 function RegExpGetLastMatch() { |
| 347 if (lastMatchInfoOverride) { return lastMatchInfoOverride[0]; } |
347 var regExpSubject = LAST_SUBJECT(lastMatchInfo); | 348 var regExpSubject = LAST_SUBJECT(lastMatchInfo); |
348 return SubString(regExpSubject, | 349 return SubString(regExpSubject, |
349 lastMatchInfo[CAPTURE0], | 350 lastMatchInfo[CAPTURE0], |
350 lastMatchInfo[CAPTURE1]); | 351 lastMatchInfo[CAPTURE1]); |
351 } | 352 } |
352 | 353 |
353 | 354 |
354 function RegExpGetLastParen() { | 355 function RegExpGetLastParen() { |
| 356 if (lastMatchInfoOverride) { |
| 357 var override = lastMatchInfoOverride; |
| 358 if (override.length <= 3) return ''; |
| 359 return override[override.length - 3]; |
| 360 } |
355 var length = NUMBER_OF_CAPTURES(lastMatchInfo); | 361 var length = NUMBER_OF_CAPTURES(lastMatchInfo); |
356 if (length <= 2) return ''; // There were no captures. | 362 if (length <= 2) return ''; // There were no captures. |
357 // We match the SpiderMonkey behavior: return the substring defined by the | 363 // We match the SpiderMonkey behavior: return the substring defined by the |
358 // last pair (after the first pair) of elements of the capture array even if | 364 // last pair (after the first pair) of elements of the capture array even if |
359 // it is empty. | 365 // it is empty. |
360 var regExpSubject = LAST_SUBJECT(lastMatchInfo); | 366 var regExpSubject = LAST_SUBJECT(lastMatchInfo); |
361 var start = lastMatchInfo[CAPTURE(length - 2)]; | 367 var start = lastMatchInfo[CAPTURE(length - 2)]; |
362 var end = lastMatchInfo[CAPTURE(length - 1)]; | 368 var end = lastMatchInfo[CAPTURE(length - 1)]; |
363 if (start != -1 && end != -1) { | 369 if (start != -1 && end != -1) { |
364 return SubString(regExpSubject, start, end); | 370 return SubString(regExpSubject, start, end); |
365 } | 371 } |
366 return ""; | 372 return ""; |
367 } | 373 } |
368 | 374 |
369 | 375 |
370 function RegExpGetLeftContext() { | 376 function RegExpGetLeftContext() { |
371 return SubString(LAST_SUBJECT(lastMatchInfo), | 377 var start_index; |
372 0, | 378 var subject; |
373 lastMatchInfo[CAPTURE0]); | 379 if (!lastMatchInfoOverride) { |
| 380 start_index = lastMatchInfo[CAPTURE0]; |
| 381 subject = LAST_SUBJECT(lastMatchInfo); |
| 382 } else { |
| 383 var override = lastMatchInfoOverride; |
| 384 start_index = override[override.length - 2]; |
| 385 subject = override[override.length - 1]; |
| 386 } |
| 387 return SubString(subject, 0, start_index); |
374 } | 388 } |
375 | 389 |
376 | 390 |
377 function RegExpGetRightContext() { | 391 function RegExpGetRightContext() { |
378 var subject = LAST_SUBJECT(lastMatchInfo); | 392 var start_index; |
379 return SubString(subject, | 393 var subject; |
380 lastMatchInfo[CAPTURE1], | 394 if (!lastMatchInfoOverride) { |
381 subject.length); | 395 start_index = lastMatchInfo[CAPTURE1]; |
| 396 subject = LAST_SUBJECT(lastMatchInfo); |
| 397 } else { |
| 398 var override = lastMatchInfoOverride; |
| 399 subject = override[override.length - 1]; |
| 400 start_index = override[override.length - 2] + subject.length; |
| 401 } |
| 402 return SubString(subject, start_index, subject.length); |
382 } | 403 } |
383 | 404 |
384 | 405 |
385 // The properties $1..$9 are the first nine capturing substrings of the last | 406 // The properties $1..$9 are the first nine capturing substrings of the last |
386 // successful match, or ''. The function RegExpMakeCaptureGetter will be | 407 // successful match, or ''. The function RegExpMakeCaptureGetter will be |
387 // called with indices from 1 to 9. | 408 // called with indices from 1 to 9. |
388 function RegExpMakeCaptureGetter(n) { | 409 function RegExpMakeCaptureGetter(n) { |
389 return function() { | 410 return function() { |
| 411 if (lastMatchInfoOverride) { |
| 412 if (n < lastMatchInfoOverride.length - 2) return lastMatchInfoOverride[n]; |
| 413 return ''; |
| 414 } |
390 var index = n * 2; | 415 var index = n * 2; |
391 if (index >= NUMBER_OF_CAPTURES(lastMatchInfo)) return ''; | 416 if (index >= NUMBER_OF_CAPTURES(lastMatchInfo)) return ''; |
392 var matchStart = lastMatchInfo[CAPTURE(index)]; | 417 var matchStart = lastMatchInfo[CAPTURE(index)]; |
393 var matchEnd = lastMatchInfo[CAPTURE(index + 1)]; | 418 var matchEnd = lastMatchInfo[CAPTURE(index + 1)]; |
394 if (matchStart == -1 || matchEnd == -1) return ''; | 419 if (matchStart == -1 || matchEnd == -1) return ''; |
395 return SubString(LAST_SUBJECT(lastMatchInfo), matchStart, matchEnd); | 420 return SubString(LAST_SUBJECT(lastMatchInfo), matchStart, matchEnd); |
396 }; | 421 }; |
397 } | 422 } |
398 | 423 |
399 | 424 |
400 // Property of the builtins object for recording the result of the last | 425 // Property of the builtins object for recording the result of the last |
401 // regexp match. The property lastMatchInfo includes the matchIndices | 426 // regexp match. The property lastMatchInfo includes the matchIndices |
402 // array of the last successful regexp match (an array of start/end index | 427 // array of the last successful regexp match (an array of start/end index |
403 // pairs for the match and all the captured substrings), the invariant is | 428 // pairs for the match and all the captured substrings), the invariant is |
404 // that there are at least two capture indeces. The array also contains | 429 // that there are at least two capture indeces. The array also contains |
405 // the subject string for the last successful match. | 430 // the subject string for the last successful match. |
406 var lastMatchInfo = [ | 431 var lastMatchInfo = [ |
407 2, // REGEXP_NUMBER_OF_CAPTURES | 432 2, // REGEXP_NUMBER_OF_CAPTURES |
408 "", // Last subject. | 433 "", // Last subject. |
409 void 0, // Last input - settable with RegExpSetInput. | 434 void 0, // Last input - settable with RegExpSetInput. |
410 0, // REGEXP_FIRST_CAPTURE + 0 | 435 0, // REGEXP_FIRST_CAPTURE + 0 |
411 0, // REGEXP_FIRST_CAPTURE + 1 | 436 0, // REGEXP_FIRST_CAPTURE + 1 |
412 ]; | 437 ]; |
413 | 438 |
| 439 // Override last match info with an array of actual substrings. |
| 440 // Used internally by replace regexp with function. |
| 441 // The array has the format of an "apply" argument for a replacement |
| 442 // function. |
| 443 var lastMatchInfoOverride = null; |
| 444 |
414 // ------------------------------------------------------------------- | 445 // ------------------------------------------------------------------- |
415 | 446 |
416 function SetupRegExp() { | 447 function SetupRegExp() { |
417 %FunctionSetInstanceClassName($RegExp, 'RegExp'); | 448 %FunctionSetInstanceClassName($RegExp, 'RegExp'); |
418 %FunctionSetPrototype($RegExp, new $Object()); | 449 %FunctionSetPrototype($RegExp, new $Object()); |
419 %SetProperty($RegExp.prototype, 'constructor', $RegExp, DONT_ENUM); | 450 %SetProperty($RegExp.prototype, 'constructor', $RegExp, DONT_ENUM); |
420 %SetCode($RegExp, RegExpConstructor); | 451 %SetCode($RegExp, RegExpConstructor); |
421 | 452 |
422 InstallFunctions($RegExp.prototype, DONT_ENUM, $Array( | 453 InstallFunctions($RegExp.prototype, DONT_ENUM, $Array( |
423 "exec", RegExpExec, | 454 "exec", RegExpExec, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); | 519 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); |
489 | 520 |
490 for (var i = 1; i < 10; ++i) { | 521 for (var i = 1; i < 10; ++i) { |
491 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D
ELETE); | 522 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D
ELETE); |
492 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); | 523 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); |
493 } | 524 } |
494 } | 525 } |
495 | 526 |
496 | 527 |
497 SetupRegExp(); | 528 SetupRegExp(); |
OLD | NEW |