@poe-platform/safe-bash 0.1.726 → 0.1.727

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.
Files changed (207) hide show
  1. package/dist/safe-bash/chunks/{chunk-6VZX7ESE.js → chunk-26N7BLXE.js} +3 -3
  2. package/dist/safe-bash/chunks/{chunk-ZZ7JQBPX.js → chunk-4A2OLEML.js} +2 -2
  3. package/dist/safe-bash/chunks/{chunk-LTREB3HX.js → chunk-54MC6XF5.js} +4 -4
  4. package/dist/safe-bash/chunks/{chunk-Z3CCN6Y2.js → chunk-6J5FUESH.js} +2 -2
  5. package/dist/safe-bash/chunks/{chunk-YR5RZBWS.js → chunk-6TBFZ5JE.js} +2 -2
  6. package/dist/safe-bash/chunks/{chunk-6HJNJ625.js → chunk-7MMYQG3P.js} +2 -2
  7. package/dist/safe-bash/chunks/{chunk-WTZZX4LV.js → chunk-A4MB2KXV.js} +2 -2
  8. package/dist/safe-bash/chunks/{chunk-EM2JW7ZH.js → chunk-ATYJKRBZ.js} +2 -2
  9. package/dist/safe-bash/chunks/{chunk-VV24PRPB.js → chunk-AZQOEGP3.js} +1050 -101
  10. package/dist/safe-bash/chunks/chunk-AZQOEGP3.js.map +7 -0
  11. package/dist/safe-bash/chunks/{chunk-EFMXWUYE.js → chunk-B6JEJ6AT.js} +2 -2
  12. package/dist/safe-bash/chunks/{chunk-JFGGQUYP.js → chunk-BFXGHT3R.js} +2 -2
  13. package/dist/safe-bash/chunks/{chunk-RP5IZOOR.js → chunk-BJYV5J65.js} +1050 -101
  14. package/dist/safe-bash/chunks/chunk-BJYV5J65.js.map +7 -0
  15. package/dist/safe-bash/chunks/{chunk-HNHOPD3P.js → chunk-DIEFWGXO.js} +46 -26
  16. package/dist/safe-bash/chunks/{chunk-HNHOPD3P.js.map → chunk-DIEFWGXO.js.map} +2 -2
  17. package/dist/safe-bash/chunks/{chunk-SME47P4B.js → chunk-DV6EZOKM.js} +46 -26
  18. package/dist/safe-bash/chunks/{chunk-SME47P4B.js.map → chunk-DV6EZOKM.js.map} +2 -2
  19. package/dist/safe-bash/chunks/{chunk-646RTREQ.js → chunk-EEDOYIPC.js} +2 -2
  20. package/dist/safe-bash/chunks/{chunk-OFAAHWL5.js → chunk-GCQ5A2T2.js} +2 -2
  21. package/dist/safe-bash/chunks/{chunk-MJW4KSKV.js → chunk-GLPJEDLY.js} +2 -2
  22. package/dist/safe-bash/chunks/{chunk-FOOJWH7J.js → chunk-GO5OKPBO.js} +4 -4
  23. package/dist/safe-bash/chunks/{chunk-5JANWFJ3.js → chunk-GWYXCCGO.js} +4 -4
  24. package/dist/safe-bash/chunks/{chunk-DPHRNHPT.js → chunk-H6KJ4L22.js} +2 -2
  25. package/dist/safe-bash/chunks/{chunk-FLX2BZBF.js → chunk-HGBYIDAK.js} +4 -4
  26. package/dist/safe-bash/chunks/{chunk-VGJIDLZM.js → chunk-KS5VSJYM.js} +15 -8
  27. package/dist/safe-bash/chunks/chunk-KS5VSJYM.js.map +7 -0
  28. package/dist/safe-bash/chunks/{chunk-PO3Z7W3A.js → chunk-MUHYGUFD.js} +4 -4
  29. package/dist/safe-bash/chunks/{chunk-5DLGYPGJ.js → chunk-PDSTXORC.js} +126 -58
  30. package/dist/safe-bash/chunks/chunk-PDSTXORC.js.map +7 -0
  31. package/dist/safe-bash/chunks/{chunk-TIHMU25L.js → chunk-PQ37GDJF.js} +3 -3
  32. package/dist/safe-bash/chunks/{chunk-OTM5RCWZ.js → chunk-QNEDWYC2.js} +15 -8
  33. package/dist/safe-bash/chunks/chunk-QNEDWYC2.js.map +7 -0
  34. package/dist/safe-bash/chunks/{chunk-LZ7FUN6K.js → chunk-RHHDOA67.js} +5 -5
  35. package/dist/safe-bash/chunks/{chunk-DSCL3VA2.js → chunk-SJ3B26XV.js} +4 -4
  36. package/dist/safe-bash/chunks/{chunk-6JBTVWHH.js → chunk-SWACYEIT.js} +5 -5
  37. package/dist/safe-bash/chunks/{chunk-7UJW7TYR.js → chunk-TD6NWAUK.js} +126 -58
  38. package/dist/safe-bash/chunks/chunk-TD6NWAUK.js.map +7 -0
  39. package/dist/safe-bash/chunks/{chunk-Q4I754TV.js → chunk-THOBFD5C.js} +2 -2
  40. package/dist/safe-bash/chunks/{chunk-XELW5O3R.js → chunk-U2STHT7S.js} +2 -2
  41. package/dist/safe-bash/chunks/{chunk-5X4SOSTT.js → chunk-UJHE5PTK.js} +2 -2
  42. package/dist/safe-bash/chunks/{chunk-B6YFFKYG.js → chunk-X4I3RHTC.js} +5 -1
  43. package/dist/safe-bash/chunks/chunk-X4I3RHTC.js.map +7 -0
  44. package/dist/safe-bash/chunks/{chunk-YOK5UHA7.js → chunk-XKXFX3RH.js} +5 -1
  45. package/dist/safe-bash/chunks/chunk-XKXFX3RH.js.map +7 -0
  46. package/dist/safe-bash/chunks/{chunk-PLCYP2E5.js → chunk-XV4K3UUF.js} +2 -2
  47. package/dist/safe-bash/commands/csplit/index.browser.js +2 -2
  48. package/dist/safe-bash/commands/factor/index.browser.js +2 -2
  49. package/dist/safe-bash/commands/getopt/index.browser.js +2 -2
  50. package/dist/safe-bash/commands/hexdump/index.browser.js +2 -2
  51. package/dist/safe-bash/commands/iconv/index.browser.js +2 -2
  52. package/dist/safe-bash/commands/internal.d.ts.map +1 -1
  53. package/dist/safe-bash/commands/internal.js +4 -3
  54. package/dist/safe-bash/commands/internal.js.map +1 -1
  55. package/dist/safe-bash/commands/line-endings/index.browser.js +2 -2
  56. package/dist/safe-bash/commands/llm/index.browser.js +4 -4
  57. package/dist/safe-bash/commands/network/index.browser.js +4 -4
  58. package/dist/safe-bash/commands/node/index.browser.js +4 -4
  59. package/dist/safe-bash/commands/pandoc/index.js.map +1 -1
  60. package/dist/safe-bash/commands/pr/index.browser.js +3 -3
  61. package/dist/safe-bash/commands/python/index.browser.js +2 -2
  62. package/dist/safe-bash/commands/record-buffer.d.ts.map +1 -1
  63. package/dist/safe-bash/commands/record-buffer.js +12 -4
  64. package/dist/safe-bash/commands/record-buffer.js.map +1 -1
  65. package/dist/safe-bash/commands/regex-execution/bounded-provider.d.ts.map +1 -1
  66. package/dist/safe-bash/commands/regex-execution/bounded-provider.js +75 -8
  67. package/dist/safe-bash/commands/regex-execution/bounded-provider.js.map +1 -1
  68. package/dist/safe-bash/commands/regex-execution/ere/limits.d.ts +1 -1
  69. package/dist/safe-bash/commands/regex-execution/ere/limits.d.ts.map +1 -1
  70. package/dist/safe-bash/commands/regex-execution/ere/limits.js +6 -4
  71. package/dist/safe-bash/commands/regex-execution/ere/limits.js.map +1 -1
  72. package/dist/safe-bash/commands/regex-execution/portable.d.ts.map +1 -1
  73. package/dist/safe-bash/commands/regex-execution/portable.js +7 -2
  74. package/dist/safe-bash/commands/regex-execution/portable.js.map +1 -1
  75. package/dist/safe-bash/commands/regex-execution/protocol.d.ts +2 -0
  76. package/dist/safe-bash/commands/regex-execution/protocol.d.ts.map +1 -1
  77. package/dist/safe-bash/commands/regex-execution/protocol.js +26 -0
  78. package/dist/safe-bash/commands/regex-execution/protocol.js.map +1 -1
  79. package/dist/safe-bash/commands/regex-execution/utf8.d.ts +1 -1
  80. package/dist/safe-bash/commands/regex-execution/utf8.d.ts.map +1 -1
  81. package/dist/safe-bash/commands/regex-execution/utf8.js +26 -2
  82. package/dist/safe-bash/commands/regex-execution/utf8.js.map +1 -1
  83. package/dist/safe-bash/commands/search/grep.d.ts.map +1 -1
  84. package/dist/safe-bash/commands/search/grep.js +109 -15
  85. package/dist/safe-bash/commands/search/grep.js.map +1 -1
  86. package/dist/safe-bash/commands/search/matcher.d.ts +1 -1
  87. package/dist/safe-bash/commands/search/matcher.d.ts.map +1 -1
  88. package/dist/safe-bash/commands/search/matcher.js +2 -0
  89. package/dist/safe-bash/commands/search/matcher.js.map +1 -1
  90. package/dist/safe-bash/commands/search/shared.d.ts.map +1 -1
  91. package/dist/safe-bash/commands/search/shared.js +23 -12
  92. package/dist/safe-bash/commands/search/shared.js.map +1 -1
  93. package/dist/safe-bash/commands/standard.d.ts.map +1 -1
  94. package/dist/safe-bash/commands/standard.js +22 -0
  95. package/dist/safe-bash/commands/standard.js.map +1 -1
  96. package/dist/safe-bash/commands/streams.d.ts.map +1 -1
  97. package/dist/safe-bash/commands/streams.js +54 -10
  98. package/dist/safe-bash/commands/streams.js.map +1 -1
  99. package/dist/safe-bash/commands/structured/input.d.ts.map +1 -1
  100. package/dist/safe-bash/commands/structured/input.js +484 -55
  101. package/dist/safe-bash/commands/structured/input.js.map +1 -1
  102. package/dist/safe-bash/commands/structured/interpreter.d.ts +3 -0
  103. package/dist/safe-bash/commands/structured/interpreter.d.ts.map +1 -1
  104. package/dist/safe-bash/commands/structured/interpreter.js +157 -1
  105. package/dist/safe-bash/commands/structured/interpreter.js.map +1 -1
  106. package/dist/safe-bash/commands/structured/jq.d.ts.map +1 -1
  107. package/dist/safe-bash/commands/structured/jq.js +50 -24
  108. package/dist/safe-bash/commands/structured/jq.js.map +1 -1
  109. package/dist/safe-bash/commands/structured/limits.d.ts +5 -0
  110. package/dist/safe-bash/commands/structured/limits.d.ts.map +1 -1
  111. package/dist/safe-bash/commands/structured/limits.js +51 -36
  112. package/dist/safe-bash/commands/structured/limits.js.map +1 -1
  113. package/dist/safe-bash/commands/structured/numbers.d.ts +1 -0
  114. package/dist/safe-bash/commands/structured/numbers.d.ts.map +1 -1
  115. package/dist/safe-bash/commands/structured/numbers.js +32 -0
  116. package/dist/safe-bash/commands/structured/numbers.js.map +1 -1
  117. package/dist/safe-bash/commands/text-programs/awk-reader.d.ts +1 -0
  118. package/dist/safe-bash/commands/text-programs/awk-reader.d.ts.map +1 -1
  119. package/dist/safe-bash/commands/text-programs/awk-reader.js +41 -5
  120. package/dist/safe-bash/commands/text-programs/awk-reader.js.map +1 -1
  121. package/dist/safe-bash/commands/text-programs/awk-retention.d.ts +1 -0
  122. package/dist/safe-bash/commands/text-programs/awk-retention.d.ts.map +1 -1
  123. package/dist/safe-bash/commands/text-programs/awk-retention.js +9 -0
  124. package/dist/safe-bash/commands/text-programs/awk-retention.js.map +1 -1
  125. package/dist/safe-bash/commands/text-programs/awk-runtime.d.ts +13 -0
  126. package/dist/safe-bash/commands/text-programs/awk-runtime.d.ts.map +1 -1
  127. package/dist/safe-bash/commands/text-programs/awk-runtime.js +421 -83
  128. package/dist/safe-bash/commands/text-programs/awk-runtime.js.map +1 -1
  129. package/dist/safe-bash/commands/text-programs/awk-values.d.ts.map +1 -1
  130. package/dist/safe-bash/commands/text-programs/awk-values.js +21 -0
  131. package/dist/safe-bash/commands/text-programs/awk-values.js.map +1 -1
  132. package/dist/safe-bash/commands/text-programs/regex.d.ts +15 -2
  133. package/dist/safe-bash/commands/text-programs/regex.d.ts.map +1 -1
  134. package/dist/safe-bash/commands/text-programs/regex.js +501 -13
  135. package/dist/safe-bash/commands/text-programs/regex.js.map +1 -1
  136. package/dist/safe-bash/commands/text-programs/sed.d.ts.map +1 -1
  137. package/dist/safe-bash/commands/text-programs/sed.js +242 -102
  138. package/dist/safe-bash/commands/text-programs/sed.js.map +1 -1
  139. package/dist/safe-bash/commands/text-programs/shared.d.ts +2 -0
  140. package/dist/safe-bash/commands/text-programs/shared.d.ts.map +1 -1
  141. package/dist/safe-bash/commands/text-programs/shared.js +36 -0
  142. package/dist/safe-bash/commands/text-programs/shared.js.map +1 -1
  143. package/dist/safe-bash/commands/text.d.ts.map +1 -1
  144. package/dist/safe-bash/commands/text.js +136 -19
  145. package/dist/safe-bash/commands/text.js.map +1 -1
  146. package/dist/safe-bash/commands/tsort/index.browser.js +2 -2
  147. package/dist/safe-bash/commands/xml/index.browser.js +5 -5
  148. package/dist/safe-bash/commands/yq/index.browser.js +5 -5
  149. package/dist/safe-bash/contracts/yield.d.ts +1 -0
  150. package/dist/safe-bash/contracts/yield.d.ts.map +1 -1
  151. package/dist/safe-bash/contracts/yield.js +3 -0
  152. package/dist/safe-bash/contracts/yield.js.map +1 -1
  153. package/dist/safe-bash/core.browser.js +1052 -256
  154. package/dist/safe-bash/core.browser.js.map +3 -3
  155. package/dist/safe-bash/plugins/composition.d.ts +1 -0
  156. package/dist/safe-bash/plugins/composition.d.ts.map +1 -1
  157. package/dist/safe-bash/plugins/composition.js +80 -2
  158. package/dist/safe-bash/plugins/composition.js.map +1 -1
  159. package/dist/safe-bash/plugins/index.d.ts.map +1 -1
  160. package/dist/safe-bash/plugins/index.js +2 -2
  161. package/dist/safe-bash/plugins/index.js.map +1 -1
  162. package/dist/safe-bash-command-fold/arguments.d.ts +1 -1
  163. package/dist/safe-bash-command-fold/contracts.d.ts +2 -1
  164. package/dist/safe-bash-command-fold/engine.d.ts +1 -1
  165. package/dist/safe-bash-command-fold/index.js +10 -8
  166. package/dist/safe-bash-command-fold/index.js.map +2 -2
  167. package/dist/safe-bash-command-sips/index.js +231 -67
  168. package/dist/safe-bash-command-sips/index.js.map +2 -2
  169. package/dist/safe-bash-command-unrtf/contracts.d.ts +5 -2
  170. package/dist/safe-bash-command-unrtf/index.js +6 -5
  171. package/dist/safe-bash-command-unrtf/index.js.map +2 -2
  172. package/dist/safe-playwright-cloudflare/browser-run-code.js +22 -6
  173. package/package.json +2 -2
  174. package/dist/safe-bash/chunks/chunk-5DLGYPGJ.js.map +0 -7
  175. package/dist/safe-bash/chunks/chunk-7UJW7TYR.js.map +0 -7
  176. package/dist/safe-bash/chunks/chunk-B6YFFKYG.js.map +0 -7
  177. package/dist/safe-bash/chunks/chunk-OTM5RCWZ.js.map +0 -7
  178. package/dist/safe-bash/chunks/chunk-RP5IZOOR.js.map +0 -7
  179. package/dist/safe-bash/chunks/chunk-VGJIDLZM.js.map +0 -7
  180. package/dist/safe-bash/chunks/chunk-VV24PRPB.js.map +0 -7
  181. package/dist/safe-bash/chunks/chunk-YOK5UHA7.js.map +0 -7
  182. /package/dist/safe-bash/chunks/{chunk-6VZX7ESE.js.map → chunk-26N7BLXE.js.map} +0 -0
  183. /package/dist/safe-bash/chunks/{chunk-ZZ7JQBPX.js.map → chunk-4A2OLEML.js.map} +0 -0
  184. /package/dist/safe-bash/chunks/{chunk-LTREB3HX.js.map → chunk-54MC6XF5.js.map} +0 -0
  185. /package/dist/safe-bash/chunks/{chunk-Z3CCN6Y2.js.map → chunk-6J5FUESH.js.map} +0 -0
  186. /package/dist/safe-bash/chunks/{chunk-YR5RZBWS.js.map → chunk-6TBFZ5JE.js.map} +0 -0
  187. /package/dist/safe-bash/chunks/{chunk-6HJNJ625.js.map → chunk-7MMYQG3P.js.map} +0 -0
  188. /package/dist/safe-bash/chunks/{chunk-WTZZX4LV.js.map → chunk-A4MB2KXV.js.map} +0 -0
  189. /package/dist/safe-bash/chunks/{chunk-EM2JW7ZH.js.map → chunk-ATYJKRBZ.js.map} +0 -0
  190. /package/dist/safe-bash/chunks/{chunk-EFMXWUYE.js.map → chunk-B6JEJ6AT.js.map} +0 -0
  191. /package/dist/safe-bash/chunks/{chunk-JFGGQUYP.js.map → chunk-BFXGHT3R.js.map} +0 -0
  192. /package/dist/safe-bash/chunks/{chunk-646RTREQ.js.map → chunk-EEDOYIPC.js.map} +0 -0
  193. /package/dist/safe-bash/chunks/{chunk-OFAAHWL5.js.map → chunk-GCQ5A2T2.js.map} +0 -0
  194. /package/dist/safe-bash/chunks/{chunk-MJW4KSKV.js.map → chunk-GLPJEDLY.js.map} +0 -0
  195. /package/dist/safe-bash/chunks/{chunk-FOOJWH7J.js.map → chunk-GO5OKPBO.js.map} +0 -0
  196. /package/dist/safe-bash/chunks/{chunk-5JANWFJ3.js.map → chunk-GWYXCCGO.js.map} +0 -0
  197. /package/dist/safe-bash/chunks/{chunk-DPHRNHPT.js.map → chunk-H6KJ4L22.js.map} +0 -0
  198. /package/dist/safe-bash/chunks/{chunk-FLX2BZBF.js.map → chunk-HGBYIDAK.js.map} +0 -0
  199. /package/dist/safe-bash/chunks/{chunk-PO3Z7W3A.js.map → chunk-MUHYGUFD.js.map} +0 -0
  200. /package/dist/safe-bash/chunks/{chunk-TIHMU25L.js.map → chunk-PQ37GDJF.js.map} +0 -0
  201. /package/dist/safe-bash/chunks/{chunk-LZ7FUN6K.js.map → chunk-RHHDOA67.js.map} +0 -0
  202. /package/dist/safe-bash/chunks/{chunk-DSCL3VA2.js.map → chunk-SJ3B26XV.js.map} +0 -0
  203. /package/dist/safe-bash/chunks/{chunk-6JBTVWHH.js.map → chunk-SWACYEIT.js.map} +0 -0
  204. /package/dist/safe-bash/chunks/{chunk-Q4I754TV.js.map → chunk-THOBFD5C.js.map} +0 -0
  205. /package/dist/safe-bash/chunks/{chunk-XELW5O3R.js.map → chunk-U2STHT7S.js.map} +0 -0
  206. /package/dist/safe-bash/chunks/{chunk-5X4SOSTT.js.map → chunk-UJHE5PTK.js.map} +0 -0
  207. /package/dist/safe-bash/chunks/{chunk-PLCYP2E5.js.map → chunk-XV4K3UUF.js.map} +0 -0
@@ -96,6 +96,8 @@ export class Pattern {
96
96
  parsed;
97
97
  anchored;
98
98
  linear = false;
99
+ literalMatch;
100
+ simpleRepeatMatch;
99
101
  backreferences = false;
100
102
  constructor(source, extended = true, ignoreCase = false, dialect = "sed", modifiers = "") {
101
103
  this.ignoreCase = ignoreCase;
@@ -110,7 +112,11 @@ export class Pattern {
110
112
  let groups = 0;
111
113
  let depth = 0;
112
114
  const closedGroups = new Set();
113
- const characterNode = (character) => ({ type: "character", accepts: candidate => ignoreCase ? candidate.toLowerCase() === character.toLowerCase() : candidate === character });
115
+ const characterNode = (character) => ({
116
+ type: "character",
117
+ ...(ignoreCase ? {} : { literal: character }),
118
+ accepts: candidate => ignoreCase ? candidate.toLowerCase() === character.toLowerCase() : candidate === character,
119
+ });
114
120
  const escaped = () => {
115
121
  const character = source[offset++];
116
122
  if (character === undefined)
@@ -305,7 +311,7 @@ export class Pattern {
305
311
  return;
306
312
  const { root, counts } = this.parsed;
307
313
  budget.step(counts.get(root) + 1);
308
- await budget.checkpoint();
314
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
309
315
  // Publish only a finished program. Cancelled or concurrent preparations own
310
316
  // separate arrays, so a failed caller cannot leave a partially patched NFA.
311
317
  const code = [];
@@ -318,7 +324,7 @@ export class Pattern {
318
324
  return;
319
325
  yield;
320
326
  if (node.type === "character") {
321
- emit({ kind: "character", accepts: node.accepts });
327
+ emit({ kind: "character", ...(node.literal !== undefined ? { literal: node.literal } : {}), accepts: node.accepts });
322
328
  return;
323
329
  }
324
330
  if (node.type === "backreference") {
@@ -396,14 +402,97 @@ export class Pattern {
396
402
  let work = 0;
397
403
  for (const ignored of compile(root)) {
398
404
  if (++work % 64 === 0) {
399
- await budget.checkpoint();
405
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
400
406
  budget.step(0);
401
407
  }
402
408
  }
403
409
  emit({ kind: "match" });
404
- await budget.checkpoint();
410
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
405
411
  budget.step(0);
406
412
  this.linear = code.every(instruction => instruction.kind === "character" || instruction.kind === "begin" || instruction.kind === "end" || instruction.kind === "match");
413
+ if (this.linear && !this.ignoreCase && this.dialect !== "jq") {
414
+ let validLiteral = true;
415
+ let anchoredStart = false;
416
+ let anchoredEnd = false;
417
+ let literalValue = "";
418
+ for (let i = 0; i < code.length - 1; i++) {
419
+ const inst = code[i];
420
+ if (inst.kind === "begin") {
421
+ if (i === 0)
422
+ anchoredStart = true;
423
+ else {
424
+ validLiteral = false;
425
+ break;
426
+ }
427
+ }
428
+ else if (inst.kind === "end") {
429
+ if (i === code.length - 2)
430
+ anchoredEnd = true;
431
+ else {
432
+ validLiteral = false;
433
+ break;
434
+ }
435
+ }
436
+ else if (inst.kind === "character" && inst.literal !== undefined) {
437
+ literalValue += inst.literal;
438
+ }
439
+ else {
440
+ validLiteral = false;
441
+ break;
442
+ }
443
+ }
444
+ if (validLiteral) {
445
+ this.literalMatch = { value: literalValue, anchoredStart, anchoredEnd, groups: [literalValue] };
446
+ }
447
+ }
448
+ else if (!this.ignoreCase && this.dialect !== "jq" && root.type === "sequence" && this.groupCount <= 1) {
449
+ let startIdx = 0;
450
+ let endIdx = root.nodes.length;
451
+ let anchoredStart = false;
452
+ let anchoredEnd = false;
453
+ if (startIdx < endIdx && root.nodes[startIdx]?.type === "begin") {
454
+ anchoredStart = true;
455
+ startIdx++;
456
+ }
457
+ if (startIdx < endIdx && root.nodes[endIdx - 1]?.type === "end") {
458
+ anchoredEnd = true;
459
+ endIdx--;
460
+ }
461
+ if (startIdx < endIdx) {
462
+ let prefix = "";
463
+ let prefixValid = true;
464
+ for (let i = startIdx; i < endIdx - 1; i++) {
465
+ const n = root.nodes[i];
466
+ if (n.type === "character" && n.literal !== undefined) {
467
+ prefix += n.literal;
468
+ }
469
+ else {
470
+ prefixValid = false;
471
+ break;
472
+ }
473
+ }
474
+ const tail = root.nodes[endIdx - 1];
475
+ const captured = tail.type === "group" && tail.index === 1 && this.groupCount === 1;
476
+ const rawInner = captured ? tail.node : this.groupCount === 0 ? tail : undefined;
477
+ const repeatNode = rawInner?.type === "sequence" && rawInner.nodes.length === 1 ? rawInner.nodes[0] : rawInner;
478
+ if (prefixValid &&
479
+ (anchoredStart || prefix.length > 0) &&
480
+ repeatNode?.type === "repeat" &&
481
+ repeatNode.minimum >= 1 &&
482
+ repeatNode.maximum === Infinity &&
483
+ !repeatNode.lazy &&
484
+ repeatNode.node.type === "character") {
485
+ this.simpleRepeatMatch = {
486
+ prefix,
487
+ anchoredStart,
488
+ anchoredEnd,
489
+ captured,
490
+ minimum: repeatNode.minimum,
491
+ accepts: repeatNode.node.accepts,
492
+ };
493
+ }
494
+ }
495
+ }
407
496
  this.backreferences = code.some(instruction => instruction.kind === "backreference");
408
497
  this.code = code;
409
498
  this.parsed = undefined;
@@ -417,7 +506,7 @@ export class Pattern {
417
506
  let checkpoints = 0;
418
507
  while (pending.length) {
419
508
  if (++checkpoints % 64 === 1)
420
- await budget.checkpoint();
509
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
421
510
  budget.step();
422
511
  const state = pending.pop();
423
512
  if (options.end !== undefined && state.position > options.end)
@@ -499,12 +588,266 @@ export class Pattern {
499
588
  }
500
589
  return undefined;
501
590
  }
591
+ canFindSync() {
592
+ return this.code.length > 0 && this.dialect !== "jq" && Boolean(this.literalMatch || this.simpleRepeatMatch);
593
+ }
594
+ findSyncFast(text, budget, from = 0) {
595
+ if (this.simpleRepeatMatch) {
596
+ const { prefix, anchoredStart, anchoredEnd, captured, minimum, accepts } = this.simpleRepeatMatch;
597
+ if (from > text.length || (anchoredStart && from > 0))
598
+ return undefined;
599
+ let found = -1;
600
+ let matchEnd = -1;
601
+ let groupStart = -1;
602
+ let groupEnd = -1;
603
+ if (anchoredStart) {
604
+ if (text.startsWith(prefix)) {
605
+ const pos = prefix.length;
606
+ let cursor = pos;
607
+ while (cursor < text.length && accepts(text[cursor]))
608
+ cursor++;
609
+ if (cursor - pos >= minimum && (!anchoredEnd || cursor === text.length)) {
610
+ found = 0;
611
+ matchEnd = cursor;
612
+ groupStart = pos;
613
+ groupEnd = cursor;
614
+ }
615
+ }
616
+ }
617
+ else {
618
+ let searchFrom = from;
619
+ while (searchFrom <= text.length - prefix.length) {
620
+ const idx = text.indexOf(prefix, searchFrom);
621
+ if (idx < 0)
622
+ break;
623
+ const pos = idx + prefix.length;
624
+ let cursor = pos;
625
+ while (cursor < text.length && accepts(text[cursor]))
626
+ cursor++;
627
+ if (cursor - pos >= minimum && (!anchoredEnd || cursor === text.length)) {
628
+ found = idx;
629
+ matchEnd = cursor;
630
+ groupStart = pos;
631
+ groupEnd = cursor;
632
+ break;
633
+ }
634
+ searchFrom = idx + 1;
635
+ }
636
+ }
637
+ const positionsTried = anchoredStart ? 1 : found >= 0 ? found - from + 1 : text.length - from + 1;
638
+ const len = found >= 0 ? matchEnd - found : 0;
639
+ budget.step(positionsTried * 2 + (found >= 0 ? this.code.length * 2 + len : 0));
640
+ if (found < 0)
641
+ return undefined;
642
+ if (len > budget.maxBufferBytes)
643
+ throw new ProgramError("text buffer limit exceeded");
644
+ const full = text.slice(found, matchEnd);
645
+ const groups = captured ? [full, text.slice(groupStart, groupEnd)] : [full];
646
+ return { start: found, end: matchEnd, groups };
647
+ }
648
+ const { value, anchoredStart, anchoredEnd, groups } = this.literalMatch;
649
+ const len = value.length;
650
+ if (from > text.length || (anchoredStart && from > 0))
651
+ return undefined;
652
+ let found = -1;
653
+ if (anchoredStart && anchoredEnd) {
654
+ if (from === 0 && text.length === len && text === value)
655
+ found = 0;
656
+ }
657
+ else if (anchoredStart) {
658
+ if (from === 0 && text.startsWith(value))
659
+ found = 0;
660
+ }
661
+ else if (anchoredEnd) {
662
+ const candidate = text.length - len;
663
+ if (candidate >= from && text.endsWith(value))
664
+ found = candidate;
665
+ }
666
+ else {
667
+ found = text.indexOf(value, from);
668
+ }
669
+ const positionsTried = anchoredStart ? 1 : found >= 0 ? found - from + 1 : text.length - from + 1;
670
+ budget.step(positionsTried * 2 + (found >= 0 ? this.code.length * 2 + len : 0));
671
+ if (found < 0)
672
+ return undefined;
673
+ if (len > budget.maxBufferBytes)
674
+ throw new ProgramError("text buffer limit exceeded");
675
+ return { start: found, end: found + len, groups };
676
+ }
677
+ tryFindSync(text, budget, from = 0) {
678
+ if (this.code.length && this.simpleRepeatMatch && this.dialect !== "jq") {
679
+ const initialCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
680
+ if (initialCheck)
681
+ return initialCheck.then(() => this.find(text, budget, from));
682
+ return this.execSimpleRepeat(text, budget, from);
683
+ }
684
+ if (!this.code.length || !this.literalMatch || this.dialect === "jq") {
685
+ return this.find(text, budget, from);
686
+ }
687
+ const initialCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
688
+ if (initialCheck)
689
+ return initialCheck.then(() => this.find(text, budget, from));
690
+ const { value, anchoredStart, anchoredEnd, groups } = this.literalMatch;
691
+ const len = value.length;
692
+ if (from > text.length || (anchoredStart && from > 0))
693
+ return undefined;
694
+ let found = -1;
695
+ if (anchoredStart && anchoredEnd) {
696
+ if (from === 0 && text.length === len && text === value)
697
+ found = 0;
698
+ }
699
+ else if (anchoredStart) {
700
+ if (from === 0 && text.startsWith(value))
701
+ found = 0;
702
+ }
703
+ else if (anchoredEnd) {
704
+ const candidate = text.length - len;
705
+ if (candidate >= from && text.endsWith(value))
706
+ found = candidate;
707
+ }
708
+ else {
709
+ found = text.indexOf(value, from);
710
+ }
711
+ const positionsTried = anchoredStart ? 1 : found >= 0 ? found - from + 1 : text.length - from + 1;
712
+ const stepCount = positionsTried * 2 + (found >= 0 ? this.code.length * 2 + len : 0);
713
+ budget.step(stepCount);
714
+ if (stepCount >= 64) {
715
+ const midCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
716
+ if (midCheck) {
717
+ if (found < 0)
718
+ return midCheck.then(() => undefined);
719
+ if (len > budget.maxBufferBytes)
720
+ throw new ProgramError("text buffer limit exceeded");
721
+ return midCheck.then(() => ({ start: found, end: found + len, groups }));
722
+ }
723
+ }
724
+ if (found < 0)
725
+ return undefined;
726
+ if (len > budget.maxBufferBytes)
727
+ throw new ProgramError("text buffer limit exceeded");
728
+ const endCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
729
+ if (endCheck)
730
+ return endCheck.then(() => ({ start: found, end: found + len, groups }));
731
+ return { start: found, end: found + len, groups };
732
+ }
733
+ execSimpleRepeat(text, budget, from) {
734
+ const { prefix, anchoredStart, anchoredEnd, captured, minimum, accepts } = this.simpleRepeatMatch;
735
+ if (from > text.length || (anchoredStart && from > 0))
736
+ return undefined;
737
+ let found = -1;
738
+ let matchEnd = -1;
739
+ let groupStart = -1;
740
+ let groupEnd = -1;
741
+ if (anchoredStart) {
742
+ if (text.startsWith(prefix)) {
743
+ const pos = prefix.length;
744
+ let cursor = pos;
745
+ while (cursor < text.length && accepts(text[cursor]))
746
+ cursor++;
747
+ if (cursor - pos >= minimum && (!anchoredEnd || cursor === text.length)) {
748
+ found = 0;
749
+ matchEnd = cursor;
750
+ groupStart = pos;
751
+ groupEnd = cursor;
752
+ }
753
+ }
754
+ }
755
+ else {
756
+ let searchFrom = from;
757
+ while (searchFrom <= text.length - prefix.length) {
758
+ const idx = text.indexOf(prefix, searchFrom);
759
+ if (idx < 0)
760
+ break;
761
+ const pos = idx + prefix.length;
762
+ let cursor = pos;
763
+ while (cursor < text.length && accepts(text[cursor]))
764
+ cursor++;
765
+ if (cursor - pos >= minimum && (!anchoredEnd || cursor === text.length)) {
766
+ found = idx;
767
+ matchEnd = cursor;
768
+ groupStart = pos;
769
+ groupEnd = cursor;
770
+ break;
771
+ }
772
+ searchFrom = idx + 1;
773
+ }
774
+ }
775
+ const positionsTried = anchoredStart ? 1 : found >= 0 ? found - from + 1 : text.length - from + 1;
776
+ const len = found >= 0 ? matchEnd - found : 0;
777
+ const stepCount = positionsTried * 2 + (found >= 0 ? this.code.length * 2 + len : 0);
778
+ budget.step(stepCount);
779
+ const finish = () => {
780
+ if (found < 0)
781
+ return undefined;
782
+ if (len > budget.maxBufferBytes)
783
+ throw new ProgramError("text buffer limit exceeded");
784
+ const full = text.slice(found, matchEnd);
785
+ const groups = captured ? [full, text.slice(groupStart, groupEnd)] : [full];
786
+ return { start: found, end: matchEnd, groups };
787
+ };
788
+ if (stepCount >= 64) {
789
+ const midCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
790
+ if (midCheck)
791
+ return midCheck.then(finish);
792
+ }
793
+ const endCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
794
+ if (endCheck)
795
+ return endCheck.then(finish);
796
+ return finish();
797
+ }
502
798
  async find(text, budget, from = 0) {
503
799
  if (!this.code.length)
504
800
  await this.prepare(budget);
505
801
  if (this.dialect === "jq")
506
802
  return (await this.findJq(text, budget, from))?.match;
507
- await budget.checkpoint();
803
+ if (this.simpleRepeatMatch) {
804
+ const initialCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
805
+ if (initialCheck)
806
+ await initialCheck;
807
+ return await this.execSimpleRepeat(text, budget, from);
808
+ }
809
+ const initialCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
810
+ if (initialCheck)
811
+ await initialCheck;
812
+ if (this.literalMatch) {
813
+ const { value, anchoredStart, anchoredEnd, groups } = this.literalMatch;
814
+ const len = value.length;
815
+ if (from > text.length || (anchoredStart && from > 0))
816
+ return undefined;
817
+ let found = -1;
818
+ if (anchoredStart && anchoredEnd) {
819
+ if (from === 0 && text.length === len && text === value)
820
+ found = 0;
821
+ }
822
+ else if (anchoredStart) {
823
+ if (from === 0 && text.startsWith(value))
824
+ found = 0;
825
+ }
826
+ else if (anchoredEnd) {
827
+ const candidate = text.length - len;
828
+ if (candidate >= from && text.endsWith(value))
829
+ found = candidate;
830
+ }
831
+ else {
832
+ found = text.indexOf(value, from);
833
+ }
834
+ const positionsTried = anchoredStart ? 1 : found >= 0 ? found - from + 1 : text.length - from + 1;
835
+ const stepCount = positionsTried * 2 + (found >= 0 ? this.code.length * 2 + len : 0);
836
+ budget.step(stepCount);
837
+ if (stepCount >= 64) {
838
+ const midCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
839
+ if (midCheck)
840
+ await midCheck;
841
+ }
842
+ if (found < 0)
843
+ return undefined;
844
+ if (len > budget.maxBufferBytes)
845
+ throw new ProgramError("text buffer limit exceeded");
846
+ const endCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
847
+ if (endCheck)
848
+ await endCheck;
849
+ return { start: found, end: found + len, groups };
850
+ }
508
851
  let units = 0;
509
852
  const work = (count = 1) => {
510
853
  budget.step(count);
@@ -512,7 +855,7 @@ export class Pattern {
512
855
  if (units < 64)
513
856
  return undefined;
514
857
  units %= 64;
515
- return budget.checkpoint();
858
+ return (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
516
859
  };
517
860
  if (this.linear) {
518
861
  for (let start = from; start <= text.length && (!this.anchored || start === 0); start++) {
@@ -535,7 +878,7 @@ export class Pattern {
535
878
  if (copied)
536
879
  await copied;
537
880
  const match = { start, end: position, groups: [text.slice(start, position)] };
538
- await budget.checkpoint();
881
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
539
882
  return match;
540
883
  }
541
884
  }
@@ -754,7 +1097,7 @@ export class Pattern {
754
1097
  const end = bestCaptures[index * 2 + 1];
755
1098
  groups.push(begin === undefined || end === undefined ? undefined : text.slice(begin, end));
756
1099
  }
757
- await budget.checkpoint();
1100
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
758
1101
  return { start: bestStart, end: bestEnd, groups };
759
1102
  }
760
1103
  return undefined;
@@ -771,7 +1114,7 @@ async function replacementLength(replacement, match, budget, available, syntax)
771
1114
  let tokens = 0;
772
1115
  for (let index = 0; index < replacement.length; index++) {
773
1116
  if (tokens++ % 256 === 0)
774
- await budget.checkpoint();
1117
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
775
1118
  budget.step();
776
1119
  const character = replacement[index];
777
1120
  let size = 1;
@@ -801,7 +1144,7 @@ async function replacementText(replacement, match, buffer, budget, syntax) {
801
1144
  let tokens = 0;
802
1145
  for (let index = 0; index < replacement.length; index++) {
803
1146
  if (tokens++ % 256 === 0)
804
- await budget.checkpoint();
1147
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
805
1148
  budget.step();
806
1149
  const character = replacement[index];
807
1150
  if (character !== "&" && (character !== "\\" || index + 1 === replacement.length))
@@ -828,7 +1171,152 @@ async function replacementText(replacement, match, buffer, budget, syntax) {
828
1171
  }
829
1172
  await buffer.append(replacement, literal);
830
1173
  }
1174
+ function expandReplacementSync(replacement, match, budget, available, syntax) {
1175
+ if (!replacement.includes("&") && !replacement.includes("\\")) {
1176
+ budget.step(replacement.length * 2 + 1);
1177
+ if (replacement.length > available)
1178
+ throw new ProgramError("text buffer limit exceeded");
1179
+ return replacement;
1180
+ }
1181
+ let out = "";
1182
+ for (let index = 0; index < replacement.length; index++) {
1183
+ budget.step();
1184
+ const character = replacement[index];
1185
+ let piece = character;
1186
+ if (character === "&") {
1187
+ budget.step();
1188
+ piece = match.groups[0] ?? "";
1189
+ }
1190
+ else if (character === "\\" && index + 1 < replacement.length) {
1191
+ budget.step();
1192
+ const next = replacement[++index];
1193
+ if (syntax === "awk") {
1194
+ piece = next === "&" || next === "\\" ? next : `\\${next}`;
1195
+ }
1196
+ else if (next >= "0" && next <= "9") {
1197
+ budget.step();
1198
+ piece = match.groups[Number(next)] ?? "";
1199
+ }
1200
+ else {
1201
+ piece = next === "n" ? "\n" : next === "t" ? "\t" : next;
1202
+ }
1203
+ }
1204
+ if (piece.length > available - out.length)
1205
+ throw new ProgramError("text buffer limit exceeded");
1206
+ out += piece;
1207
+ }
1208
+ budget.step(out.length + 1);
1209
+ return out;
1210
+ }
1211
+ export function trySubstituteSync(text, pattern, replacement, budget, global, occurrence = 1, syntax = "sed") {
1212
+ if (pattern.canFindSync() && text.length <= 4096 && replacement.length <= 256) {
1213
+ const check = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
1214
+ if (check)
1215
+ return substitute(text, pattern, replacement, budget, global, occurrence, syntax);
1216
+ let search = 0;
1217
+ let consumed = 0;
1218
+ let previousEnd = -1;
1219
+ let encountered = 0;
1220
+ let count = 0;
1221
+ let out = "";
1222
+ while (search <= text.length) {
1223
+ budget.step();
1224
+ const match = pattern.findSyncFast(text, budget, search);
1225
+ if (!match)
1226
+ break;
1227
+ if (match.start === match.end && match.start === previousEnd) {
1228
+ search = match.end + 1;
1229
+ continue;
1230
+ }
1231
+ encountered++;
1232
+ if (encountered >= occurrence) {
1233
+ const prefixLen = match.start - consumed;
1234
+ if (out.length + prefixLen > budget.maxBufferBytes) {
1235
+ throw new ProgramError("text buffer limit exceeded");
1236
+ }
1237
+ if (prefixLen > 0)
1238
+ out += text.slice(consumed, match.start);
1239
+ const rep = expandReplacementSync(replacement, match, budget, budget.maxBufferBytes - out.length, syntax);
1240
+ out += rep;
1241
+ consumed = match.end;
1242
+ count++;
1243
+ if (!global)
1244
+ break;
1245
+ }
1246
+ previousEnd = match.end;
1247
+ search = match.end === match.start ? match.end + 1 : match.end;
1248
+ }
1249
+ if (count > 0) {
1250
+ const tailLen = text.length - consumed;
1251
+ if (out.length + tailLen > budget.maxBufferBytes) {
1252
+ throw new ProgramError("text buffer limit exceeded");
1253
+ }
1254
+ if (tailLen > 0)
1255
+ out += text.slice(consumed);
1256
+ }
1257
+ else {
1258
+ out = budget.check(text);
1259
+ }
1260
+ const postCheck = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
1261
+ if (postCheck)
1262
+ return postCheck.then(() => ({ text: out, count }));
1263
+ return { text: out, count };
1264
+ }
1265
+ if (!global && occurrence === 1 && !replacement.includes("&") && !replacement.includes("\\")) {
1266
+ const check = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
1267
+ if (check)
1268
+ return substitute(text, pattern, replacement, budget, global, occurrence, syntax);
1269
+ budget.step();
1270
+ const matchOrPromise = pattern.tryFindSync(text, budget, 0);
1271
+ if (matchOrPromise instanceof Promise) {
1272
+ return matchOrPromise.then(match => {
1273
+ if (!match) {
1274
+ budget.step(0);
1275
+ return { text: budget.check(text), count: 0 };
1276
+ }
1277
+ const newLen = text.length - (match.end - match.start) + replacement.length;
1278
+ if (newLen > budget.maxBufferBytes || match.start + replacement.length > budget.maxBufferBytes) {
1279
+ throw new ProgramError("text buffer limit exceeded");
1280
+ }
1281
+ budget.step(replacement.length * 2 + 1);
1282
+ const out = (match.start === 0 ? "" : text.slice(0, match.start)) + replacement + (match.end === text.length ? "" : text.slice(match.end));
1283
+ return { text: budget.check(out), count: 1 };
1284
+ });
1285
+ }
1286
+ const match = matchOrPromise;
1287
+ if (!match) {
1288
+ budget.step(0);
1289
+ return { text: budget.check(text), count: 0 };
1290
+ }
1291
+ const newLen = text.length - (match.end - match.start) + replacement.length;
1292
+ if (newLen > budget.maxBufferBytes || match.start + replacement.length > budget.maxBufferBytes) {
1293
+ throw new ProgramError("text buffer limit exceeded");
1294
+ }
1295
+ budget.step(replacement.length * 2 + 1);
1296
+ const out = (match.start === 0 ? "" : text.slice(0, match.start)) + replacement + (match.end === text.length ? "" : text.slice(match.end));
1297
+ return { text: budget.check(out), count: 1 };
1298
+ }
1299
+ return substitute(text, pattern, replacement, budget, global, occurrence, syntax);
1300
+ }
831
1301
  export async function substitute(text, pattern, replacement, budget, global, occurrence = 1, syntax = "sed") {
1302
+ if (!global && occurrence === 1 && !replacement.includes("&") && !replacement.includes("\\")) {
1303
+ const check = (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
1304
+ if (check)
1305
+ await check;
1306
+ budget.step();
1307
+ const match = await pattern.find(text, budget, 0);
1308
+ if (!match) {
1309
+ budget.step(0);
1310
+ return { text: budget.check(text), count: 0 };
1311
+ }
1312
+ const newLen = text.length - (match.end - match.start) + replacement.length;
1313
+ if (newLen > budget.maxBufferBytes || match.start + replacement.length > budget.maxBufferBytes) {
1314
+ throw new ProgramError("text buffer limit exceeded");
1315
+ }
1316
+ budget.step(replacement.length * 2 + 1);
1317
+ const out = (match.start === 0 ? "" : text.slice(0, match.start)) + replacement + (match.end === text.length ? "" : text.slice(match.end));
1318
+ return { text: budget.check(out), count: 1 };
1319
+ }
832
1320
  let search = 0;
833
1321
  let consumed = 0;
834
1322
  let previousEnd = -1;
@@ -837,7 +1325,7 @@ export async function substitute(text, pattern, replacement, budget, global, occ
837
1325
  const result = new ReplacementBuffer(budget);
838
1326
  try {
839
1327
  while (search <= text.length) {
840
- await budget.checkpoint();
1328
+ await (budget.checkpointSync ? budget.checkpointSync() : budget.checkpoint());
841
1329
  budget.step();
842
1330
  const match = await pattern.find(text, budget, search);
843
1331
  if (!match)