Skip to content
This repository
Browse code

Improved comments; throw when addToken is given a nonnative regex.

  • Loading branch information...
commit dd9a561b64f369be5d24afc9d43244c8296b1310 1 parent 3f7b39c
Steven Levithan authored
22 src/xregexp.js
@@ -446,7 +446,7 @@ var XRegExp = (function(undefined) {
446 446 do {
447 447 // Check for custom tokens at the current position
448 448 tokenResult = runTokens(pattern, flags, pos, scope, context);
449   - // If the matched token used the `reparse` option, splice its result into the
  449 + // If the matched token used the `reparse` option, splice its output into the
450 450 // pattern before running tokens again at the same position
451 451 if (tokenResult && tokenResult.reparse) {
452 452 pattern = pattern.slice(0, pos) +
@@ -459,7 +459,7 @@ var XRegExp = (function(undefined) {
459 459 output += tokenResult.output;
460 460 pos += (tokenResult.matchLength || 1);
461 461 } else {
462   - // Check for native tokens at the current position. This could use the native
  462 + // Get the native token at the current position. This could use the native
463 463 // `exec`, except that sticky processing avoids string slicing in browsers that
464 464 // support flag y
465 465 match = self.exec(pattern, nativeTokens[scope], pos, 'sticky')[0];
@@ -536,12 +536,26 @@ var XRegExp = (function(undefined) {
536 536 * {scope: 'all'}
537 537 * );
538 538 * XRegExp('\\a[\\a-\\n]+').test('\x07\n\x07'); // -> true
  539 + *
  540 + * // Add the U (ungreedy) flag from PCRE and RE2, which reverses greedy and lazy quantifiers
  541 + * XRegExp.addToken(
  542 + * /([?*+]|{\d+(?:,\d*)?})(\??)/,
  543 + * function(match) {return match[1] + (match[2] ? '' : '?');},
  544 + * {flag: 'U'}
  545 + * );
  546 + * XRegExp('a+', 'U').exec('aaa')[0]; // -> 'a'
  547 + * XRegExp('a+?', 'U').exec('aaa')[0]; // -> 'aaa'
539 548 */
540 549 self.addToken = function(regex, handler, options) {
541 550 options = options || {};
  551 + var optionalFlags = options.optionalFlags, i;
542 552
543   - var optionalFlags = options.optionalFlags,
544   - i;
  553 + // Cannot use XRegExp regexes because the XRegExp construction process (in `runTokens`)
  554 + // uses `XRegExp.exec`, which copies regexes the first time they're used. The copying thus
  555 + // triggers an infinite loop, since it is building a new XRegExp
  556 + if (regex[REGEX_DATA] && !regex[REGEX_DATA].isNative) {
  557 + throw new Error('Cannot use XRegExp regexes with addToken');
  558 + }
545 559
546 560 if (options.flag) {
547 561 registerFlag(options.flag);
5 tests/spec/s-xregexp-methods.js
@@ -179,6 +179,11 @@ describe('XRegExp.addToken()', function() {
179 179 expect(XRegExp('\x0A').test('1x2')).toBe(true);
180 180 });
181 181
  182 + // This test is merely tracking current behavior. The current behavior is not ideal, though.
  183 + // Change this if the error is no longer necessary in future versions
  184 + it('should throw an exception when given an XRegExp as the search pattern', function() {
  185 + expect(function() {XRegExp.addToken(XRegExp('\\x0B'), function() {return 'B';});}).toThrow();
  186 + });
182 187 });
183 188
184 189 describe('XRegExp.cache()', function() {
22 xregexp-all.js
@@ -473,7 +473,7 @@ var XRegExp = (function(undefined) {
473 473 do {
474 474 // Check for custom tokens at the current position
475 475 tokenResult = runTokens(pattern, flags, pos, scope, context);
476   - // If the matched token used the `reparse` option, splice its result into the
  476 + // If the matched token used the `reparse` option, splice its output into the
477 477 // pattern before running tokens again at the same position
478 478 if (tokenResult && tokenResult.reparse) {
479 479 pattern = pattern.slice(0, pos) +
@@ -486,7 +486,7 @@ var XRegExp = (function(undefined) {
486 486 output += tokenResult.output;
487 487 pos += (tokenResult.matchLength || 1);
488 488 } else {
489   - // Check for native tokens at the current position. This could use the native
  489 + // Get the native token at the current position. This could use the native
490 490 // `exec`, except that sticky processing avoids string slicing in browsers that
491 491 // support flag y
492 492 match = self.exec(pattern, nativeTokens[scope], pos, 'sticky')[0];
@@ -563,12 +563,26 @@ var XRegExp = (function(undefined) {
563 563 * {scope: 'all'}
564 564 * );
565 565 * XRegExp('\\a[\\a-\\n]+').test('\x07\n\x07'); // -> true
  566 + *
  567 + * // Add the U (ungreedy) flag from PCRE and RE2, which reverses greedy and lazy quantifiers
  568 + * XRegExp.addToken(
  569 + * /([?*+]|{\d+(?:,\d*)?})(\??)/,
  570 + * function(match) {return match[1] + (match[2] ? '' : '?');},
  571 + * {flag: 'U'}
  572 + * );
  573 + * XRegExp('a+', 'U').exec('aaa')[0]; // -> 'a'
  574 + * XRegExp('a+?', 'U').exec('aaa')[0]; // -> 'aaa'
566 575 */
567 576 self.addToken = function(regex, handler, options) {
568 577 options = options || {};
  578 + var optionalFlags = options.optionalFlags, i;
569 579
570   - var optionalFlags = options.optionalFlags,
571   - i;
  580 + // Cannot use XRegExp regexes because the XRegExp construction process (in `runTokens`)
  581 + // uses `XRegExp.exec`, which copies regexes the first time they're used. The copying thus
  582 + // triggers an infinite loop, since it is building a new XRegExp
  583 + if (regex[REGEX_DATA] && !regex[REGEX_DATA].isNative) {
  584 + throw new Error('Cannot use XRegExp regexes with addToken');
  585 + }
572 586
573 587 if (options.flag) {
574 588 registerFlag(options.flag);

0 comments on commit dd9a561

Please sign in to comment.
Something went wrong with that request. Please try again.