re2js 2.6.1 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.d.ts","sourceRoot":"","sources":["index.esm.js"],"names":[],"mappings":"AA22CA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;IACE;;;;;;;OAOG;IACH,6BAJW,MAAM,aACN,OAAO,GACL,MAAM,CA2BlB;IACD;;;;OAIG;IACH,qBAHW,KAAK,SACL,MAAM,GAAC,MAAM,EAAE,GAAC,UAAU,EA6BpC;IAvBC;;;OAGG;IACH,cAFU,KAAK,CAEY;IAG3B,qBAAqB;IACrB,mBADW,MAAM,CACqC;IAEtD,uBAAuB;IACvB,QADW,MAAM,EAAE,CACH;IAChB,qCAAqC;IACrC,aADW,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CACC;IAClC,qBAAqB;IACrB,sBADW,MAAM,CACqC;IAUxD;;;OAGG;IACH,WAFa,KAAK,CAIjB;IAED;;;;OAIG;IACH,SAFa,OAAO,CAiBnB;IAbC,qBAAqB;IACrB,uCAAoD;IAEpD,qBAAqB;IACrB,8BAAkB;IAElB,8BAAqB;IAGrB,+BAAsB;IAEtB,+BAAmB;IAIrB;;;;OAIG;IACH,yBAHW,gBAAgB,GACd,OAAO,CASnB;IAHC,2CAAyB;IAK3B;;;;;OAKG;IACH,cAHW,MAAM,GAAC,MAAM,GACX,MAAM,CAYlB;IAED;;;;;OAKG;IACH,YAHW,MAAM,GAAC,MAAM,GACX,MAAM,CAYlB;IAED;;;;;;;;;OASG;IACH,eAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAHW,MAAM,GAAC,MAAM,GACX,MAAM,GAAC,IAAI,CAgBvB;IAED;;;;OAIG;IACH,kBAFa,MAAM,CAAC,MAAM,EAAE,MAAM,GAAC,IAAI,CAAC,CAWvC;IAED;;;;OAIG;IACH,cAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,kBAkBC;IAED;;;;;OAKG;IACH,WAFa,OAAO,CAInB;IAED;;;;;OAKG;IACH,aAFa,OAAO,CAInB;IAED;;;;;;;OAOG;IACH,aAJW,MAAM,GAAC,IAAI,GACT,OAAO,CA4BnB;IAED;;;;;;OAMG;IACH,iBAaC;IAED;;;;;OAKG;IACH,iBAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAOlB;IAED;;;OAGG;IACH,eAFa,MAAM,CAIlB;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,0BAUC;IAED;;;;OAIG;IACH,sCAgEC;IAED;;;;OAIG;IACH,oCAuGC;IAED;;;;OAIG;IACH,cAFa,MAAM,CAIlB;IAED;;;;;;;;OAQG;IACH,wBALW,MAAM,aACN,OAAO,GACL,MAAM,CAKlB;IAED;;;;;;;;OAQG;IACH,0BALW,MAAM,aACN,OAAO,GACL,MAAM,CAKlB;IAED;;;;;;;OAOG;IACH,gBAWC;CACF;AAwsMD;;;;;;;;;GASG;AACH;IACE;;OAEG;IACH,gCAAuD;IACvD;;OAEG;IACH,sBAAmC;IACnC;;;OAGG;IACH,yBAAyC;IACzC;;OAEG;IACH,sCAAmE;IACnE;;OAEG;IACH,6BAAiD;IACjD;;OAEG;IACH,2BAA6C;IAE7C;;;;;;;;;;OAUG;IACH,kBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;;;OASG;IACH,6BAJW,MAAM,aACN,OAAO,GACL,MAAM,CAIlB;IAED;;;;;;;;;;OAUG;IACH,6BAHW,MAAM,GAAC,MAAM,GACX,MAAM,CAIlB;IAED;;;;;OAKG;IACH,sBAJW,MAAM,UACN,MAAM,GACJ,KAAK,CA2BjB;IAED;;;;;;;OAOG;IACH,sBALW,MAAM,SACN,MAAM,GAAC,MAAM,EAAE,GAAC,UAAU,GACxB,OAAO,CAKnB;IAED;;;OAGG;IACH,wBAWC;IAED;;;;OAIG;IACH,qBAHW,MAAM,SACN,MAAM,EAOhB;IAHC,qBAA2B;IAE3B,mBAAuB;IAGzB;;;OAGG;IACH,cAEC;IAED;;;OAGG;IACH,SAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,WAFa,MAAM,CAIlB;IACD,WAEC;IAED;;;;;OAKG;IACH,eAHW,MAAM,GAAC,MAAM,EAAE,GAAC,UAAU,GACxB,OAAO,CAInB;IAED;;;;;OAKG;IACH,eAHW,MAAM,GAAC,MAAM,EAAE,GAAC,UAAU,GACxB,OAAO,CAOnB;IAED;;;;;;;;OAQG;IACH,YAHW,MAAM,GAAC,MAAM,EAAE,GAAC,UAAU,GACxB,OAAO,CAUnB;IAED;;;;;;;;OAQG;IACH,iBAHW,MAAM,GAAC,MAAM,EAAE,GAAC,UAAU,GACxB,OAAO,CAKnB;IAED;;;;;;;;;;;;OAYG;IACH,aAJW,MAAM,UACN,MAAM,GACJ,MAAM,EAAE,CAgDpB;IAED;;;;;;OAMG;IACH,gBAHW,MAAM,GAAC,MAAM,EAAE,GAAC,UAAU,GACxB,gBAAgB,OAAO,CAiCnC;IAED;;;OAGG;IACH,YAFa,MAAM,CAIlB;IAED;;;;;;;;;OASG;IACH,eAFa,MAAM,CAIlB;IAED;;;;;OAKG;IACH,cAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,eAFa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIlC;IAED;;;;OAIG;IACH,cAHW,GAAC,GACC,OAAO,CAUnB;CACF;AA9uOD;;GAEG;AACH;CAMC;AAxDD;IACE,8BAA8B;IAC9B,qBADY,MAAM,EAIjB;CACF;AA+DD;;GAEG;AACH;CAMC;AApBD;;GAEG;AACH;CAMC;AAaD;;GAEG;AACH;CAMC;AAjFD;;GAEG;AACH;IACE;;;OAGG;IACH,mBAHW,MAAM,UACN,MAAM,GAAC,IAAI,EAcrB;IAJC,qBAAqB;IACrB,OADW,MAAM,CACC;IAClB,0BAA0B;IAC1B,OADW,MAAM,GAAC,IAAI,CACJ;IAGpB;;;OAGG;IACH,kBAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,cAFa,MAAM,GAAC,IAAI,CAIvB;CACF;AAqhND;IACE,qBAAqB;IACrB,mBADW,MAAM,CACuB;IACxC,qBAAqB;IACrB,qBADW,MAAM,CAC2B;IAC5C,qBAAqB;IACrB,oBADW,MAAM,CACyB;IAE1C;;;;OAIG;IACH,qBAHW,MAAM,UACN,MAAM,EAiBhB;IAdC,eAAoB;IACpB,gBAAoB;IAQpB,iBAAwB;IACxB,eAAiB;IACjB,kBAAgB;IAChB,gBAAe;IACf;;;;;;aAAoB;IAGtB;;;;;;OAMG;IACH,aAJW,MAAM,GACJ,MAAM,CAoBlB;IAED;;;;OAIG;IACH,WAFa,IAAI,CAahB;IAED;;;;OAIG;IACH,aAHW,MAAM,GAAC,MAAM,EAAE,GAAC,UAAU,GACxB,MAAM,EAAE,CAoBpB;CACF;AA4nBD,kHAUC;AA1pPD;;GAEG;AACH;IACE,qBAAkD;IAClD,oBAEC;IAED;;;OAGG;IACH,kBAFa,OAAO,CAInB;IAED;;;OAGG;IACH,mBAFa,OAAO,CAInB;CACF;AAm0GD;;GAEG;AACH;IAEI,YAAc;IACd,cAAc;IAGd,eAAe;IACf,gBAAkB;IAClB,cAAc;IAKhB,sBAEC;IAGD,kBAEC;IAID,uBAEC;IAID,sBAOC;IAKD,+BAWC;IAID,oBAoBC;IAeD,8BAYC;IACD,8BAYC;IACD;;;OAGG;IACH,YAFa,MAAM,CAelB;CACF;AArxDD;IACE,gCAA4B;IAC5B,uBASC;IARC,UAAgB;IAChB,0BAA2B;IAC3B,mBAAmB;IACnB,gBAAsB;IACtB,mBAAuB;IACvB,oBAAoB;IACpB,gBAAmB;IACnB,cAAc;IAIhB;;;;aAuCC;IAGD,wBAyDC;IACD,mBAyCC;IAGD,kDA+CC;IAGD,yDA+CC;IAGD,0DAwCC;CACF"}
1
+ {"version":3,"file":"index.esm.d.ts","sourceRoot":"","sources":["index.esm.js"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  * re2js
3
3
  * RE2JS is the JavaScript port of RE2, a regular expression engine that provides linear time matching
4
4
  *
5
- * @version v2.6.1
5
+ * @version v2.7.1
6
6
  * @author Oleksii Vasyliev
7
7
  * @homepage https://github.com/le0pard/re2js#readme
8
8
  * @repository github:le0pard/re2js
@@ -2153,9 +2153,9 @@ class Inst {
2153
2153
  case Inst.NOP:
2154
2154
  return `nop -> ${this.out}`;
2155
2155
  case Inst.LB_WRITE:
2156
- return `lbwrite ${this.lb} -> ${this.out}`;
2156
+ return `lbwrite ${this.arg} -> ${this.out}`;
2157
2157
  case Inst.LB_CHECK:
2158
- return `lbcheck ${this.lb} -> ${this.out}, ${this.arg}`;
2158
+ return `lbcheck ${this.arg} -> ${this.out}`;
2159
2159
  case Inst.RUNE:
2160
2160
  if (this.runes === null) {
2161
2161
  return 'rune <null>';
@@ -2335,30 +2335,35 @@ class Machine {
2335
2335
  }
2336
2336
  this.matched = false;
2337
2337
  this.matchcap.fill(-1);
2338
+
2339
+ // Lookbehinds must scan from the beginning of the string to build their state table,
2340
+ // even if the main pattern search is requested to start mid-string.
2341
+ let currentPos = this.prog.numLb > 0 ? 0 : pos;
2342
+ let matchStartPos = pos;
2338
2343
  let runq = this.q0;
2339
2344
  let nextq = this.q1;
2340
- let r = input.step(pos);
2345
+ let r = input.step(currentPos);
2341
2346
  let rune = r >> 3;
2342
2347
  let width = r & 7;
2343
2348
  let rune1 = -1;
2344
2349
  let width1 = 0;
2345
2350
  if (r !== MachineInputBase.EOF()) {
2346
- r = input.step(pos + width);
2351
+ r = input.step(currentPos + width);
2347
2352
  rune1 = r >> 3;
2348
2353
  width1 = r & 7;
2349
2354
  }
2350
2355
  let flag;
2351
- if (pos === 0) {
2356
+ if (currentPos === 0) {
2352
2357
  flag = Utils.emptyOpContext(-1, rune);
2353
2358
  } else {
2354
- flag = input.context(pos);
2359
+ flag = input.context(currentPos);
2355
2360
  }
2356
2361
  while (true) {
2357
2362
  if (runq.isEmpty()) {
2358
- if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && pos !== 0) {
2363
+ if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && currentPos !== 0) {
2359
2364
  break;
2360
2365
  }
2361
- if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) {
2366
+ if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && currentPos !== 0) {
2362
2367
  break;
2363
2368
  }
2364
2369
  if (this.matched) {
@@ -2368,43 +2373,50 @@ class Machine {
2368
2373
  // Fast-forwarding the string pointer will skip over the positions where
2369
2374
  // the parallel lookbehind automata need to be spawned.
2370
2375
  if (this.prog.numLb === 0 && !(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
2371
- const advance = input.index(this.re2, pos);
2376
+ const advance = input.index(this.re2, currentPos);
2372
2377
  if (advance < 0) {
2373
2378
  break;
2374
2379
  }
2375
- pos += advance;
2376
- r = input.step(pos);
2380
+ currentPos += advance;
2381
+ r = input.step(currentPos);
2377
2382
  rune = r >> 3;
2378
2383
  width = r & 7;
2379
- r = input.step(pos + width);
2384
+ r = input.step(currentPos + width);
2380
2385
  rune1 = r >> 3;
2381
2386
  width1 = r & 7;
2382
2387
  }
2383
2388
  }
2384
- if (!this.matched && (pos === 0 || anchor === RE2Flags.UNANCHORED)) {
2385
- if (this.ncap > 0) {
2386
- this.matchcap[0] = pos;
2387
- }
2388
- // Spawn Lookbehind threads BEFORE the main pattern
2389
+
2390
+ // Optimize lookbehind spawning. Because lookbehinds are prefixed with `.*` by the compiler,
2391
+ // they only need to be spawned exactly once at the beginning of the string (currentPos === 0).
2392
+ if (currentPos === 0 && this.prog.numLb > 0) {
2389
2393
  for (let i = 0; i < this.prog.lbStarts.length; i++) {
2390
- this.add(runq, this.prog.lbStarts[i], pos, this.matchcap, flag, null);
2394
+ this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap, flag, null);
2395
+ }
2396
+ }
2397
+ if (!this.matched && (currentPos === 0 || anchor === RE2Flags.UNANCHORED)) {
2398
+ // ONLY spawn the main pattern if we have reached the requested search start boundary
2399
+ if (currentPos >= matchStartPos) {
2400
+ if (this.ncap > 0) {
2401
+ this.matchcap[0] = currentPos;
2402
+ }
2403
+ this.add(runq, this.prog.start, currentPos, this.matchcap, flag, null);
2391
2404
  }
2392
- this.add(runq, this.prog.start, pos, this.matchcap, flag, null);
2393
2405
  }
2394
- const nextPos = pos + width;
2406
+ const nextPos = currentPos + width;
2395
2407
  flag = input.context(nextPos);
2396
- this.step(runq, nextq, pos, nextPos, rune, flag, anchor, pos === input.endPos());
2408
+ this.step(runq, nextq, currentPos, nextPos, rune, flag, anchor, currentPos === input.endPos());
2397
2409
  if (width === 0) {
2398
2410
  break;
2399
2411
  }
2400
2412
  if (this.ncap === 0 && this.matched) {
2401
2413
  break;
2402
2414
  }
2403
- pos += width;
2415
+ currentPos += width;
2404
2416
  rune = rune1;
2405
2417
  width = width1;
2406
2418
  if (rune !== -1) {
2407
- r = input.step(pos + width);
2419
+ r = input.step(currentPos + width);
2408
2420
  rune1 = r >> 3;
2409
2421
  width1 = r & 7;
2410
2422
  }
@@ -2421,35 +2433,46 @@ class Machine {
2421
2433
  if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) {
2422
2434
  return [];
2423
2435
  }
2436
+
2437
+ // Lookbehinds must scan from the beginning of the string to build their state table,
2438
+ // even if the main pattern search is requested to start mid-string.
2439
+ let currentPos = this.prog.numLb > 0 ? 0 : pos;
2440
+ let matchStartPos = pos;
2424
2441
  let runq = this.q0;
2425
2442
  let nextq = this.q1;
2426
- let r = input.step(pos);
2443
+ let r = input.step(currentPos);
2427
2444
  let rune = r >> 3;
2428
2445
  let width = r & 7;
2429
2446
  let rune1 = -1;
2430
2447
  let width1 = 0;
2431
2448
  if (r !== MachineInputBase.EOF()) {
2432
- r = input.step(pos + width);
2449
+ r = input.step(currentPos + width);
2433
2450
  rune1 = r >> 3;
2434
2451
  width1 = r & 7;
2435
2452
  }
2436
- let flag = pos === 0 ? Utils.emptyOpContext(-1, rune) : input.context(pos);
2453
+ let flag = currentPos === 0 ? Utils.emptyOpContext(-1, rune) : input.context(currentPos);
2437
2454
  const matches = new Set();
2438
2455
  while (true) {
2439
2456
  if (runq.isEmpty()) {
2440
- if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && pos !== 0) break;
2441
- if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) {
2457
+ if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && currentPos !== 0) break;
2458
+ if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && currentPos !== 0) {
2442
2459
  break;
2443
2460
  }
2444
2461
  }
2445
- if (pos === 0 || anchor === RE2Flags.UNANCHORED) {
2446
- // Spawn Lookbehind threads BEFORE the main pattern
2462
+
2463
+ // Optimize lookbehind spawning to exactly once at BOF
2464
+ if (currentPos === 0 && this.prog.numLb > 0) {
2447
2465
  for (let i = 0; i < this.prog.lbStarts.length; i++) {
2448
- this.add(runq, this.prog.lbStarts[i], pos, this.matchcap, flag, null);
2466
+ this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap, flag, null);
2467
+ }
2468
+ }
2469
+ if (currentPos === 0 || anchor === RE2Flags.UNANCHORED) {
2470
+ // ONLY spawn the main pattern if we have reached the requested search start boundary
2471
+ if (currentPos >= matchStartPos) {
2472
+ this.add(runq, this.prog.start, currentPos, this.matchcap, flag, null);
2449
2473
  }
2450
- this.add(runq, this.prog.start, pos, this.matchcap, flag, null);
2451
2474
  }
2452
- const nextPos = pos + width;
2475
+ const nextPos = currentPos + width;
2453
2476
  flag = input.context(nextPos);
2454
2477
  for (let j = 0; j < runq.size; j++) {
2455
2478
  let t = runq.denseThreads[j];
@@ -2458,7 +2481,7 @@ class Machine {
2458
2481
  let add = false;
2459
2482
  switch (i.op) {
2460
2483
  case Inst.MATCH:
2461
- if (anchor === RE2Flags.ANCHOR_BOTH && pos !== input.endPos()) break;
2484
+ if (anchor === RE2Flags.ANCHOR_BOTH && currentPos !== input.endPos()) break;
2462
2485
  matches.add(i.arg); // Record the matched Set ID
2463
2486
  break;
2464
2487
  case Inst.RUNE:
@@ -2486,11 +2509,11 @@ class Machine {
2486
2509
  }
2487
2510
  runq.clear();
2488
2511
  if (width === 0) break;
2489
- pos += width;
2512
+ currentPos += width;
2490
2513
  rune = rune1;
2491
2514
  width = width1;
2492
2515
  if (rune !== -1) {
2493
- r = input.step(pos + width);
2516
+ r = input.step(currentPos + width);
2494
2517
  rune1 = r >> 3;
2495
2518
  width1 = r & 7;
2496
2519
  }
@@ -2594,17 +2617,17 @@ class Machine {
2594
2617
  continue;
2595
2618
  }
2596
2619
  case Inst.LB_WRITE:
2597
- this.lbTable[Math.abs(inst.lb)] = pos;
2620
+ this.lbTable[Math.abs(inst.arg)] = pos;
2598
2621
  pc = inst.out;
2599
2622
  continue;
2600
2623
  case Inst.LB_CHECK:
2601
- if (inst.lb > 0) {
2624
+ if (inst.arg > 0) {
2602
2625
  // Positive Lookbehind
2603
- if (this.lbTable[inst.lb] === pos) {
2626
+ if (this.lbTable[inst.arg] === pos) {
2604
2627
  pc = inst.out; // Flattened tail recursion
2605
2628
  continue;
2606
2629
  }
2607
- } else if (this.lbTable[-inst.lb] !== pos) {
2630
+ } else if (this.lbTable[-inst.arg] !== pos) {
2608
2631
  // Negative Lookbehind
2609
2632
  pc = inst.out; // Flattened tail recursion
2610
2633
  continue;
@@ -4684,7 +4707,7 @@ class Compiler {
4684
4707
  }
4685
4708
  lookBehind(a, lb) {
4686
4709
  const id = this.newInst(Inst.LB_WRITE);
4687
- this.prog.getInst(id.i).lb = lb;
4710
+ this.prog.getInst(id.i).arg = lb;
4688
4711
 
4689
4712
  // Create the prefix wildcard `.*` for the lookbehind automaton
4690
4713
  const any = this.rune(Compiler.ANY_RUNE(), 0);
@@ -4692,7 +4715,7 @@ class Compiler {
4692
4715
  const lbAutomaton = this.cat(dotStar, a);
4693
4716
  this.prog.patch(lbAutomaton.out, id.i);
4694
4717
  const checkId = this.newInst(Inst.LB_CHECK);
4695
- this.prog.getInst(checkId.i).lb = lb;
4718
+ this.prog.getInst(checkId.i).arg = lb;
4696
4719
 
4697
4720
  // Save the starting point of this lookbehind automaton
4698
4721
  this.prog.lbStarts.push(lbAutomaton.i);
@@ -5467,6 +5490,7 @@ class Parser {
5467
5490
  static ERR_UNEXPECTED_PAREN = 'unexpected )';
5468
5491
  static ERR_NESTING_DEPTH = 'expression nests too deeply';
5469
5492
  static ERR_LARGE = 'expression too large';
5493
+ static ERR_INVALID_CAPTURE_IN_LOOKBEHIND = 'invalid capture in lookbehind';
5470
5494
 
5471
5495
  // maxHeight is the maximum height of a regexp parse tree.
5472
5496
  // It is somewhat arbitrarily chosen, but the idea is to be large enough
@@ -5870,6 +5894,18 @@ class Parser {
5870
5894
  }
5871
5895
  return x;
5872
5896
  }
5897
+
5898
+ // recursively check for captures
5899
+ static hasCapture(re) {
5900
+ if (re === null) return false;
5901
+ if (re.op === Regexp.Op.CAPTURE) return true;
5902
+ if (re.subs) {
5903
+ for (let sub of re.subs) {
5904
+ if (Parser.hasCapture(sub)) return true;
5905
+ }
5906
+ }
5907
+ return false;
5908
+ }
5873
5909
  constructor(wholeRegexp, flags = 0) {
5874
5910
  this.wholeRegexp = wholeRegexp;
5875
5911
  // Flags control the behavior of the parser and record information about
@@ -6553,7 +6589,7 @@ class Parser {
6553
6589
  case 1:
6554
6590
  // Impossible but handle.
6555
6591
  re.op = Regexp.Op.EMPTY_MATCH;
6556
- re.subs = null;
6592
+ re.subs = Regexp.emptySubs();
6557
6593
  break;
6558
6594
  case 2:
6559
6595
  {
@@ -7004,6 +7040,9 @@ class Parser {
7004
7040
 
7005
7041
  // Handle lookbehinds
7006
7042
  if (re2.lb !== 0) {
7043
+ if (Parser.hasCapture(re1)) {
7044
+ throw new RE2JSSyntaxException(Parser.ERR_INVALID_CAPTURE_IN_LOOKBEHIND, this.wholeRegexp);
7045
+ }
7007
7046
  if (re2.lb > 0) {
7008
7047
  re2.op = Regexp.Op.PLB;
7009
7048
  } else {