@poe-platform/safe-bash 0.1.434 → 0.1.436
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.
- package/dist/safe-bash/browser.js +350 -113
- package/dist/safe-bash/browser.js.map +3 -3
- package/dist/safe-bash/commands/stream-format/nl.js +1 -1
- package/dist/safe-bash/commands/stream-format/nl.js.map +1 -1
- package/dist/safe-bash/commands/structured/interpreter.js +10 -10
- package/dist/safe-bash/commands/structured/interpreter.js.map +1 -1
- package/dist/safe-bash/commands/structured/limits.d.ts +3 -1
- package/dist/safe-bash/commands/structured/limits.d.ts.map +1 -1
- package/dist/safe-bash/commands/structured/limits.js +16 -5
- package/dist/safe-bash/commands/structured/limits.js.map +1 -1
- package/dist/safe-bash/commands/structured/values.d.ts +5 -3
- package/dist/safe-bash/commands/structured/values.d.ts.map +1 -1
- package/dist/safe-bash/commands/structured/values.js +73 -21
- package/dist/safe-bash/commands/structured/values.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-runtime.js +4 -4
- package/dist/safe-bash/commands/text-programs/awk-runtime.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/regex.d.ts +2 -1
- package/dist/safe-bash/commands/text-programs/regex.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/regex.js +230 -93
- package/dist/safe-bash/commands/text-programs/regex.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/sed.js +1 -1
- package/dist/safe-bash/commands/text-programs/sed.js.map +1 -1
- package/dist/safe-bash/portable.js +439 -148
- package/dist/safe-bash/portable.js.map +3 -3
- package/dist/safe-bash/shell/arrays/state.d.ts +6 -1
- package/dist/safe-bash/shell/arrays/state.d.ts.map +1 -1
- package/dist/safe-bash/shell/arrays/state.js +30 -3
- package/dist/safe-bash/shell/arrays/state.js.map +1 -1
- package/dist/safe-bash/shell/cleanup.d.ts +1 -1
- package/dist/safe-bash/shell/cleanup.d.ts.map +1 -1
- package/dist/safe-bash/shell/cleanup.js +7 -3
- package/dist/safe-bash/shell/cleanup.js.map +1 -1
- package/dist/safe-bash/shell/getopts.d.ts +10 -1
- package/dist/safe-bash/shell/getopts.d.ts.map +1 -1
- package/dist/safe-bash/shell/getopts.js +55 -6
- package/dist/safe-bash/shell/getopts.js.map +1 -1
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +69 -27
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/package.json +2 -2
|
@@ -9219,7 +9219,7 @@ var InvocationScope = class _InvocationScope {
|
|
|
9219
9219
|
failures;
|
|
9220
9220
|
parent;
|
|
9221
9221
|
#children = /* @__PURE__ */ new Set();
|
|
9222
|
-
#callbacks =
|
|
9222
|
+
#callbacks = /* @__PURE__ */ new Map();
|
|
9223
9223
|
#finalizers = [];
|
|
9224
9224
|
#work = /* @__PURE__ */ new Set();
|
|
9225
9225
|
#controller = new AbortController();
|
|
@@ -9246,7 +9246,11 @@ var InvocationScope = class _InvocationScope {
|
|
|
9246
9246
|
register(cleanup) {
|
|
9247
9247
|
this.assertOpen();
|
|
9248
9248
|
if (typeof cleanup !== "function") throw new TypeError("Cleanup must be callable");
|
|
9249
|
-
|
|
9249
|
+
const registration = /* @__PURE__ */ Symbol();
|
|
9250
|
+
this.#callbacks.set(registration, cleanup);
|
|
9251
|
+
return () => {
|
|
9252
|
+
this.#callbacks.delete(registration);
|
|
9253
|
+
};
|
|
9250
9254
|
}
|
|
9251
9255
|
run(operation) {
|
|
9252
9256
|
this.assertOpen();
|
|
@@ -9279,9 +9283,11 @@ var InvocationScope = class _InvocationScope {
|
|
|
9279
9283
|
close() {
|
|
9280
9284
|
if (!this.#drain) {
|
|
9281
9285
|
this.#drain = Promise.resolve().then(async () => {
|
|
9286
|
+
const callbacks = [...this.#callbacks.values()];
|
|
9287
|
+
this.#callbacks.clear();
|
|
9282
9288
|
try {
|
|
9283
9289
|
await Promise.all([
|
|
9284
|
-
...
|
|
9290
|
+
...callbacks.map((cleanup) => this.cleanup(cleanup)),
|
|
9285
9291
|
...[...this.#children].map((child) => child.close()),
|
|
9286
9292
|
...this.#work
|
|
9287
9293
|
]);
|
|
@@ -9308,6 +9314,39 @@ function throwCleanupFailures(failures) {
|
|
|
9308
9314
|
|
|
9309
9315
|
// packages/safe-bash/src/shell/getopts.ts
|
|
9310
9316
|
init_platform();
|
|
9317
|
+
var ownedInputs = /* @__PURE__ */ new WeakMap();
|
|
9318
|
+
function getoptsInputAllocationSize(argumentsCount) {
|
|
9319
|
+
return { bytes: 256 + argumentsCount * 8, slots: argumentsCount + 2 };
|
|
9320
|
+
}
|
|
9321
|
+
async function createGetoptsInput(args, allocation, controls2) {
|
|
9322
|
+
const work = new ScanWork(controls2);
|
|
9323
|
+
if (!Array.isArray(args)) throw new GetoptsError("INVALID_INPUT", "Getopts requires an argument array");
|
|
9324
|
+
const length = args.length;
|
|
9325
|
+
if (length > work.maxArguments) throw new GetoptsError("ARGUMENT_LIMIT", "Getopts argument limit exceeded");
|
|
9326
|
+
const size = getoptsInputAllocationSize(length);
|
|
9327
|
+
const reservation = allocation?.reserve(size.bytes, size.slots);
|
|
9328
|
+
try {
|
|
9329
|
+
const snapshot = [];
|
|
9330
|
+
for (let index = 0; index < length; index++) {
|
|
9331
|
+
const waiting = work.step();
|
|
9332
|
+
if (waiting) await waiting;
|
|
9333
|
+
snapshot.push(args[index]);
|
|
9334
|
+
}
|
|
9335
|
+
await work.flush();
|
|
9336
|
+
if (args.length !== length) throw new GetoptsError("INVALID_INPUT", "Getopts argument extent changed during admission");
|
|
9337
|
+
const input3 = Object.freeze({ args: Object.freeze(snapshot) });
|
|
9338
|
+
reservation?.commit(input3);
|
|
9339
|
+
ownedInputs.set(input3, {});
|
|
9340
|
+
return input3;
|
|
9341
|
+
} catch (error) {
|
|
9342
|
+
try {
|
|
9343
|
+
reservation?.release();
|
|
9344
|
+
} catch (cleanup) {
|
|
9345
|
+
throw new AggregateError([error, cleanup], "Getopts input allocation and release failed");
|
|
9346
|
+
}
|
|
9347
|
+
throw error;
|
|
9348
|
+
}
|
|
9349
|
+
}
|
|
9311
9350
|
var GetoptsError = class extends Error {
|
|
9312
9351
|
constructor(code, message2) {
|
|
9313
9352
|
super(message2);
|
|
@@ -9372,6 +9411,9 @@ var ScanWork = class {
|
|
|
9372
9411
|
check() {
|
|
9373
9412
|
this.signal?.throwIfAborted();
|
|
9374
9413
|
}
|
|
9414
|
+
get inputBytes() {
|
|
9415
|
+
return this.bytes;
|
|
9416
|
+
}
|
|
9375
9417
|
step() {
|
|
9376
9418
|
this.check();
|
|
9377
9419
|
if (this.steps === this.maxSteps) throw new GetoptsError("STEP_LIMIT", "Getopts work step limit exceeded");
|
|
@@ -9428,19 +9470,25 @@ async function validateString(value2, work, optstring = false) {
|
|
|
9428
9470
|
else work.addBytes(3);
|
|
9429
9471
|
}
|
|
9430
9472
|
}
|
|
9431
|
-
async function scanGetopts(state, optstring,
|
|
9473
|
+
async function scanGetopts(state, optstring, input3, options3) {
|
|
9432
9474
|
if (!record2(options3) || typeof options3.reportErrors !== "boolean") throw new GetoptsError("INVALID_INPUT", "Getopts requires explicit diagnostic policy and work controls");
|
|
9433
9475
|
const work = new ScanWork(options3.work);
|
|
9434
9476
|
const original = cloneGetoptsState(state);
|
|
9477
|
+
const owned = ownedInputs.get(input3);
|
|
9478
|
+
const args = owned ? input3.args : input3;
|
|
9435
9479
|
if (!Array.isArray(args)) throw new GetoptsError("INVALID_INPUT", "Getopts requires an argument array");
|
|
9436
9480
|
if (args.length > work.maxArguments) throw new GetoptsError("ARGUMENT_LIMIT", "Getopts argument limit exceeded");
|
|
9437
9481
|
const starting = work.step();
|
|
9438
9482
|
if (starting) await starting;
|
|
9439
9483
|
await validateString(optstring, work, true);
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9484
|
+
const specificationBytes = work.inputBytes;
|
|
9485
|
+
if (owned?.bytes !== void 0) work.addBytes(owned.bytes);
|
|
9486
|
+
else {
|
|
9487
|
+
for (let argument = 0; argument < args.length; argument++) {
|
|
9488
|
+
const waiting = work.step();
|
|
9489
|
+
if (waiting) await waiting;
|
|
9490
|
+
await validateString(args[argument], work);
|
|
9491
|
+
}
|
|
9444
9492
|
}
|
|
9445
9493
|
const silent = optstring.startsWith(":");
|
|
9446
9494
|
const specification = new Int8Array(128).fill(-1);
|
|
@@ -9456,6 +9504,7 @@ async function scanGetopts(state, optstring, args, options3) {
|
|
|
9456
9504
|
const waiting = work.step();
|
|
9457
9505
|
if (waiting) await waiting;
|
|
9458
9506
|
await work.flush();
|
|
9507
|
+
if (owned) owned.bytes = work.inputBytes - specificationBytes;
|
|
9459
9508
|
return { state: active === void 0 ? { index } : { index, active: { ...active } }, kind, status: kind === "end" ? 1 : 0, option: option2, optind: index, argument, diagnostic: diagnostic3 };
|
|
9460
9509
|
};
|
|
9461
9510
|
const end = () => {
|
|
@@ -10603,7 +10652,7 @@ var StateMonitor = class {
|
|
|
10603
10652
|
monitors.set(raw, this);
|
|
10604
10653
|
monitors.set(this.proxy, this);
|
|
10605
10654
|
if (session.monitors) session.monitors.add(this);
|
|
10606
|
-
else session.scope.register(async () => {
|
|
10655
|
+
else this.#retireCleanup = session.scope.register(async () => {
|
|
10607
10656
|
await session.scope.drainWork();
|
|
10608
10657
|
this.closeValues();
|
|
10609
10658
|
});
|
|
@@ -10622,18 +10671,46 @@ var StateMonitor = class {
|
|
|
10622
10671
|
#internalEnrollment;
|
|
10623
10672
|
#restorations;
|
|
10624
10673
|
#overlays;
|
|
10674
|
+
#retireCleanup;
|
|
10675
|
+
#positionalRevision = {};
|
|
10676
|
+
#getoptsInput;
|
|
10625
10677
|
closeValues() {
|
|
10626
10678
|
this.values.close();
|
|
10627
10679
|
this.positionals.close();
|
|
10680
|
+
this.invalidateGetoptsInput();
|
|
10681
|
+
this.#retireCleanup?.();
|
|
10682
|
+
this.#retireCleanup = void 0;
|
|
10683
|
+
}
|
|
10684
|
+
get positionalRevision() {
|
|
10685
|
+
return this.#positionalRevision;
|
|
10686
|
+
}
|
|
10687
|
+
get getoptsInput() {
|
|
10688
|
+
return this.#getoptsInput?.input;
|
|
10689
|
+
}
|
|
10690
|
+
retainGetoptsInput(revision, input3, allocation) {
|
|
10691
|
+
this.session.scope.assertOpen();
|
|
10692
|
+
if (revision !== this.#positionalRevision) return false;
|
|
10693
|
+
this.#getoptsInput?.allocation.close();
|
|
10694
|
+
this.#getoptsInput = { input: input3, allocation };
|
|
10695
|
+
return true;
|
|
10696
|
+
}
|
|
10697
|
+
invalidateGetoptsInput() {
|
|
10698
|
+
this.#getoptsInput?.allocation.close();
|
|
10699
|
+
this.#getoptsInput = void 0;
|
|
10700
|
+
this.#positionalRevision = {};
|
|
10628
10701
|
}
|
|
10629
10702
|
changedValue(target, field, key) {
|
|
10630
10703
|
if (field === "state") {
|
|
10631
10704
|
if (key === "variables") this.values.invalidate();
|
|
10632
|
-
if (key === "positional")
|
|
10705
|
+
if (key === "positional") {
|
|
10706
|
+
this.positionals.invalidate();
|
|
10707
|
+
this.invalidateGetoptsInput();
|
|
10708
|
+
}
|
|
10633
10709
|
} else if (field === "variables" && (this.raw.variables === target || this.raw.variables === this.#wrapped.get(target))) {
|
|
10634
10710
|
this.values.invalidate(String(key));
|
|
10635
10711
|
} else if (field === "positional" && (this.raw.positional === target || this.raw.positional === this.#wrapped.get(target))) {
|
|
10636
10712
|
this.positionals.invalidate();
|
|
10713
|
+
this.invalidateGetoptsInput();
|
|
10637
10714
|
}
|
|
10638
10715
|
}
|
|
10639
10716
|
internalOwner() {
|
|
@@ -12592,7 +12669,7 @@ var InvocationCancellationOwner = class {
|
|
|
12592
12669
|
this.finalized = new Promise((resolve) => {
|
|
12593
12670
|
this.#resolveFinalized = resolve;
|
|
12594
12671
|
});
|
|
12595
|
-
parent.register(async () => {
|
|
12672
|
+
this.#retireCleanup = parent.register(async () => {
|
|
12596
12673
|
this.requestClose();
|
|
12597
12674
|
await this.finalized;
|
|
12598
12675
|
});
|
|
@@ -12602,6 +12679,7 @@ var InvocationCancellationOwner = class {
|
|
|
12602
12679
|
#failures;
|
|
12603
12680
|
#outcomes;
|
|
12604
12681
|
#publicPromise;
|
|
12682
|
+
#retireCleanup;
|
|
12605
12683
|
#resolveFinalized;
|
|
12606
12684
|
#admissionOpen = true;
|
|
12607
12685
|
#boundary;
|
|
@@ -12678,6 +12756,7 @@ var InvocationCancellationOwner = class {
|
|
|
12678
12756
|
this.#outcomes.discard(this.#record);
|
|
12679
12757
|
this.#closeBoundary();
|
|
12680
12758
|
this.#resolveFinalized();
|
|
12759
|
+
this.#retireCleanup();
|
|
12681
12760
|
}
|
|
12682
12761
|
}
|
|
12683
12762
|
async #finishOnce(barrier, captured) {
|
|
@@ -12690,6 +12769,7 @@ var InvocationCancellationOwner = class {
|
|
|
12690
12769
|
return selection;
|
|
12691
12770
|
} finally {
|
|
12692
12771
|
this.#resolveFinalized();
|
|
12772
|
+
this.#retireCleanup();
|
|
12693
12773
|
}
|
|
12694
12774
|
}
|
|
12695
12775
|
#closeBoundary() {
|
|
@@ -14044,10 +14124,18 @@ var Runtime = class _Runtime {
|
|
|
14044
14124
|
if (--file.references === 0 && this.outputFiles.get(path) === file) this.outputFiles.delete(path);
|
|
14045
14125
|
};
|
|
14046
14126
|
let target2;
|
|
14127
|
+
let outputScope;
|
|
14047
14128
|
try {
|
|
14048
|
-
|
|
14129
|
+
outputScope = io[invocationScope].child();
|
|
14130
|
+
target2 = await openFileOutput({ fs: this.fs, signal: this.signal, registerCleanup: (cleanup) => {
|
|
14131
|
+
outputScope.register(cleanup);
|
|
14132
|
+
} }, path, append ? "a" : "w", random ? incremental : void 0);
|
|
14049
14133
|
} catch (error) {
|
|
14050
|
-
|
|
14134
|
+
try {
|
|
14135
|
+
await outputScope?.close();
|
|
14136
|
+
} finally {
|
|
14137
|
+
release();
|
|
14138
|
+
}
|
|
14051
14139
|
throw error;
|
|
14052
14140
|
}
|
|
14053
14141
|
outputs.add(async (completion) => {
|
|
@@ -14063,7 +14151,11 @@ var Runtime = class _Runtime {
|
|
|
14063
14151
|
}
|
|
14064
14152
|
}
|
|
14065
14153
|
} finally {
|
|
14066
|
-
|
|
14154
|
+
try {
|
|
14155
|
+
await outputScope?.close();
|
|
14156
|
+
} finally {
|
|
14157
|
+
release();
|
|
14158
|
+
}
|
|
14067
14159
|
}
|
|
14068
14160
|
});
|
|
14069
14161
|
const output2 = this.budget.sink(target2.sink, this.signal);
|
|
@@ -14304,7 +14396,9 @@ var Runtime = class _Runtime {
|
|
|
14304
14396
|
fs: this.fs,
|
|
14305
14397
|
signal: this.commandSignal,
|
|
14306
14398
|
executionScope: this.budget.executionScope,
|
|
14307
|
-
registerCleanup: (cleanup) =>
|
|
14399
|
+
registerCleanup: (cleanup) => {
|
|
14400
|
+
scope.register(cleanup);
|
|
14401
|
+
},
|
|
14308
14402
|
invoke: (name3, args, options3) => {
|
|
14309
14403
|
const invocation = this.invoke(name3, args, options3, context, state, scope);
|
|
14310
14404
|
void invocation.catch(() => void 0);
|
|
@@ -14911,7 +15005,9 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
14911
15005
|
stdout: this.budget.sink(incoming.stdout, runtime.signal),
|
|
14912
15006
|
stderr: this.budget.sink(incoming.stderr, runtime.signal),
|
|
14913
15007
|
signal: this.commandSignal,
|
|
14914
|
-
registerCleanup: (cleanup) =>
|
|
15008
|
+
registerCleanup: (cleanup) => {
|
|
15009
|
+
scope.register(cleanup);
|
|
15010
|
+
},
|
|
14915
15011
|
invoke: (name2, args, options3) => {
|
|
14916
15012
|
const invocation = invocationOverride.current ? invocationOverride.current(name2, args, options3) : runtime.invoke(name2, args, options3, context, child, scope);
|
|
14917
15013
|
void invocation.catch(() => void 0);
|
|
@@ -15489,26 +15585,49 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
15489
15585
|
}
|
|
15490
15586
|
const optstring = context.args[offset];
|
|
15491
15587
|
const name2 = context.args[offset + 1];
|
|
15492
|
-
const
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
const
|
|
15500
|
-
|
|
15501
|
-
|
|
15588
|
+
const explicit = context.args.length > offset + 2;
|
|
15589
|
+
const monitor = explicit ? void 0 : stateMonitor(state);
|
|
15590
|
+
const revision = monitor?.positionalRevision;
|
|
15591
|
+
const supplied = explicit ? context.args.slice(offset + 2) : state.positional;
|
|
15592
|
+
if (supplied.length > fields) this.budget.fail("maxExpansionFields");
|
|
15593
|
+
const maxBytes = saturatedProduct(bytes2, saturatedSum(supplied.length, 1));
|
|
15594
|
+
const maxSteps = saturatedSum(saturatedProduct(maxBytes, 2), saturatedSum(supplied.length, 2));
|
|
15595
|
+
const work = { maxArguments: fields, maxBytes, maxSteps, yieldEvery: 128, signal: this.signal, checkpoint };
|
|
15596
|
+
let input3 = monitor?.getoptsInput;
|
|
15597
|
+
let allocation;
|
|
15502
15598
|
let result;
|
|
15503
15599
|
try {
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
|
|
15507
|
-
|
|
15508
|
-
|
|
15600
|
+
if (!input3 && monitor) {
|
|
15601
|
+
const size = getoptsInputAllocationSize(supplied.length);
|
|
15602
|
+
const arena = this.budget.values;
|
|
15603
|
+
const usage = arena.usage;
|
|
15604
|
+
if (size.bytes + 64 <= arena.maximumBytes - usage.bytes && size.slots + 1 <= arena.maximumSlots - usage.slots) {
|
|
15605
|
+
allocation = arena.scope();
|
|
15606
|
+
input3 = await createGetoptsInput(supplied, allocation, work);
|
|
15607
|
+
}
|
|
15608
|
+
}
|
|
15609
|
+
const args = input3?.args ?? supplied;
|
|
15610
|
+
if (!input3 || allocation) for (let index = 0; index < args.length; index++) {
|
|
15611
|
+
this.signal.throwIfAborted();
|
|
15612
|
+
admit2(args[index]);
|
|
15613
|
+
if ((index + 1) % 128 === 0) await checkpoint();
|
|
15614
|
+
}
|
|
15615
|
+
state.getopts ??= cloneGetoptsBinding(state);
|
|
15616
|
+
try {
|
|
15617
|
+
result = await scanGetopts(state.getopts.cursor, optstring, input3 ?? args, {
|
|
15618
|
+
reportErrors: state.variables.OPTERR === void 0 || state.variables.OPTERR === "" || decimalIndex(state.variables.OPTERR) !== 0,
|
|
15619
|
+
work
|
|
15620
|
+
});
|
|
15621
|
+
} catch (error) {
|
|
15622
|
+
this.signal.throwIfAborted();
|
|
15623
|
+
if (error instanceof GetoptsError && (error.code === "NON_ASCII_OPTION" || error.code === "INVALID_INPUT")) throw new CommandFailure(`getopts: ${error.message}`, 2);
|
|
15624
|
+
throw error;
|
|
15625
|
+
}
|
|
15509
15626
|
this.signal.throwIfAborted();
|
|
15510
|
-
if (
|
|
15511
|
-
|
|
15627
|
+
if (monitor && monitor.positionalRevision !== revision) throw new CommandFailure("getopts: positional arguments changed during validation", 2);
|
|
15628
|
+
if (allocation && monitor.retainGetoptsInput(revision, input3, allocation)) allocation = void 0;
|
|
15629
|
+
} finally {
|
|
15630
|
+
allocation?.close();
|
|
15512
15631
|
}
|
|
15513
15632
|
this.signal.throwIfAborted();
|
|
15514
15633
|
state.getopts.cursor = result.state;
|
|
@@ -18829,10 +18948,32 @@ function extendedSource(source) {
|
|
|
18829
18948
|
}
|
|
18830
18949
|
return result;
|
|
18831
18950
|
}
|
|
18951
|
+
var NfaStorage = class {
|
|
18952
|
+
constructor(budget) {
|
|
18953
|
+
this.budget = budget;
|
|
18954
|
+
}
|
|
18955
|
+
budget;
|
|
18956
|
+
used = 0;
|
|
18957
|
+
reserve(bytes2) {
|
|
18958
|
+
this.budget.step(0);
|
|
18959
|
+
if (!Number.isSafeInteger(bytes2) || bytes2 < 0 || bytes2 > this.budget.maxBufferBytes - this.used) {
|
|
18960
|
+
throw new ProgramError("regular expression state buffer limit exceeded");
|
|
18961
|
+
}
|
|
18962
|
+
this.used += bytes2;
|
|
18963
|
+
}
|
|
18964
|
+
release(bytes2) {
|
|
18965
|
+
if (!Number.isSafeInteger(bytes2) || bytes2 < 0 || bytes2 > this.used) throw new ProgramError("invalid regular expression state accounting");
|
|
18966
|
+
this.used -= bytes2;
|
|
18967
|
+
}
|
|
18968
|
+
clear() {
|
|
18969
|
+
this.used = 0;
|
|
18970
|
+
}
|
|
18971
|
+
};
|
|
18832
18972
|
var Pattern = class {
|
|
18833
18973
|
groupCount;
|
|
18834
18974
|
code = [];
|
|
18835
18975
|
anchored;
|
|
18976
|
+
linear;
|
|
18836
18977
|
constructor(source, extended = true, ignoreCase = false) {
|
|
18837
18978
|
if (source.length > 8192) throw new ProgramError("regular expression exceeds 8192 bytes");
|
|
18838
18979
|
if (!extended) source = extendedSource(source);
|
|
@@ -18999,92 +19140,188 @@ var Pattern = class {
|
|
|
18999
19140
|
};
|
|
19000
19141
|
compile(root);
|
|
19001
19142
|
emit({ kind: "match" });
|
|
19143
|
+
this.linear = this.code.every((instruction) => instruction.kind === "character" || instruction.kind === "begin" || instruction.kind === "end" || instruction.kind === "match");
|
|
19002
19144
|
}
|
|
19003
|
-
find(text, budget, from = 0) {
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
|
|
19009
|
-
|
|
19010
|
-
|
|
19011
|
-
|
|
19012
|
-
|
|
19013
|
-
|
|
19014
|
-
|
|
19015
|
-
|
|
19016
|
-
|
|
19017
|
-
|
|
19018
|
-
|
|
19019
|
-
return false;
|
|
19020
|
-
};
|
|
19021
|
-
for (let position = start; positions.size && position <= text.length; position++) {
|
|
19022
|
-
budget.step();
|
|
19023
|
-
const pending = positions.get(position)?.reverse() ?? [];
|
|
19024
|
-
positions.delete(position);
|
|
19025
|
-
queued -= pending.length;
|
|
19026
|
-
const visited = /* @__PURE__ */ new Set();
|
|
19027
|
-
let stateBytes = 0;
|
|
19028
|
-
const enqueue = (destination, thread) => {
|
|
19029
|
-
if (destination === position) pending.push(thread);
|
|
19030
|
-
else {
|
|
19031
|
-
const waiting = positions.get(destination);
|
|
19032
|
-
if (waiting) waiting.push(thread);
|
|
19033
|
-
else positions.set(destination, [thread]);
|
|
19034
|
-
queued++;
|
|
19035
|
-
}
|
|
19036
|
-
if ((queued + pending.length) * (32 + this.groupCount * 16) > budget.maxBufferBytes) throw new ProgramError("regular expression state buffer limit exceeded");
|
|
19037
|
-
};
|
|
19038
|
-
while (pending.length) {
|
|
19039
|
-
budget.step();
|
|
19040
|
-
const thread = pending.pop();
|
|
19041
|
-
const state = this.groupCount ? `${thread.pc}:${thread.captures.join(",")}` : thread.pc;
|
|
19042
|
-
if (visited.has(state)) continue;
|
|
19043
|
-
visited.add(state);
|
|
19044
|
-
stateBytes += typeof state === "string" ? state.length * 2 + 32 : 16;
|
|
19045
|
-
if (stateBytes > budget.maxBufferBytes) throw new ProgramError("regular expression state buffer limit exceeded");
|
|
19046
|
-
const instruction = this.code[thread.pc];
|
|
19145
|
+
async find(text, budget, from = 0) {
|
|
19146
|
+
await budget.checkpoint();
|
|
19147
|
+
let units = 0;
|
|
19148
|
+
const work = (count2 = 1) => {
|
|
19149
|
+
budget.step(count2);
|
|
19150
|
+
units += count2;
|
|
19151
|
+
if (units < 64) return void 0;
|
|
19152
|
+
units %= 64;
|
|
19153
|
+
return budget.checkpoint();
|
|
19154
|
+
};
|
|
19155
|
+
if (this.linear) {
|
|
19156
|
+
for (let start = from; start <= text.length && (!this.anchored || start === 0); start++) {
|
|
19157
|
+
let position = start;
|
|
19158
|
+
for (const instruction of this.code) {
|
|
19159
|
+
const paused = work(2);
|
|
19160
|
+
if (paused) await paused;
|
|
19047
19161
|
if (instruction.kind === "character") {
|
|
19048
|
-
if (position
|
|
19049
|
-
|
|
19050
|
-
|
|
19051
|
-
|
|
19052
|
-
if (
|
|
19053
|
-
|
|
19054
|
-
|
|
19055
|
-
|
|
19056
|
-
|
|
19057
|
-
|
|
19058
|
-
|
|
19059
|
-
|
|
19060
|
-
|
|
19162
|
+
if (position >= text.length || !instruction.accepts(text[position])) break;
|
|
19163
|
+
position++;
|
|
19164
|
+
} else if (instruction.kind === "begin" && position !== 0 || instruction.kind === "end" && position !== text.length) break;
|
|
19165
|
+
else if (instruction.kind === "match") {
|
|
19166
|
+
if (position - start > budget.maxBufferBytes) throw new ProgramError("text buffer limit exceeded");
|
|
19167
|
+
const copied = work(position - start);
|
|
19168
|
+
if (copied) await copied;
|
|
19169
|
+
const match = { start, end: position, groups: [text.slice(start, position)] };
|
|
19170
|
+
await budget.checkpoint();
|
|
19171
|
+
return match;
|
|
19172
|
+
}
|
|
19173
|
+
}
|
|
19174
|
+
}
|
|
19175
|
+
return void 0;
|
|
19176
|
+
}
|
|
19177
|
+
const storage = new NfaStorage(budget);
|
|
19178
|
+
const positionDigits = String(text.length).length;
|
|
19179
|
+
const instructionDigits = String(this.code.length).length;
|
|
19180
|
+
try {
|
|
19181
|
+
for (let start = from; start <= text.length && (!this.anchored || start === 0); start++) {
|
|
19182
|
+
storage.reserve(256);
|
|
19183
|
+
const positions = /* @__PURE__ */ new Map([[start, [{ pc: 0, captures: [], bytes: 64 }]]]);
|
|
19184
|
+
let bestEnd;
|
|
19185
|
+
let bestCaptures = [];
|
|
19186
|
+
let bestBytes = 0;
|
|
19187
|
+
try {
|
|
19188
|
+
for (let position = start; positions.size && position <= text.length; position++) {
|
|
19189
|
+
const advanced = work();
|
|
19190
|
+
if (advanced) await advanced;
|
|
19191
|
+
const pending = positions.get(position);
|
|
19192
|
+
if (!pending) continue;
|
|
19193
|
+
const reversed = work(pending.length);
|
|
19194
|
+
if (reversed) await reversed;
|
|
19195
|
+
pending.reverse();
|
|
19196
|
+
positions.delete(position);
|
|
19197
|
+
const visited = /* @__PURE__ */ new Set();
|
|
19198
|
+
let stateBytes = 0;
|
|
19199
|
+
const enqueue = (destination, pc, captures, saveSlot) => {
|
|
19200
|
+
const length = saveSlot === void 0 ? captures.length : Math.max(captures.length, saveSlot + 1);
|
|
19201
|
+
const bytes2 = 64 + length * 8;
|
|
19202
|
+
const waiting = destination === position ? pending : positions.get(destination);
|
|
19203
|
+
storage.reserve(bytes2 + (waiting ? 0 : 64));
|
|
19204
|
+
const saved = saveSlot === void 0 ? captures : [...captures];
|
|
19205
|
+
if (saveSlot !== void 0) saved[saveSlot] = position;
|
|
19206
|
+
const thread = { pc, captures: saved, bytes: bytes2 };
|
|
19207
|
+
if (waiting) waiting.push(thread);
|
|
19208
|
+
else positions.set(destination, [thread]);
|
|
19209
|
+
};
|
|
19210
|
+
while (pending.length) {
|
|
19211
|
+
const paused = work();
|
|
19212
|
+
if (paused) await paused;
|
|
19213
|
+
const thread = pending.pop();
|
|
19214
|
+
try {
|
|
19215
|
+
let state = thread.pc;
|
|
19216
|
+
let bytes2 = 32;
|
|
19217
|
+
if (this.groupCount) {
|
|
19218
|
+
const joinedLength = Math.max(0, thread.captures.length - 1) + thread.captures.length * positionDigits;
|
|
19219
|
+
const stateLength = instructionDigits + 1 + joinedLength;
|
|
19220
|
+
const serialized = work(stateLength);
|
|
19221
|
+
if (serialized) await serialized;
|
|
19222
|
+
const reserved = 32 + joinedLength * 2 + 64 + stateLength * 2;
|
|
19223
|
+
storage.reserve(reserved);
|
|
19224
|
+
state = `${thread.pc}:${thread.captures.join(",")}`;
|
|
19225
|
+
bytes2 = 64 + state.length * 2;
|
|
19226
|
+
storage.release(reserved - bytes2);
|
|
19227
|
+
} else storage.reserve(bytes2);
|
|
19228
|
+
if (visited.has(state)) {
|
|
19229
|
+
storage.release(bytes2);
|
|
19230
|
+
continue;
|
|
19231
|
+
}
|
|
19232
|
+
visited.add(state);
|
|
19233
|
+
stateBytes += bytes2;
|
|
19234
|
+
const instruction = this.code[thread.pc];
|
|
19235
|
+
if (instruction.kind === "character") {
|
|
19236
|
+
if (position < text.length && instruction.accepts(text[position])) enqueue(position + 1, thread.pc + 1, thread.captures);
|
|
19237
|
+
} else if (instruction.kind === "backreference") {
|
|
19238
|
+
const begin = thread.captures[instruction.index * 2];
|
|
19239
|
+
const end = thread.captures[instruction.index * 2 + 1];
|
|
19240
|
+
if (begin === void 0 || end === void 0 || position + end - begin > text.length) continue;
|
|
19241
|
+
let matches = true;
|
|
19242
|
+
for (let offset = 0; offset < end - begin; offset++) {
|
|
19243
|
+
const compared = work();
|
|
19244
|
+
if (compared) await compared;
|
|
19245
|
+
const expected = text[begin + offset];
|
|
19246
|
+
const actual = text[position + offset];
|
|
19247
|
+
if (instruction.ignoreCase ? expected.toLowerCase() !== actual.toLowerCase() : expected !== actual) {
|
|
19248
|
+
matches = false;
|
|
19249
|
+
break;
|
|
19250
|
+
}
|
|
19251
|
+
}
|
|
19252
|
+
if (matches) enqueue(position + end - begin, thread.pc + 1, thread.captures);
|
|
19253
|
+
} else if (instruction.kind === "match") {
|
|
19254
|
+
let preferred2 = bestEnd === void 0 || position > bestEnd;
|
|
19255
|
+
if (position === bestEnd) for (let index = 1; index <= this.groupCount; index++) {
|
|
19256
|
+
const compared = work();
|
|
19257
|
+
if (compared) await compared;
|
|
19258
|
+
const begin = thread.captures[index * 2];
|
|
19259
|
+
const end = thread.captures[index * 2 + 1];
|
|
19260
|
+
const priorBegin = bestCaptures[index * 2];
|
|
19261
|
+
const priorEnd = bestCaptures[index * 2 + 1];
|
|
19262
|
+
const length = begin === void 0 || end === void 0 ? -1 : end - begin;
|
|
19263
|
+
const priorLength = priorBegin === void 0 || priorEnd === void 0 ? -1 : priorEnd - priorBegin;
|
|
19264
|
+
if (length !== priorLength) {
|
|
19265
|
+
preferred2 = length > priorLength;
|
|
19266
|
+
break;
|
|
19267
|
+
}
|
|
19268
|
+
}
|
|
19269
|
+
if (preferred2) {
|
|
19270
|
+
const retained = 32 + thread.captures.length * 8;
|
|
19271
|
+
storage.reserve(retained);
|
|
19272
|
+
bestEnd = position;
|
|
19273
|
+
bestCaptures = thread.captures;
|
|
19274
|
+
storage.release(bestBytes);
|
|
19275
|
+
bestBytes = retained;
|
|
19276
|
+
}
|
|
19277
|
+
} else if (instruction.kind === "split") {
|
|
19278
|
+
enqueue(position, instruction.second, thread.captures);
|
|
19279
|
+
enqueue(position, instruction.first, thread.captures);
|
|
19280
|
+
} else if (instruction.kind === "jump") enqueue(position, instruction.target, thread.captures);
|
|
19281
|
+
else if (instruction.kind === "save") {
|
|
19282
|
+
const copied = work(Math.max(thread.captures.length, instruction.slot + 1));
|
|
19283
|
+
if (copied) await copied;
|
|
19284
|
+
enqueue(position, thread.pc + 1, thread.captures, instruction.slot);
|
|
19285
|
+
} else if (instruction.kind === "begin" ? position === 0 : position === text.length) enqueue(position, thread.pc + 1, thread.captures);
|
|
19286
|
+
} finally {
|
|
19287
|
+
storage.release(thread.bytes);
|
|
19061
19288
|
}
|
|
19062
19289
|
}
|
|
19063
|
-
|
|
19064
|
-
|
|
19065
|
-
|
|
19066
|
-
|
|
19067
|
-
|
|
19068
|
-
|
|
19069
|
-
|
|
19070
|
-
|
|
19071
|
-
|
|
19072
|
-
|
|
19073
|
-
|
|
19290
|
+
visited.clear();
|
|
19291
|
+
storage.release(stateBytes + 64);
|
|
19292
|
+
}
|
|
19293
|
+
if (bestEnd !== void 0) {
|
|
19294
|
+
let characters = bestEnd - start;
|
|
19295
|
+
for (let index = 1; index <= this.groupCount; index++) {
|
|
19296
|
+
const counted = work();
|
|
19297
|
+
if (counted) await counted;
|
|
19298
|
+
const begin = bestCaptures[index * 2];
|
|
19299
|
+
const end = bestCaptures[index * 2 + 1];
|
|
19300
|
+
if (begin !== void 0 && end !== void 0) characters += end - begin;
|
|
19074
19301
|
}
|
|
19075
|
-
|
|
19076
|
-
|
|
19077
|
-
|
|
19078
|
-
|
|
19079
|
-
|
|
19080
|
-
|
|
19081
|
-
|
|
19082
|
-
|
|
19302
|
+
const copied = work(characters);
|
|
19303
|
+
if (copied) await copied;
|
|
19304
|
+
storage.reserve(64 + (this.groupCount + 1) * 40 + characters * 2);
|
|
19305
|
+
const groups = [text.slice(start, bestEnd)];
|
|
19306
|
+
for (let index = 1; index <= this.groupCount; index++) {
|
|
19307
|
+
const materialized = work();
|
|
19308
|
+
if (materialized) await materialized;
|
|
19309
|
+
const begin = bestCaptures[index * 2];
|
|
19310
|
+
const end = bestCaptures[index * 2 + 1];
|
|
19311
|
+
groups.push(begin === void 0 || end === void 0 ? void 0 : text.slice(begin, end));
|
|
19312
|
+
}
|
|
19313
|
+
await budget.checkpoint();
|
|
19314
|
+
return { start, end: bestEnd, groups };
|
|
19315
|
+
}
|
|
19316
|
+
} finally {
|
|
19317
|
+
positions.clear();
|
|
19318
|
+
storage.clear();
|
|
19083
19319
|
}
|
|
19084
19320
|
}
|
|
19085
|
-
|
|
19321
|
+
return void 0;
|
|
19322
|
+
} finally {
|
|
19323
|
+
storage.clear();
|
|
19086
19324
|
}
|
|
19087
|
-
return void 0;
|
|
19088
19325
|
}
|
|
19089
19326
|
};
|
|
19090
19327
|
async function replacementLength(replacement, match, budget, available) {
|
|
@@ -19146,7 +19383,7 @@ async function substitute(text, pattern, replacement, budget, global, occurrence
|
|
|
19146
19383
|
while (search <= text.length) {
|
|
19147
19384
|
await budget.checkpoint();
|
|
19148
19385
|
budget.step();
|
|
19149
|
-
const match = pattern.find(text, budget, search);
|
|
19386
|
+
const match = await pattern.find(text, budget, search);
|
|
19150
19387
|
if (!match) break;
|
|
19151
19388
|
if (match.start === match.end && match.start === previousEnd) {
|
|
19152
19389
|
search = match.end + 1;
|
|
@@ -19479,7 +19716,7 @@ async function execute(program, context, files, quiet, budget, separator, output
|
|
|
19479
19716
|
if (terminated) outputState.unterminatedFiles.delete(path);
|
|
19480
19717
|
else outputState.unterminatedFiles.add(path);
|
|
19481
19718
|
};
|
|
19482
|
-
const matches = async (address) => address.kind === "number" ? number === address.number : address.kind === "last" ? (await peekNext()).done === true : getPattern(address.pattern).find(pattern, budget) !== void 0;
|
|
19719
|
+
const matches = async (address) => address.kind === "number" ? number === address.number : address.kind === "last" ? (await peekNext()).done === true : await getPattern(address.pattern).find(pattern, budget) !== void 0;
|
|
19483
19720
|
for (let pc = 0; pc < program.length; ) {
|
|
19484
19721
|
budget.step();
|
|
19485
19722
|
await budget.checkpoint();
|