@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.
- package/dist/safe-bash/chunks/{chunk-6VZX7ESE.js → chunk-26N7BLXE.js} +3 -3
- package/dist/safe-bash/chunks/{chunk-ZZ7JQBPX.js → chunk-4A2OLEML.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-LTREB3HX.js → chunk-54MC6XF5.js} +4 -4
- package/dist/safe-bash/chunks/{chunk-Z3CCN6Y2.js → chunk-6J5FUESH.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-YR5RZBWS.js → chunk-6TBFZ5JE.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-6HJNJ625.js → chunk-7MMYQG3P.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-WTZZX4LV.js → chunk-A4MB2KXV.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-EM2JW7ZH.js → chunk-ATYJKRBZ.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-VV24PRPB.js → chunk-AZQOEGP3.js} +1050 -101
- package/dist/safe-bash/chunks/chunk-AZQOEGP3.js.map +7 -0
- package/dist/safe-bash/chunks/{chunk-EFMXWUYE.js → chunk-B6JEJ6AT.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-JFGGQUYP.js → chunk-BFXGHT3R.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-RP5IZOOR.js → chunk-BJYV5J65.js} +1050 -101
- package/dist/safe-bash/chunks/chunk-BJYV5J65.js.map +7 -0
- package/dist/safe-bash/chunks/{chunk-HNHOPD3P.js → chunk-DIEFWGXO.js} +46 -26
- package/dist/safe-bash/chunks/{chunk-HNHOPD3P.js.map → chunk-DIEFWGXO.js.map} +2 -2
- package/dist/safe-bash/chunks/{chunk-SME47P4B.js → chunk-DV6EZOKM.js} +46 -26
- package/dist/safe-bash/chunks/{chunk-SME47P4B.js.map → chunk-DV6EZOKM.js.map} +2 -2
- package/dist/safe-bash/chunks/{chunk-646RTREQ.js → chunk-EEDOYIPC.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-OFAAHWL5.js → chunk-GCQ5A2T2.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-MJW4KSKV.js → chunk-GLPJEDLY.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-FOOJWH7J.js → chunk-GO5OKPBO.js} +4 -4
- package/dist/safe-bash/chunks/{chunk-5JANWFJ3.js → chunk-GWYXCCGO.js} +4 -4
- package/dist/safe-bash/chunks/{chunk-DPHRNHPT.js → chunk-H6KJ4L22.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-FLX2BZBF.js → chunk-HGBYIDAK.js} +4 -4
- package/dist/safe-bash/chunks/{chunk-VGJIDLZM.js → chunk-KS5VSJYM.js} +15 -8
- package/dist/safe-bash/chunks/chunk-KS5VSJYM.js.map +7 -0
- package/dist/safe-bash/chunks/{chunk-PO3Z7W3A.js → chunk-MUHYGUFD.js} +4 -4
- package/dist/safe-bash/chunks/{chunk-5DLGYPGJ.js → chunk-PDSTXORC.js} +126 -58
- package/dist/safe-bash/chunks/chunk-PDSTXORC.js.map +7 -0
- package/dist/safe-bash/chunks/{chunk-TIHMU25L.js → chunk-PQ37GDJF.js} +3 -3
- package/dist/safe-bash/chunks/{chunk-OTM5RCWZ.js → chunk-QNEDWYC2.js} +15 -8
- package/dist/safe-bash/chunks/chunk-QNEDWYC2.js.map +7 -0
- package/dist/safe-bash/chunks/{chunk-LZ7FUN6K.js → chunk-RHHDOA67.js} +5 -5
- package/dist/safe-bash/chunks/{chunk-DSCL3VA2.js → chunk-SJ3B26XV.js} +4 -4
- package/dist/safe-bash/chunks/{chunk-6JBTVWHH.js → chunk-SWACYEIT.js} +5 -5
- package/dist/safe-bash/chunks/{chunk-7UJW7TYR.js → chunk-TD6NWAUK.js} +126 -58
- package/dist/safe-bash/chunks/chunk-TD6NWAUK.js.map +7 -0
- package/dist/safe-bash/chunks/{chunk-Q4I754TV.js → chunk-THOBFD5C.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-XELW5O3R.js → chunk-U2STHT7S.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-5X4SOSTT.js → chunk-UJHE5PTK.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-B6YFFKYG.js → chunk-X4I3RHTC.js} +5 -1
- package/dist/safe-bash/chunks/chunk-X4I3RHTC.js.map +7 -0
- package/dist/safe-bash/chunks/{chunk-YOK5UHA7.js → chunk-XKXFX3RH.js} +5 -1
- package/dist/safe-bash/chunks/chunk-XKXFX3RH.js.map +7 -0
- package/dist/safe-bash/chunks/{chunk-PLCYP2E5.js → chunk-XV4K3UUF.js} +2 -2
- package/dist/safe-bash/commands/csplit/index.browser.js +2 -2
- package/dist/safe-bash/commands/factor/index.browser.js +2 -2
- package/dist/safe-bash/commands/getopt/index.browser.js +2 -2
- package/dist/safe-bash/commands/hexdump/index.browser.js +2 -2
- package/dist/safe-bash/commands/iconv/index.browser.js +2 -2
- package/dist/safe-bash/commands/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/internal.js +4 -3
- package/dist/safe-bash/commands/internal.js.map +1 -1
- package/dist/safe-bash/commands/line-endings/index.browser.js +2 -2
- package/dist/safe-bash/commands/llm/index.browser.js +4 -4
- package/dist/safe-bash/commands/network/index.browser.js +4 -4
- package/dist/safe-bash/commands/node/index.browser.js +4 -4
- package/dist/safe-bash/commands/pandoc/index.js.map +1 -1
- package/dist/safe-bash/commands/pr/index.browser.js +3 -3
- package/dist/safe-bash/commands/python/index.browser.js +2 -2
- package/dist/safe-bash/commands/record-buffer.d.ts.map +1 -1
- package/dist/safe-bash/commands/record-buffer.js +12 -4
- package/dist/safe-bash/commands/record-buffer.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/bounded-provider.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/bounded-provider.js +75 -8
- package/dist/safe-bash/commands/regex-execution/bounded-provider.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/limits.d.ts +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/limits.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/limits.js +6 -4
- package/dist/safe-bash/commands/regex-execution/ere/limits.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/portable.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/portable.js +7 -2
- package/dist/safe-bash/commands/regex-execution/portable.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/protocol.d.ts +2 -0
- package/dist/safe-bash/commands/regex-execution/protocol.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/protocol.js +26 -0
- package/dist/safe-bash/commands/regex-execution/protocol.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/utf8.d.ts +1 -1
- package/dist/safe-bash/commands/regex-execution/utf8.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/utf8.js +26 -2
- package/dist/safe-bash/commands/regex-execution/utf8.js.map +1 -1
- package/dist/safe-bash/commands/search/grep.d.ts.map +1 -1
- package/dist/safe-bash/commands/search/grep.js +109 -15
- package/dist/safe-bash/commands/search/grep.js.map +1 -1
- package/dist/safe-bash/commands/search/matcher.d.ts +1 -1
- package/dist/safe-bash/commands/search/matcher.d.ts.map +1 -1
- package/dist/safe-bash/commands/search/matcher.js +2 -0
- package/dist/safe-bash/commands/search/matcher.js.map +1 -1
- package/dist/safe-bash/commands/search/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/search/shared.js +23 -12
- package/dist/safe-bash/commands/search/shared.js.map +1 -1
- package/dist/safe-bash/commands/standard.d.ts.map +1 -1
- package/dist/safe-bash/commands/standard.js +22 -0
- package/dist/safe-bash/commands/standard.js.map +1 -1
- package/dist/safe-bash/commands/streams.d.ts.map +1 -1
- package/dist/safe-bash/commands/streams.js +54 -10
- package/dist/safe-bash/commands/streams.js.map +1 -1
- package/dist/safe-bash/commands/structured/input.d.ts.map +1 -1
- package/dist/safe-bash/commands/structured/input.js +484 -55
- package/dist/safe-bash/commands/structured/input.js.map +1 -1
- package/dist/safe-bash/commands/structured/interpreter.d.ts +3 -0
- package/dist/safe-bash/commands/structured/interpreter.d.ts.map +1 -1
- package/dist/safe-bash/commands/structured/interpreter.js +157 -1
- package/dist/safe-bash/commands/structured/interpreter.js.map +1 -1
- package/dist/safe-bash/commands/structured/jq.d.ts.map +1 -1
- package/dist/safe-bash/commands/structured/jq.js +50 -24
- package/dist/safe-bash/commands/structured/jq.js.map +1 -1
- package/dist/safe-bash/commands/structured/limits.d.ts +5 -0
- package/dist/safe-bash/commands/structured/limits.d.ts.map +1 -1
- package/dist/safe-bash/commands/structured/limits.js +51 -36
- package/dist/safe-bash/commands/structured/limits.js.map +1 -1
- package/dist/safe-bash/commands/structured/numbers.d.ts +1 -0
- package/dist/safe-bash/commands/structured/numbers.d.ts.map +1 -1
- package/dist/safe-bash/commands/structured/numbers.js +32 -0
- package/dist/safe-bash/commands/structured/numbers.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-reader.d.ts +1 -0
- package/dist/safe-bash/commands/text-programs/awk-reader.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-reader.js +41 -5
- package/dist/safe-bash/commands/text-programs/awk-reader.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-retention.d.ts +1 -0
- package/dist/safe-bash/commands/text-programs/awk-retention.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-retention.js +9 -0
- package/dist/safe-bash/commands/text-programs/awk-retention.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-runtime.d.ts +13 -0
- package/dist/safe-bash/commands/text-programs/awk-runtime.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-runtime.js +421 -83
- package/dist/safe-bash/commands/text-programs/awk-runtime.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-values.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/awk-values.js +21 -0
- package/dist/safe-bash/commands/text-programs/awk-values.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/regex.d.ts +15 -2
- package/dist/safe-bash/commands/text-programs/regex.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/regex.js +501 -13
- package/dist/safe-bash/commands/text-programs/regex.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/sed.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/sed.js +242 -102
- package/dist/safe-bash/commands/text-programs/sed.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/shared.d.ts +2 -0
- package/dist/safe-bash/commands/text-programs/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/shared.js +36 -0
- package/dist/safe-bash/commands/text-programs/shared.js.map +1 -1
- package/dist/safe-bash/commands/text.d.ts.map +1 -1
- package/dist/safe-bash/commands/text.js +136 -19
- package/dist/safe-bash/commands/text.js.map +1 -1
- package/dist/safe-bash/commands/tsort/index.browser.js +2 -2
- package/dist/safe-bash/commands/xml/index.browser.js +5 -5
- package/dist/safe-bash/commands/yq/index.browser.js +5 -5
- package/dist/safe-bash/contracts/yield.d.ts +1 -0
- package/dist/safe-bash/contracts/yield.d.ts.map +1 -1
- package/dist/safe-bash/contracts/yield.js +3 -0
- package/dist/safe-bash/contracts/yield.js.map +1 -1
- package/dist/safe-bash/core.browser.js +1052 -256
- package/dist/safe-bash/core.browser.js.map +3 -3
- package/dist/safe-bash/plugins/composition.d.ts +1 -0
- package/dist/safe-bash/plugins/composition.d.ts.map +1 -1
- package/dist/safe-bash/plugins/composition.js +80 -2
- package/dist/safe-bash/plugins/composition.js.map +1 -1
- package/dist/safe-bash/plugins/index.d.ts.map +1 -1
- package/dist/safe-bash/plugins/index.js +2 -2
- package/dist/safe-bash/plugins/index.js.map +1 -1
- package/dist/safe-bash-command-fold/arguments.d.ts +1 -1
- package/dist/safe-bash-command-fold/contracts.d.ts +2 -1
- package/dist/safe-bash-command-fold/engine.d.ts +1 -1
- package/dist/safe-bash-command-fold/index.js +10 -8
- package/dist/safe-bash-command-fold/index.js.map +2 -2
- package/dist/safe-bash-command-sips/index.js +231 -67
- package/dist/safe-bash-command-sips/index.js.map +2 -2
- package/dist/safe-bash-command-unrtf/contracts.d.ts +5 -2
- package/dist/safe-bash-command-unrtf/index.js +6 -5
- package/dist/safe-bash-command-unrtf/index.js.map +2 -2
- package/dist/safe-playwright-cloudflare/browser-run-code.js +22 -6
- package/package.json +2 -2
- package/dist/safe-bash/chunks/chunk-5DLGYPGJ.js.map +0 -7
- package/dist/safe-bash/chunks/chunk-7UJW7TYR.js.map +0 -7
- package/dist/safe-bash/chunks/chunk-B6YFFKYG.js.map +0 -7
- package/dist/safe-bash/chunks/chunk-OTM5RCWZ.js.map +0 -7
- package/dist/safe-bash/chunks/chunk-RP5IZOOR.js.map +0 -7
- package/dist/safe-bash/chunks/chunk-VGJIDLZM.js.map +0 -7
- package/dist/safe-bash/chunks/chunk-VV24PRPB.js.map +0 -7
- package/dist/safe-bash/chunks/chunk-YOK5UHA7.js.map +0 -7
- /package/dist/safe-bash/chunks/{chunk-6VZX7ESE.js.map → chunk-26N7BLXE.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-ZZ7JQBPX.js.map → chunk-4A2OLEML.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-LTREB3HX.js.map → chunk-54MC6XF5.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-Z3CCN6Y2.js.map → chunk-6J5FUESH.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-YR5RZBWS.js.map → chunk-6TBFZ5JE.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-6HJNJ625.js.map → chunk-7MMYQG3P.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-WTZZX4LV.js.map → chunk-A4MB2KXV.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-EM2JW7ZH.js.map → chunk-ATYJKRBZ.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-EFMXWUYE.js.map → chunk-B6JEJ6AT.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-JFGGQUYP.js.map → chunk-BFXGHT3R.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-646RTREQ.js.map → chunk-EEDOYIPC.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-OFAAHWL5.js.map → chunk-GCQ5A2T2.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-MJW4KSKV.js.map → chunk-GLPJEDLY.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-FOOJWH7J.js.map → chunk-GO5OKPBO.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-5JANWFJ3.js.map → chunk-GWYXCCGO.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-DPHRNHPT.js.map → chunk-H6KJ4L22.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-FLX2BZBF.js.map → chunk-HGBYIDAK.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-PO3Z7W3A.js.map → chunk-MUHYGUFD.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-TIHMU25L.js.map → chunk-PQ37GDJF.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-LZ7FUN6K.js.map → chunk-RHHDOA67.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-DSCL3VA2.js.map → chunk-SJ3B26XV.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-6JBTVWHH.js.map → chunk-SWACYEIT.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-Q4I754TV.js.map → chunk-THOBFD5C.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-XELW5O3R.js.map → chunk-U2STHT7S.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-5X4SOSTT.js.map → chunk-UJHE5PTK.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-PLCYP2E5.js.map → chunk-XV4K3UUF.js.map} +0 -0
|
@@ -11,7 +11,7 @@ function textSize(value) {
|
|
|
11
11
|
}
|
|
12
12
|
function ownScalar(value) {
|
|
13
13
|
return value.kind === "string" || value.kind === "numeric"
|
|
14
|
-
? { ...value, text: Buffer.from(value.text, "latin1").toString("latin1") } : value;
|
|
14
|
+
? { ...value, text: value.text.length < 13 ? value.text : Buffer.from(value.text, "latin1").toString("latin1") } : value;
|
|
15
15
|
}
|
|
16
16
|
class Flow {
|
|
17
17
|
kind;
|
|
@@ -79,7 +79,13 @@ export class AwkRuntime {
|
|
|
79
79
|
store(name) { return this.frames.at(-1)?.has(name) ? this.frames.at(-1) : this.variables; }
|
|
80
80
|
get(name) { return this.store(name).get(name) ?? unset; }
|
|
81
81
|
getScalar(name) { return scalar(this.get(name)); }
|
|
82
|
-
asText(value) {
|
|
82
|
+
asText(value) {
|
|
83
|
+
if (value.kind === "string" || value.kind === "numeric")
|
|
84
|
+
return value.text;
|
|
85
|
+
if (value.kind === "unset")
|
|
86
|
+
return "";
|
|
87
|
+
return text(value, text(this.getScalar("CONVFMT"), undefined, this.budget), this.budget);
|
|
88
|
+
}
|
|
83
89
|
varText(name) { return this.asText(this.getScalar(name)); }
|
|
84
90
|
retainName(path) {
|
|
85
91
|
this.context.signal.throwIfAborted();
|
|
@@ -88,8 +94,8 @@ export class AwkRuntime {
|
|
|
88
94
|
storeScalar(store, name, value) {
|
|
89
95
|
if (value.kind === "string" || value.kind === "numeric")
|
|
90
96
|
this.budget.check(value.text);
|
|
91
|
-
|
|
92
|
-
store.set(name,
|
|
97
|
+
this.retention.admit(textSize(store.get(name)), textSize(value));
|
|
98
|
+
store.set(name, ownScalar(value));
|
|
93
99
|
}
|
|
94
100
|
bindArray(store, name, array) {
|
|
95
101
|
let allocation = this.arrays.get(array);
|
|
@@ -144,14 +150,14 @@ export class AwkRuntime {
|
|
|
144
150
|
this.budget.check(key);
|
|
145
151
|
if (value.kind === "string" || value.kind === "numeric")
|
|
146
152
|
this.budget.check(value.text);
|
|
147
|
-
const
|
|
153
|
+
const existingValue = array.entries.get(key);
|
|
154
|
+
const existing = existingValue !== undefined || array.entries.has(key);
|
|
148
155
|
if (!existing && this.entries >= (this.budget.options.maxArrayEntries ?? Infinity))
|
|
149
156
|
throw new ProgramError("array entry limit exceeded");
|
|
150
|
-
const previous = textSize(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
array.entries.set(owned.key, owned.value);
|
|
157
|
+
const previous = textSize(existingValue), next = textSize(value) + (existing ? 0 : key.length);
|
|
158
|
+
this.retention.admit(previous, next);
|
|
159
|
+
const ownedKey = existing || key.length < 13 ? key : Buffer.from(key, "latin1").toString("latin1");
|
|
160
|
+
array.entries.set(ownedKey, ownScalar(value));
|
|
155
161
|
this.arrays.get(array).bytes += next - previous;
|
|
156
162
|
if (!existing)
|
|
157
163
|
this.entries++;
|
|
@@ -167,6 +173,50 @@ export class AwkRuntime {
|
|
|
167
173
|
return pattern;
|
|
168
174
|
}
|
|
169
175
|
async regex(expression) { return expression.kind === "regex" ? expression.pattern : this.pattern(this.asText(await this.scalarExpression(expression))); }
|
|
176
|
+
splitSync(value, separator, paragraph) {
|
|
177
|
+
if (!paragraph && value.length < 256 && (separator === " " || separator.length === 1)) {
|
|
178
|
+
this.budget.step(value.length);
|
|
179
|
+
const maxFields = this.budget.options.maxFields ?? Infinity;
|
|
180
|
+
const parts = [];
|
|
181
|
+
if (separator === " ") {
|
|
182
|
+
let start = -1;
|
|
183
|
+
for (let index = 0; index < value.length; index++) {
|
|
184
|
+
const ch = value.charCodeAt(index);
|
|
185
|
+
if (ch === 32 || ch === 9 || ch === 10) {
|
|
186
|
+
if (start >= 0) {
|
|
187
|
+
if (parts.length >= maxFields)
|
|
188
|
+
throw new ProgramError("field count limit exceeded");
|
|
189
|
+
parts.push(inputValue(value.slice(start, index)));
|
|
190
|
+
start = -1;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else if (start < 0)
|
|
194
|
+
start = index;
|
|
195
|
+
}
|
|
196
|
+
if (start >= 0) {
|
|
197
|
+
if (parts.length >= maxFields)
|
|
198
|
+
throw new ProgramError("field count limit exceeded");
|
|
199
|
+
parts.push(inputValue(value.slice(start, value.length)));
|
|
200
|
+
}
|
|
201
|
+
return parts;
|
|
202
|
+
}
|
|
203
|
+
if (value !== "") {
|
|
204
|
+
let start = 0;
|
|
205
|
+
let idx;
|
|
206
|
+
while ((idx = value.indexOf(separator, start)) >= 0) {
|
|
207
|
+
if (parts.length >= maxFields)
|
|
208
|
+
throw new ProgramError("field count limit exceeded");
|
|
209
|
+
parts.push(inputValue(value.slice(start, idx)));
|
|
210
|
+
start = idx + 1;
|
|
211
|
+
}
|
|
212
|
+
if (parts.length >= maxFields)
|
|
213
|
+
throw new ProgramError("field count limit exceeded");
|
|
214
|
+
parts.push(inputValue(value.slice(start, value.length)));
|
|
215
|
+
}
|
|
216
|
+
return parts;
|
|
217
|
+
}
|
|
218
|
+
return this.split(value, separator, paragraph);
|
|
219
|
+
}
|
|
170
220
|
async split(value, separator, paragraph = false) {
|
|
171
221
|
// Admit the byte scan/copy before building fields; regex matching charges its own work.
|
|
172
222
|
this.budget.step(value.length);
|
|
@@ -180,7 +230,7 @@ export class AwkRuntime {
|
|
|
180
230
|
let start = -1;
|
|
181
231
|
for (let index = 0; index < value.length; index++) {
|
|
182
232
|
if (index % 256 === 0)
|
|
183
|
-
await this.budget.
|
|
233
|
+
await this.budget.checkpointSync();
|
|
184
234
|
if (" \t\n".includes(value[index])) {
|
|
185
235
|
if (start >= 0) {
|
|
186
236
|
append(start, index);
|
|
@@ -198,15 +248,30 @@ export class AwkRuntime {
|
|
|
198
248
|
throw new ProgramError("field count limit exceeded");
|
|
199
249
|
for (let index = 0; index < value.length; index++) {
|
|
200
250
|
if (index % 256 === 0)
|
|
201
|
-
await this.budget.
|
|
251
|
+
await this.budget.checkpointSync();
|
|
202
252
|
append(index, index + 1);
|
|
203
253
|
}
|
|
204
254
|
}
|
|
205
255
|
else if (typeof separator === "string" && separator.length === 1) {
|
|
256
|
+
if (!paragraph && value.length < 256) {
|
|
257
|
+
if (value !== "") {
|
|
258
|
+
let start = 0;
|
|
259
|
+
let idx;
|
|
260
|
+
while ((idx = value.indexOf(separator, start)) >= 0) {
|
|
261
|
+
append(start, idx);
|
|
262
|
+
start = idx + 1;
|
|
263
|
+
}
|
|
264
|
+
append(start, value.length);
|
|
265
|
+
}
|
|
266
|
+
return parts;
|
|
267
|
+
}
|
|
206
268
|
let start = 0;
|
|
207
269
|
for (let index = 0; index < value.length; index++) {
|
|
208
|
-
if (index % 256 === 0)
|
|
209
|
-
|
|
270
|
+
if (index > 0 && index % 256 === 0) {
|
|
271
|
+
const p = this.budget.checkpointSync();
|
|
272
|
+
if (p)
|
|
273
|
+
await p;
|
|
274
|
+
}
|
|
210
275
|
if (value[index] === separator || paragraph && value[index] === "\n") {
|
|
211
276
|
append(start, index);
|
|
212
277
|
start = index + 1;
|
|
@@ -221,7 +286,7 @@ export class AwkRuntime {
|
|
|
221
286
|
if (paragraph)
|
|
222
287
|
for (let index = start; index < end; index++) {
|
|
223
288
|
if (index % 256 === 0)
|
|
224
|
-
await this.budget.
|
|
289
|
+
await this.budget.checkpointSync();
|
|
225
290
|
if (value[index] === "\n") {
|
|
226
291
|
append(start, index);
|
|
227
292
|
start = index + 1;
|
|
@@ -232,7 +297,7 @@ export class AwkRuntime {
|
|
|
232
297
|
let consumed = 0;
|
|
233
298
|
let search = 0;
|
|
234
299
|
while (search <= value.length) {
|
|
235
|
-
await this.budget.
|
|
300
|
+
await this.budget.checkpointSync();
|
|
236
301
|
const match = await matcher.find(value, this.budget, search);
|
|
237
302
|
if (!match)
|
|
238
303
|
break;
|
|
@@ -249,10 +314,17 @@ export class AwkRuntime {
|
|
|
249
314
|
}
|
|
250
315
|
return parts;
|
|
251
316
|
}
|
|
252
|
-
|
|
317
|
+
setRecordSync(record, value = inputValue(record)) {
|
|
253
318
|
this.budget.check(record);
|
|
254
|
-
const fields =
|
|
255
|
-
|
|
319
|
+
const fields = this.splitSync(record, this.varText("FS"), this.varText("RS") === "");
|
|
320
|
+
if (!(fields instanceof Promise)) {
|
|
321
|
+
this.replaceRecord(record, fields, value);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
return fields.then(resolved => { this.replaceRecord(record, resolved, value); });
|
|
325
|
+
}
|
|
326
|
+
async setRecord(record, value = inputValue(record)) {
|
|
327
|
+
await this.setRecordSync(record, value);
|
|
256
328
|
}
|
|
257
329
|
replaceRecord(record, fields, value = string(record)) {
|
|
258
330
|
let fieldBytes = 0;
|
|
@@ -261,12 +333,9 @@ export class AwkRuntime {
|
|
|
261
333
|
this.budget.check(field.text);
|
|
262
334
|
fieldBytes += textSize(field);
|
|
263
335
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}));
|
|
268
|
-
this.record = owned.record;
|
|
269
|
-
this.fields = owned.fields;
|
|
336
|
+
this.retention.admit(this.record.length + this.fieldBytes, record.length + fieldBytes);
|
|
337
|
+
this.record = record;
|
|
338
|
+
this.fields = fields;
|
|
270
339
|
this.fieldBytes = fieldBytes;
|
|
271
340
|
this.recordValue = value.kind === "string" || value.kind === "numeric" ? { ...value, text: this.record } : value;
|
|
272
341
|
this.variables.set("NF", numeric(fields.length));
|
|
@@ -294,7 +363,21 @@ export class AwkRuntime {
|
|
|
294
363
|
const record = this.join(fields.map(value => this.asText(value)), this.varText("OFS"));
|
|
295
364
|
this.replaceRecord(record, fields);
|
|
296
365
|
}
|
|
297
|
-
|
|
366
|
+
key(items) {
|
|
367
|
+
if (items.length === 1) {
|
|
368
|
+
const first = this.scalarExpression(items[0]);
|
|
369
|
+
if (!(first instanceof Promise)) {
|
|
370
|
+
const k = this.asText(first);
|
|
371
|
+
this.budget.step(2);
|
|
372
|
+
if (k.length > this.budget.maxBufferBytes)
|
|
373
|
+
throw new ProgramError("text buffer limit exceeded");
|
|
374
|
+
this.budget.step(k.length);
|
|
375
|
+
return k;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return this.keySlow(items);
|
|
379
|
+
}
|
|
380
|
+
async keySlow(items) {
|
|
298
381
|
const pieces = [];
|
|
299
382
|
for (const item of items)
|
|
300
383
|
pieces.push(this.asText(await this.scalarExpression(item)));
|
|
@@ -336,76 +419,237 @@ export class AwkRuntime {
|
|
|
336
419
|
throw new ProgramError("non-finite arithmetic result");
|
|
337
420
|
return result;
|
|
338
421
|
}
|
|
339
|
-
|
|
340
|
-
|
|
422
|
+
scalarExpression(expression) {
|
|
423
|
+
const val = this.evaluate(expression);
|
|
424
|
+
return val instanceof Promise ? val.then(scalar) : scalar(val);
|
|
425
|
+
}
|
|
426
|
+
evaluate(expression) {
|
|
341
427
|
this.budget.step();
|
|
342
428
|
switch (expression.kind) {
|
|
343
429
|
case "number": return numeric(expression.value);
|
|
344
430
|
case "string": return string(expression.value);
|
|
345
|
-
case "regex": return
|
|
431
|
+
case "regex": return expression.pattern.find(this.record, this.budget).then(m => numeric(m ? 1 : 0));
|
|
346
432
|
case "variable": return this.get(expression.name);
|
|
347
|
-
case "field":
|
|
348
|
-
|
|
433
|
+
case "field": {
|
|
434
|
+
const idxVal = this.scalarExpression(expression.index);
|
|
435
|
+
if (!(idxVal instanceof Promise)) {
|
|
436
|
+
const index = Math.trunc(number(idxVal));
|
|
437
|
+
if (!Number.isSafeInteger(index) || index < 0 || index > (this.budget.options.maxFields ?? Infinity))
|
|
438
|
+
throw new ProgramError("invalid or excessive field index");
|
|
439
|
+
return index === 0 ? this.recordValue : this.fields[index - 1] ?? unset;
|
|
440
|
+
}
|
|
441
|
+
return idxVal.then(resolved => {
|
|
442
|
+
const index = Math.trunc(number(resolved));
|
|
443
|
+
if (!Number.isSafeInteger(index) || index < 0 || index > (this.budget.options.maxFields ?? Infinity))
|
|
444
|
+
throw new ProgramError("invalid or excessive field index");
|
|
445
|
+
return index === 0 ? this.recordValue : this.fields[index - 1] ?? unset;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
case "array": {
|
|
449
|
+
const array = this.array(expression.name);
|
|
450
|
+
const k = this.key(expression.indexes);
|
|
451
|
+
if (!(k instanceof Promise)) {
|
|
452
|
+
let existing = array.entries.get(k);
|
|
453
|
+
if (existing === undefined && !array.entries.has(k)) {
|
|
454
|
+
this.arraySet(array, k, unset);
|
|
455
|
+
existing = unset;
|
|
456
|
+
}
|
|
457
|
+
return existing;
|
|
458
|
+
}
|
|
459
|
+
return k.then(resolvedKey => {
|
|
460
|
+
let existing = array.entries.get(resolvedKey);
|
|
461
|
+
if (existing === undefined && !array.entries.has(resolvedKey)) {
|
|
462
|
+
this.arraySet(array, resolvedKey, unset);
|
|
463
|
+
existing = unset;
|
|
464
|
+
}
|
|
465
|
+
return existing;
|
|
466
|
+
});
|
|
467
|
+
}
|
|
349
468
|
case "getline": return this.getline(expression);
|
|
350
469
|
case "tuple": throw new ProgramError("tuple is only valid as an array membership key");
|
|
351
|
-
case "conditional":
|
|
470
|
+
case "conditional": {
|
|
471
|
+
const cond = this.scalarExpression(expression.condition);
|
|
472
|
+
return cond instanceof Promise ? cond.then(c => this.evaluate(truth(c) ? expression.yes : expression.no)) : this.evaluate(truth(cond) ? expression.yes : expression.no);
|
|
473
|
+
}
|
|
352
474
|
case "unary": {
|
|
353
475
|
if (expression.operator === "++" || expression.operator === "--") {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
476
|
+
if (expression.operand.kind === "variable") {
|
|
477
|
+
const name = expression.operand.name;
|
|
478
|
+
const previous = number(scalar(this.get(name)));
|
|
479
|
+
const next = previous + (expression.operator === "++" ? 1 : -1);
|
|
480
|
+
this.set(name, numeric(next));
|
|
481
|
+
return numeric(expression.postfix ? previous : next);
|
|
482
|
+
}
|
|
483
|
+
if (expression.operand.kind === "array") {
|
|
484
|
+
const array = this.array(expression.operand.name);
|
|
485
|
+
const k = this.key(expression.operand.indexes);
|
|
486
|
+
if (!(k instanceof Promise)) {
|
|
487
|
+
let current = array.entries.get(k);
|
|
488
|
+
if (current === undefined && !array.entries.has(k)) {
|
|
489
|
+
this.arraySet(array, k, unset);
|
|
490
|
+
current = unset;
|
|
491
|
+
}
|
|
492
|
+
const previous = number(scalar(current));
|
|
493
|
+
const next = previous + (expression.operator === "++" ? 1 : -1);
|
|
494
|
+
this.arraySet(array, k, numeric(next));
|
|
495
|
+
return numeric(expression.postfix ? previous : next);
|
|
496
|
+
}
|
|
497
|
+
return k.then(resolvedKey => {
|
|
498
|
+
let current = array.entries.get(resolvedKey);
|
|
499
|
+
if (current === undefined && !array.entries.has(resolvedKey)) {
|
|
500
|
+
this.arraySet(array, resolvedKey, unset);
|
|
501
|
+
current = unset;
|
|
502
|
+
}
|
|
503
|
+
const previous = number(scalar(current));
|
|
504
|
+
const next = previous + (expression.operator === "++" ? 1 : -1);
|
|
505
|
+
this.arraySet(array, resolvedKey, numeric(next));
|
|
506
|
+
return numeric(expression.postfix ? previous : next);
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
return this.evaluateUnarySlow(expression);
|
|
359
510
|
}
|
|
360
|
-
const operand =
|
|
361
|
-
|
|
511
|
+
const operand = this.scalarExpression(expression.operand);
|
|
512
|
+
if (!(operand instanceof Promise)) {
|
|
513
|
+
return numeric(expression.operator === "!" ? truth(operand) ? 0 : 1 : expression.operator === "-" ? -number(operand) : number(operand));
|
|
514
|
+
}
|
|
515
|
+
return operand.then(op => numeric(expression.operator === "!" ? truth(op) ? 0 : 1 : expression.operator === "-" ? -number(op) : number(op)));
|
|
362
516
|
}
|
|
363
517
|
case "binary": {
|
|
364
518
|
const operator = expression.operator;
|
|
365
|
-
if (
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
519
|
+
if (operator === "=" || operator === "+=" || operator === "-=" || operator === "*=" || operator === "/=" || operator === "%=" || operator === "^=") {
|
|
520
|
+
if (expression.left.kind === "variable") {
|
|
521
|
+
const name = expression.left.name;
|
|
522
|
+
const previous = operator === "=" ? unset : scalar(this.get(name));
|
|
523
|
+
const rightVal = this.scalarExpression(expression.right);
|
|
524
|
+
if (!(rightVal instanceof Promise)) {
|
|
525
|
+
const value = operator === "=" ? rightVal : numeric(this.arithmetic(operator[0], number(previous), number(rightVal)));
|
|
526
|
+
this.set(name, value);
|
|
527
|
+
return value;
|
|
528
|
+
}
|
|
529
|
+
return rightVal.then(resolved => {
|
|
530
|
+
const value = operator === "=" ? resolved : numeric(this.arithmetic(operator[0], number(previous), number(resolved)));
|
|
531
|
+
this.set(name, value);
|
|
532
|
+
return value;
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
else if (expression.left.kind === "array") {
|
|
536
|
+
const array = this.array(expression.left.name);
|
|
537
|
+
const k = this.key(expression.left.indexes);
|
|
538
|
+
if (!(k instanceof Promise)) {
|
|
539
|
+
let current = operator === "=" ? unset : array.entries.get(k);
|
|
540
|
+
if (operator !== "=" && current === undefined && !array.entries.has(k)) {
|
|
541
|
+
this.arraySet(array, k, unset);
|
|
542
|
+
current = unset;
|
|
543
|
+
}
|
|
544
|
+
const previous = scalar(current);
|
|
545
|
+
const rightVal = this.scalarExpression(expression.right);
|
|
546
|
+
if (!(rightVal instanceof Promise)) {
|
|
547
|
+
const value = operator === "=" ? rightVal : numeric(this.arithmetic(operator[0], number(previous), number(rightVal)));
|
|
548
|
+
this.arraySet(array, k, value);
|
|
549
|
+
return value;
|
|
550
|
+
}
|
|
551
|
+
return rightVal.then(resolved => {
|
|
552
|
+
const value = operator === "=" ? resolved : numeric(this.arithmetic(operator[0], number(previous), number(resolved)));
|
|
553
|
+
this.arraySet(array, k, value);
|
|
554
|
+
return value;
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
return k.then(async (resolvedKey) => {
|
|
558
|
+
let current = operator === "=" ? unset : array.entries.get(resolvedKey);
|
|
559
|
+
if (operator !== "=" && current === undefined && !array.entries.has(resolvedKey)) {
|
|
560
|
+
this.arraySet(array, resolvedKey, unset);
|
|
561
|
+
current = unset;
|
|
562
|
+
}
|
|
563
|
+
const previous = scalar(current);
|
|
564
|
+
const resolved = await this.scalarExpression(expression.right);
|
|
565
|
+
const value = operator === "=" ? resolved : numeric(this.arithmetic(operator[0], number(previous), number(resolved)));
|
|
566
|
+
this.arraySet(array, resolvedKey, value);
|
|
567
|
+
return value;
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
return this.evaluateBinarySlow(expression);
|
|
373
571
|
}
|
|
374
|
-
if (operator === "in") {
|
|
375
|
-
|
|
376
|
-
const key = expression.left.kind === "tuple" ? await this.key(expression.left.items) : this.asText(await this.scalarExpression(expression.left));
|
|
377
|
-
return numeric(array.entries.has(key) ? 1 : 0);
|
|
572
|
+
if (operator === "in" || operator === "~" || operator === "!~") {
|
|
573
|
+
return this.evaluateBinarySlow(expression);
|
|
378
574
|
}
|
|
379
|
-
const left =
|
|
575
|
+
const left = this.scalarExpression(expression.left);
|
|
576
|
+
if (left instanceof Promise)
|
|
577
|
+
return this.evaluateBinaryWithLeftPromise(expression, left);
|
|
380
578
|
if (operator === "&&" && !truth(left))
|
|
381
579
|
return numeric(0);
|
|
382
580
|
if (operator === "||" && truth(left))
|
|
383
581
|
return numeric(1);
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
return
|
|
387
|
-
|
|
388
|
-
const right = await this.scalarExpression(expression.right);
|
|
389
|
-
if (operator === "&&" || operator === "||")
|
|
390
|
-
return numeric(truth(right) ? 1 : 0);
|
|
391
|
-
if (operator === "concat") {
|
|
392
|
-
const leftText = this.asText(left);
|
|
393
|
-
const rightText = this.asText(right);
|
|
394
|
-
this.budget.step(0);
|
|
395
|
-
if (rightText.length > this.budget.maxBufferBytes - leftText.length)
|
|
396
|
-
throw new ProgramError("text buffer limit exceeded");
|
|
397
|
-
this.budget.step(leftText.length + rightText.length);
|
|
398
|
-
return string(leftText + rightText);
|
|
399
|
-
}
|
|
400
|
-
if (["==", "!=", "<", "<=", ">", ">="].includes(operator)) {
|
|
401
|
-
const order = compare(left, right, this.varText("CONVFMT"), this.budget);
|
|
402
|
-
return numeric((operator === "==" ? order === 0 : operator === "!=" ? order !== 0 : operator === "<" ? order < 0 : operator === "<=" ? order <= 0 : operator === ">" ? order > 0 : order >= 0) ? 1 : 0);
|
|
403
|
-
}
|
|
404
|
-
return numeric(this.arithmetic(operator, number(left), number(right)));
|
|
582
|
+
const right = this.scalarExpression(expression.right);
|
|
583
|
+
if (right instanceof Promise)
|
|
584
|
+
return right.then(r => this.evaluateBinarySyncOperands(operator, left, r));
|
|
585
|
+
return this.evaluateBinarySyncOperands(operator, left, right);
|
|
405
586
|
}
|
|
406
587
|
case "call": return this.call(expression.name, expression.args);
|
|
407
588
|
}
|
|
408
589
|
}
|
|
590
|
+
evaluateBinarySyncOperands(operator, left, right) {
|
|
591
|
+
if (operator === "&&" || operator === "||")
|
|
592
|
+
return numeric(truth(right) ? 1 : 0);
|
|
593
|
+
if (operator === "concat") {
|
|
594
|
+
const leftText = this.asText(left);
|
|
595
|
+
const rightText = this.asText(right);
|
|
596
|
+
this.budget.step(0);
|
|
597
|
+
if (rightText.length > this.budget.maxBufferBytes - leftText.length)
|
|
598
|
+
throw new ProgramError("text buffer limit exceeded");
|
|
599
|
+
this.budget.step(leftText.length + rightText.length);
|
|
600
|
+
return string(leftText + rightText);
|
|
601
|
+
}
|
|
602
|
+
if (operator === "==" || operator === "!=" || operator === "<" || operator === "<=" || operator === ">" || operator === ">=") {
|
|
603
|
+
const order = compare(left, right, this.varText("CONVFMT"), this.budget);
|
|
604
|
+
return numeric((operator === "==" ? order === 0 : operator === "!=" ? order !== 0 : operator === "<" ? order < 0 : operator === "<=" ? order <= 0 : operator === ">" ? order > 0 : order >= 0) ? 1 : 0);
|
|
605
|
+
}
|
|
606
|
+
return numeric(this.arithmetic(operator, number(left), number(right)));
|
|
607
|
+
}
|
|
608
|
+
async evaluateBinaryWithLeftPromise(expression, leftPromise) {
|
|
609
|
+
const operator = expression.operator;
|
|
610
|
+
const left = await leftPromise;
|
|
611
|
+
if (operator === "&&" && !truth(left))
|
|
612
|
+
return numeric(0);
|
|
613
|
+
if (operator === "||" && truth(left))
|
|
614
|
+
return numeric(1);
|
|
615
|
+
const right = await this.scalarExpression(expression.right);
|
|
616
|
+
return this.evaluateBinarySyncOperands(operator, left, right);
|
|
617
|
+
}
|
|
618
|
+
async evaluateUnarySlow(expression) {
|
|
619
|
+
if (expression.operator === "++" || expression.operator === "--") {
|
|
620
|
+
const reference = await this.reference(expression.operand);
|
|
621
|
+
const previous = number(scalar(reference.get()));
|
|
622
|
+
const next = previous + (expression.operator === "++" ? 1 : -1);
|
|
623
|
+
await reference.set(numeric(next));
|
|
624
|
+
return numeric(expression.postfix ? previous : next);
|
|
625
|
+
}
|
|
626
|
+
const operand = await this.scalarExpression(expression.operand);
|
|
627
|
+
return numeric(expression.operator === "!" ? truth(operand) ? 0 : 1 : expression.operator === "-" ? -number(operand) : number(operand));
|
|
628
|
+
}
|
|
629
|
+
async evaluateBinarySlow(expression) {
|
|
630
|
+
const operator = expression.operator;
|
|
631
|
+
if (["=", "+=", "-=", "*=", "/=", "%=", "^="].includes(operator)) {
|
|
632
|
+
const reference = await this.reference(expression.left);
|
|
633
|
+
const previous = operator === "=" ? unset : scalar(reference.get());
|
|
634
|
+
let value = await this.scalarExpression(expression.right);
|
|
635
|
+
if (operator !== "=")
|
|
636
|
+
value = numeric(this.arithmetic(operator[0], number(previous), number(value)));
|
|
637
|
+
await reference.set(value);
|
|
638
|
+
return value;
|
|
639
|
+
}
|
|
640
|
+
if (operator === "in") {
|
|
641
|
+
const array = this.array(expression.right.name);
|
|
642
|
+
const key = expression.left.kind === "tuple" ? await this.key(expression.left.items) : this.asText(await this.scalarExpression(expression.left));
|
|
643
|
+
return numeric(array.entries.has(key) ? 1 : 0);
|
|
644
|
+
}
|
|
645
|
+
const left = await this.scalarExpression(expression.left);
|
|
646
|
+
if (operator === "~" || operator === "!~") {
|
|
647
|
+
const matched = (await (await this.regex(expression.right)).find(this.asText(left), this.budget)) !== undefined;
|
|
648
|
+
return numeric((operator === "~" ? matched : !matched) ? 1 : 0);
|
|
649
|
+
}
|
|
650
|
+
const right = await this.scalarExpression(expression.right);
|
|
651
|
+
return this.evaluateBinarySyncOperands(operator, left, right);
|
|
652
|
+
}
|
|
409
653
|
async getline(expression) {
|
|
410
654
|
if (!expression.file) {
|
|
411
655
|
const record = await this.readMainRecord();
|
|
@@ -444,7 +688,7 @@ export class AwkRuntime {
|
|
|
444
688
|
yield* context.stdin;
|
|
445
689
|
else {
|
|
446
690
|
budget.step();
|
|
447
|
-
await budget.
|
|
691
|
+
await budget.checkpointSync();
|
|
448
692
|
const capabilities = await context.fs.capabilitiesFor?.(name, { signal: context.signal }) ?? context.fs.capabilities;
|
|
449
693
|
context.signal.throwIfAborted();
|
|
450
694
|
if (context.fs.readStream && capabilities.streamingRead !== false)
|
|
@@ -626,11 +870,52 @@ export class AwkRuntime {
|
|
|
626
870
|
throw new ProgramError(`invalid mathematical result in '${name}'`);
|
|
627
871
|
return numeric(result);
|
|
628
872
|
}
|
|
873
|
+
executeSync(statement) {
|
|
874
|
+
if (!this.inspection) {
|
|
875
|
+
const p = this.budget.checkpointSync();
|
|
876
|
+
if (!p) {
|
|
877
|
+
if (statement.kind === "expression") {
|
|
878
|
+
this.budget.step();
|
|
879
|
+
const val = this.evaluate(statement.expression);
|
|
880
|
+
return val instanceof Promise ? val.then(() => undefined) : undefined;
|
|
881
|
+
}
|
|
882
|
+
if (statement.kind === "block") {
|
|
883
|
+
this.budget.step();
|
|
884
|
+
for (let i = 0; i < statement.body.length; i++) {
|
|
885
|
+
const res = this.executeSync(statement.body[i]);
|
|
886
|
+
if (res instanceof Promise) {
|
|
887
|
+
return this.executeBlockRemainder(statement.body, i + 1, res);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return undefined;
|
|
891
|
+
}
|
|
892
|
+
if (statement.kind === "if") {
|
|
893
|
+
this.budget.step();
|
|
894
|
+
const cond = this.scalarExpression(statement.condition);
|
|
895
|
+
if (!(cond instanceof Promise)) {
|
|
896
|
+
const branch = truth(cond) ? statement.yes : statement.no;
|
|
897
|
+
return branch ? this.executeSync(branch) : undefined;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
return this.execute(statement);
|
|
903
|
+
}
|
|
904
|
+
async executeBlockRemainder(body, startIndex, current) {
|
|
905
|
+
await current;
|
|
906
|
+
for (let i = startIndex; i < body.length; i++) {
|
|
907
|
+
const res = this.executeSync(body[i]);
|
|
908
|
+
if (res instanceof Promise)
|
|
909
|
+
await res;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
629
912
|
async execute(statement) {
|
|
630
913
|
this.budget.step();
|
|
631
914
|
if (this.inspection)
|
|
632
915
|
await this.inspection.observe(statement, this.phase);
|
|
633
|
-
|
|
916
|
+
const p = this.budget.checkpointSync();
|
|
917
|
+
if (p)
|
|
918
|
+
await p;
|
|
634
919
|
switch (statement.kind) {
|
|
635
920
|
case "block":
|
|
636
921
|
for (const child of statement.body)
|
|
@@ -796,6 +1081,47 @@ export class AwkRuntime {
|
|
|
796
1081
|
return status;
|
|
797
1082
|
}
|
|
798
1083
|
async readMainRecord() {
|
|
1084
|
+
const syncRes = this.readMainRecordSync();
|
|
1085
|
+
return syncRes instanceof Promise ? await syncRes : syncRes;
|
|
1086
|
+
}
|
|
1087
|
+
incrementCounter(name) {
|
|
1088
|
+
const current = this.variables.get(name);
|
|
1089
|
+
if (current && !(current instanceof AwkArray) && current.kind === "number" && !this.frames.at(-1)?.has(name)) {
|
|
1090
|
+
this.retention.admit(0, 0);
|
|
1091
|
+
this.variables.set(name, numeric(current.number + 1));
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
this.set(name, numeric(number(this.getScalar(name)) + 1));
|
|
1095
|
+
}
|
|
1096
|
+
readMainRecordSync() {
|
|
1097
|
+
if (this.mainReader) {
|
|
1098
|
+
this.budget.step();
|
|
1099
|
+
const record = this.mainReader.readSync(this.varText("RS"));
|
|
1100
|
+
if (typeof record === "string") {
|
|
1101
|
+
this.incrementCounter("NR");
|
|
1102
|
+
this.incrementCounter("FNR");
|
|
1103
|
+
return record;
|
|
1104
|
+
}
|
|
1105
|
+
if (record instanceof Promise) {
|
|
1106
|
+
return record.then(resolved => {
|
|
1107
|
+
if (resolved !== undefined) {
|
|
1108
|
+
this.incrementCounter("NR");
|
|
1109
|
+
this.incrementCounter("FNR");
|
|
1110
|
+
return resolved;
|
|
1111
|
+
}
|
|
1112
|
+
return this.readMainRecordSlowAfterEof();
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
return this.readMainRecordSlowAfterEof();
|
|
1116
|
+
}
|
|
1117
|
+
return this.readMainRecordSlow();
|
|
1118
|
+
}
|
|
1119
|
+
async readMainRecordSlowAfterEof() {
|
|
1120
|
+
await this.mainReader?.close();
|
|
1121
|
+
this.mainReader = undefined;
|
|
1122
|
+
return this.readMainRecordSlow();
|
|
1123
|
+
}
|
|
1124
|
+
async readMainRecordSlow() {
|
|
799
1125
|
while (true) {
|
|
800
1126
|
this.budget.step();
|
|
801
1127
|
if (!this.mainReader) {
|
|
@@ -805,7 +1131,9 @@ export class AwkRuntime {
|
|
|
805
1131
|
const argumentOptions = this.budget.options;
|
|
806
1132
|
if (this.argument > (argumentOptions?.maxArguments ?? Infinity))
|
|
807
1133
|
throw new ProgramError("argument count limit exceeded");
|
|
808
|
-
|
|
1134
|
+
const p = this.budget.checkpointSync();
|
|
1135
|
+
if (p)
|
|
1136
|
+
await p;
|
|
809
1137
|
const next = this.asText(this.array("ARGV").entries.get(String(this.argument++)) ?? unset);
|
|
810
1138
|
if (!next)
|
|
811
1139
|
continue;
|
|
@@ -833,8 +1161,8 @@ export class AwkRuntime {
|
|
|
833
1161
|
this.mainReader = undefined;
|
|
834
1162
|
continue;
|
|
835
1163
|
}
|
|
836
|
-
this.
|
|
837
|
-
this.
|
|
1164
|
+
this.incrementCounter("NR");
|
|
1165
|
+
this.incrementCounter("FNR");
|
|
838
1166
|
return record;
|
|
839
1167
|
}
|
|
840
1168
|
}
|
|
@@ -857,23 +1185,33 @@ export class AwkRuntime {
|
|
|
857
1185
|
if (!stopped && (this.program.rules.length || this.program.end.length))
|
|
858
1186
|
while (true) {
|
|
859
1187
|
this.budget.step();
|
|
860
|
-
const
|
|
1188
|
+
const recOrPromise = this.readMainRecordSync();
|
|
1189
|
+
const record = recOrPromise instanceof Promise ? await recOrPromise : recOrPromise;
|
|
861
1190
|
if (record === undefined)
|
|
862
1191
|
break;
|
|
863
|
-
|
|
1192
|
+
const setRecPromise = this.setRecordSync(record);
|
|
1193
|
+
if (setRecPromise instanceof Promise)
|
|
1194
|
+
await setRecPromise;
|
|
864
1195
|
try {
|
|
865
1196
|
for (let index = 0; index < this.program.rules.length; index++) {
|
|
866
1197
|
const rule = this.program.rules[index];
|
|
867
|
-
|
|
1198
|
+
let selected = !rule.pattern || ranges.has(index);
|
|
1199
|
+
if (!selected) {
|
|
1200
|
+
const patVal = this.scalarExpression(rule.pattern);
|
|
1201
|
+
selected = truth(patVal instanceof Promise ? await patVal : patVal);
|
|
1202
|
+
}
|
|
868
1203
|
if (!selected)
|
|
869
1204
|
continue;
|
|
870
1205
|
if (rule.end) {
|
|
871
|
-
|
|
1206
|
+
const endVal = this.scalarExpression(rule.end);
|
|
1207
|
+
if (truth(endVal instanceof Promise ? await endVal : endVal))
|
|
872
1208
|
ranges.delete(index);
|
|
873
1209
|
else
|
|
874
1210
|
ranges.add(index);
|
|
875
1211
|
}
|
|
876
|
-
|
|
1212
|
+
const execRes = this.executeSync(rule.action);
|
|
1213
|
+
if (execRes instanceof Promise)
|
|
1214
|
+
await execRes;
|
|
877
1215
|
}
|
|
878
1216
|
}
|
|
879
1217
|
catch (error) {
|