@poe-platform/safe-bash 0.1.747 → 0.1.748

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { splitSyncJqExpression } from "./sync-jq-expression.js";
2
2
  import { wcDisplayWidth } from "../commands/wc-width.js";
3
- import { text as awkValueText, compare as awkCompare, inputValue as awkInputValue, numeric as awkNumeric, string as awkString } from "../commands/text-programs/awk-values.js";
3
+ import { text as awkValueText, compare as awkCompare, inputValue as awkInputValue, numeric as awkNumeric, number as awkNumber, string as awkString } from "../commands/text-programs/awk-values.js";
4
4
  import { bytesToHex, latin1Text } from "../byte-encoding.js";
5
5
  const sharedCaptureDecoder = new TextDecoder();
6
6
  const cachedCaptureAsciiBytes = new Uint8Array(4096);
@@ -13637,60 +13637,11 @@ export class Runtime {
13637
13637
  // command. A late fallback would replay effects already performed.
13638
13638
  return false;
13639
13639
  }
13640
- const sel = getArraySelector(part);
13641
- if (sel !== undefined) {
13642
- if (rawState.nounset)
13643
- return false;
13644
- if (sel.kind === "members" || sel.kind === "keys") {
13645
- if (part.operator !== undefined) {
13646
- if (sel.kind === "members" &&
13647
- !part.keys &&
13648
- !part.length &&
13649
- !part.substring &&
13650
- part.quoted &&
13651
- (sel.separator === "*" || (allowAt && sel.separator === "@")) &&
13652
- this.budget.limits.maxExpansionBytes === Infinity &&
13653
- !rawState.nocasematch) {
13654
- if ((part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") && part.alternate && part.alternate.parts.length === 1 && part.alternate.parts[0].kind === "text" && (!hasGlobOrEscape(part.alternate.parts[0].value, true) || (!part.alternate.parts[0].quoted && Boolean(tryCompileTrimGlobToRegex(part.alternate.parts[0].value, part.operator, !!rawState.extglob)))))
13655
- continue;
13656
- if ((part.operator === "/" || part.operator === "//" || part.operator === "/#" || part.operator === "/%") && part.alternate && part.alternate.parts.length === 1 && part.alternate.parts[0].kind === "text" && part.alternate.parts[0].value.length > 0 && (!hasGlobOrEscape(part.alternate.parts[0].value, true) || (!part.alternate.parts[0].quoted && Boolean(tryCompileFixedGlobToRegex(part.alternate.parts[0].value, part.operator, !!rawState.extglob)))) && (!part.replacement || part.replacement.parts.length === 0 || (part.replacement.parts.length === 1 && part.replacement.parts[0].kind === "text" && !part.replacement.parts[0].value.includes("&") && !part.replacement.parts[0].value.includes("\\") && !part.replacement.parts[0].value.startsWith("~"))))
13657
- continue;
13658
- if ((part.operator === "^" || part.operator === "^^" || part.operator === "," || part.operator === ",,") && (!part.alternate || part.alternate.parts.length === 0))
13659
- continue;
13660
- }
13661
- return false;
13662
- }
13663
- if (part.length) {
13664
- if (part.substring)
13665
- return false;
13666
- continue;
13667
- }
13668
- if (part.quoted && (sel.separator === "*" || (allowAt && sel.separator === "@")) && this.budget.limits.maxExpansionBytes === Infinity && (!part.substring || (sel.kind === "members" && part.substring.offset.parts.every(p => p.kind === "text" || (p.kind === "variable" && !p.operator && !p.substring && !p.length)) && (!part.substring.length || part.substring.length.parts.every(p => p.kind === "text" || (p.kind === "variable" && !p.operator && !p.substring && !p.length)))))) {
13669
- continue;
13670
- }
13671
- return false;
13672
- }
13673
- if (sel.kind === "element") {
13674
- if (part.substring) {
13675
- // Bindings, indices and character widths can change each
13676
- // iteration. The limited element slicer may then need fallback;
13677
- // do not speculate after earlier compound effects have run.
13678
- return false;
13679
- }
13680
- if (part.operator === undefined)
13681
- continue;
13682
- if ((part.operator === "-" || part.operator === ":-" || part.operator === "+" || part.operator === ":+") && part.alternate && !part.length)
13683
- continue;
13684
- if ((part.operator === "^" || part.operator === "^^" || part.operator === "," || part.operator === ",,") && (!part.alternate || part.alternate.parts.length === 0) && !part.length)
13685
- continue;
13686
- if (!part.length && !rawState.nocasematch && this.budget.limits.maxExpansionBytes === Infinity) {
13687
- if ((part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") && part.alternate && part.alternate.parts.length === 1 && part.alternate.parts[0].kind === "text" && !hasGlobOrEscape(part.alternate.parts[0].value, true))
13688
- continue;
13689
- if ((part.operator === "/" || part.operator === "//" || part.operator === "/#" || part.operator === "/%") && part.alternate && part.alternate.parts.length === 1 && part.alternate.parts[0].kind === "text" && part.alternate.parts[0].value.length > 0 && !hasGlobOrEscape(part.alternate.parts[0].value, true) && (!part.replacement || part.replacement.parts.length === 0 || (part.replacement.parts.length === 1 && part.replacement.parts[0].kind === "text" && !part.replacement.parts[0].value.includes("&") && !part.replacement.parts[0].value.includes("\\") && !part.replacement.parts[0].value.startsWith("~"))))
13690
- continue;
13691
- }
13692
- return false;
13693
- }
13640
+ if (getArraySelector(part) !== undefined) {
13641
+ // A loop can change the binding or subscript after preflight. The
13642
+ // limited fast evaluator may then return undefined, after earlier
13643
+ // effects have already run. Use normal expansion for selectors and
13644
+ // their alternates rather than risking corruption or replay.
13694
13645
  return false;
13695
13646
  }
13696
13647
  if (part.length || part.substring || part.operator !== undefined) {
@@ -13925,13 +13876,19 @@ export class Runtime {
13925
13876
  return false;
13926
13877
  }
13927
13878
  else if (w0Plain === "awk") {
13928
- if (plainOps.length !== opCount || this.evalSyncAwk([], plainOps) === undefined)
13879
+ const input = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState);
13880
+ if (plainOps.length !== opCount || input === undefined)
13881
+ return false;
13882
+ const lines = input.length === 0 ? [] : input.split("\n");
13883
+ if (input.endsWith("\n"))
13884
+ lines.pop();
13885
+ if (this.evalSyncAwk(lines, plainOps) === undefined)
13929
13886
  return false;
13930
13887
  }
13931
13888
  else if (w0Plain === "jq") {
13932
13889
  if (plainOps.length !== opCount)
13933
13890
  return false;
13934
- const jqIn = this.extractLoopInvariantJqInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState);
13891
+ const jqIn = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState)?.trim();
13935
13892
  if (jqIn === undefined || this.evalSyncJq(jqIn, plainOps) === undefined)
13936
13893
  return false;
13937
13894
  }
@@ -13964,7 +13921,7 @@ export class Runtime {
13964
13921
  return false;
13965
13922
  }
13966
13923
  else if (w0Plain === "numfmt") {
13967
- const nmCheck = this.extractLoopInvariantJqInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState);
13924
+ const nmCheck = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState)?.trim();
13968
13925
  if (nmCheck === undefined || plainOps.length !== opCount || this.evalSyncNumfmt(nmCheck.split("\n"), plainOps) === undefined)
13969
13926
  return false;
13970
13927
  }
@@ -14087,7 +14044,15 @@ export class Runtime {
14087
14044
  return false;
14088
14045
  }
14089
14046
  else if (sName === "awk") {
14090
- if (this.evalSyncAwk([], sPlainArgs) === undefined)
14047
+ if (sIdx !== 1)
14048
+ return false;
14049
+ const input = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState);
14050
+ if (input === undefined)
14051
+ return false;
14052
+ const lines = input.length === 0 ? [] : input.split("\n");
14053
+ if (input.endsWith("\n"))
14054
+ lines.pop();
14055
+ if (this.evalSyncAwk(lines, sPlainArgs) === undefined)
14091
14056
  return false;
14092
14057
  }
14093
14058
  else if (sName === "grep") {
@@ -14101,7 +14066,7 @@ export class Runtime {
14101
14066
  else if (sName === "jq") {
14102
14067
  if (sIdx !== 1)
14103
14068
  return false;
14104
- const jqIn = this.extractLoopInvariantJqInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState);
14069
+ const jqIn = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState)?.trim();
14105
14070
  if (jqIn === undefined || this.evalSyncJq(jqIn, sPlainArgs) === undefined)
14106
14071
  return false;
14107
14072
  }
@@ -14124,7 +14089,7 @@ export class Runtime {
14124
14089
  else if (sName === "numfmt") {
14125
14090
  if (sIdx !== 1)
14126
14091
  return false;
14127
- const nmCheck = this.extractLoopInvariantJqInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState);
14092
+ const nmCheck = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState)?.trim();
14128
14093
  if (nmCheck === undefined || this.evalSyncNumfmt(nmCheck.split("\n"), sPlainArgs) === undefined)
14129
14094
  return false;
14130
14095
  }
@@ -14201,50 +14166,15 @@ export class Runtime {
14201
14166
  }
14202
14167
  return undefined;
14203
14168
  }
14204
- execSyncUnsetStep(step, rawState, io, monitor, touched) {
14169
+ execSyncUnsetStep(step, rawState, monitor, touched) {
14205
14170
  const uVars = step.unsetVars;
14206
- const store = monitor.store;
14207
14171
  let lastExpanded = "";
14208
- for (let ui = 0; ui < uVars.length; ui++) {
14209
- const uvn = uVars[ui];
14210
- if (uvn.charCodeAt(0) === 64) {
14211
- const wIdx = Number(uvn.slice(1));
14212
- const wu = step.cmd.words[wIdx];
14213
- const tExpanded = this.fastValueWord(wu, rawState, io, false, false, false, false, 0, step.line);
14214
- lastExpanded = tExpanded;
14215
- const bracket = tExpanded.indexOf("[");
14216
- if (bracket > 0 && tExpanded.endsWith("]") && store) {
14217
- const arrName = tExpanded.slice(0, bracket);
14218
- const subStr = tExpanded.slice(bracket + 1, -1);
14219
- const binding = store.get(arrName);
14220
- if (binding) {
14221
- if (binding.associative) {
14222
- const id = fastStringHexIdentity(subStr);
14223
- const existingKey = binding.keys.get(id);
14224
- if (existingKey !== undefined) {
14225
- binding.remove(existingKey.index);
14226
- store.changed(monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets), arrName);
14227
- }
14228
- }
14229
- else {
14230
- const idxNum = /^(?:0|[1-9][0-9]{0,8})$/.test(subStr)
14231
- ? Number(subStr)
14232
- : resolveSimpleArithOperand(subStr, rawState, monitor, store, this._syncArithRawWriteOnly ? this._syncArithTouched : undefined);
14233
- const resolvedIdx = idxNum !== undefined ? (idxNum >= 0 ? idxNum : binding.maximum + 1 + idxNum) : undefined;
14234
- if (resolvedIdx !== undefined && resolvedIdx >= 0 && binding.values.has(resolvedIdx)) {
14235
- binding.remove(resolvedIdx);
14236
- store.changed(monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets), arrName);
14237
- }
14238
- }
14239
- }
14240
- }
14241
- }
14242
- else {
14243
- delete rawState.variables[uvn];
14244
- monitor.proxy.exported.delete(uvn);
14245
- touched.add(uvn);
14246
- lastExpanded = uvn;
14247
- }
14172
+ for (const uvn of uVars) {
14173
+ delete rawState.variables[uvn];
14174
+ rawState.exported.delete(uvn);
14175
+ monitor.proxy.exported.delete(uvn);
14176
+ touched.add(uvn);
14177
+ lastExpanded = uvn;
14248
14178
  }
14249
14179
  return lastExpanded;
14250
14180
  }
@@ -14268,26 +14198,7 @@ export class Runtime {
14268
14198
  if (vn && startIdx === 1 && hasShellFunction(rawState, vn))
14269
14199
  return undefined;
14270
14200
  if (!vn || vn.startsWith("-") || !isShellIdentifier(vn) || controlNames.has(vn) || vn === "OPTIND" || rawState.readonlyVariables?.has(vn) || rawState.variableAttributes?.get(vn) || store?.get(vn) || stateMonitor(rawState)?.hasOverlay(vn) || rawState.locals.some(f => f.has(vn))) {
14271
- const wu = cmd.words[i];
14272
- const p0 = wu.parts[0];
14273
- const pLast = wu.parts[wu.parts.length - 1];
14274
- const m = p0?.kind === "text" ? /^([a-zA-Z_][a-zA-Z0-9_]*)\[/.exec(p0.value) : undefined;
14275
- const arrName = m?.[1];
14276
- const b = arrName ? store?.get(arrName) : undefined;
14277
- if (arrName &&
14278
- b &&
14279
- b.references === 1 &&
14280
- !store.watches.has(arrName) &&
14281
- !rawState.readonlyVariables?.has(arrName) &&
14282
- !hasUnpreparedLocal(rawState, arrName) &&
14283
- !stateMonitor(rawState)?.hasOverlay(arrName) &&
14284
- pLast?.kind === "text" &&
14285
- pLast.value.endsWith("]") &&
14286
- this.isPureSyncValueWord(wu, rawState) &&
14287
- (p0.quoted || rawState.noglob || (!rawState.nullglob && this._isMemoryBackingFs && tryGetMemoryDirectoryEntryNamesSync(this.backingFs, rawState.cwd)?.size === 0))) {
14288
- vars.push(`@${i}`);
14289
- continue;
14290
- }
14201
+ // Array unsets need the full builtin: arithmetic, @/* and maximum-index updates.
14291
14202
  return undefined;
14292
14203
  }
14293
14204
  vars.push(vn);
@@ -15052,6 +14963,10 @@ export class Runtime {
15052
14963
  return false;
15053
14964
  }
15054
14965
  const assignment = this.assignment(w0);
14966
+ // Eligibility is checked against the entry locale. Changing it can make
14967
+ // otherwise pure expansions require the asynchronous byte-aware path.
14968
+ if (assignment && (assignment.name === "LC_ALL" || assignment.name === "LC_CTYPE" || assignment.name === "LC_COLLATE" || assignment.name === "LANG"))
14969
+ return false;
15055
14970
  if (!assignment || (assignment.append && this.budget.limits.maxExpansionBytes !== Infinity) || assignment.name === "OPTIND" || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || rawState.readonlyVariables?.has(assignment.name) || rawState.variableAttributes?.get(assignment.name) || store?.get(assignment.name) || !this.isPureSyncValueWord(assignment.value, rawState)) {
15056
14971
  return false;
15057
14972
  }
@@ -16855,7 +16770,8 @@ export class Runtime {
16855
16770
  }
16856
16771
  else {
16857
16772
  monitor.values.invalidate(varName);
16858
- monitor.proxy.exported.delete(varName);
16773
+ if (!rawState.exported.has(varName))
16774
+ monitor.proxy.exported.delete(varName);
16859
16775
  }
16860
16776
  }
16861
16777
  }
@@ -17120,7 +17036,7 @@ export class Runtime {
17120
17036
  };
17121
17037
  return visit(script);
17122
17038
  }
17123
- extractLoopInvariantJqInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState) {
17039
+ extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState) {
17124
17040
  const w0 = cmd.words[0]?.plain;
17125
17041
  const resolveInvariantWord = (w) => {
17126
17042
  if (w.plain !== undefined)
@@ -17137,10 +17053,10 @@ export class Runtime {
17137
17053
  }
17138
17054
  return undefined;
17139
17055
  };
17140
- if (w0 === "jq" || w0 === "numfmt") {
17056
+ if (w0 === "jq" || w0 === "numfmt" || w0 === "awk") {
17141
17057
  if (hasSingleHereStringRedir) {
17142
17058
  const resolved = resolveInvariantWord(cmd.redirects[0].target);
17143
- return resolved !== undefined ? resolved.trim() : undefined;
17059
+ return resolved !== undefined ? resolved + "\n" : undefined;
17144
17060
  }
17145
17061
  if (this._fileWrites?.size || this._outputFiles?.size)
17146
17062
  return undefined;
@@ -17152,12 +17068,12 @@ export class Runtime {
17152
17068
  const vCheck = this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, fPlain), false);
17153
17069
  if (!vCheck || vCheck.byteLength > 16384 || vCheck.includes(0))
17154
17070
  return undefined;
17155
- return sharedSyncPipeDecoder.decode(vCheck).trim();
17071
+ return sharedSyncPipeDecoder.decode(vCheck);
17156
17072
  }
17157
17073
  if (w0 === "cat") {
17158
17074
  if (hasSingleHereStringRedir) {
17159
17075
  const resolved = resolveInvariantWord(cmd.redirects[0].target);
17160
- return resolved !== undefined ? resolved.trim() : undefined;
17076
+ return resolved !== undefined ? resolved + "\n" : undefined;
17161
17077
  }
17162
17078
  if (this._fileWrites?.size || this._outputFiles?.size)
17163
17079
  return undefined;
@@ -17169,12 +17085,12 @@ export class Runtime {
17169
17085
  const vCheck = this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, fPlain), false);
17170
17086
  if (!vCheck || vCheck.byteLength > 16384 || vCheck.includes(0))
17171
17087
  return undefined;
17172
- return sharedSyncPipeDecoder.decode(vCheck).trim();
17088
+ return sharedSyncPipeDecoder.decode(vCheck);
17173
17089
  }
17174
17090
  if (w0 === "echo" && cmd.words.length === 2) {
17175
17091
  const resolved = resolveInvariantWord(cmd.words[1]);
17176
17092
  if (resolved !== undefined && !resolved.startsWith("-"))
17177
- return resolved.trim();
17093
+ return resolved + "\n";
17178
17094
  return undefined;
17179
17095
  }
17180
17096
  if (w0 === "printf" && cmd.words.length >= 2) {
@@ -17186,7 +17102,7 @@ export class Runtime {
17186
17102
  args.push(r);
17187
17103
  }
17188
17104
  const formatted = tryFastPrintf(args);
17189
- return formatted !== undefined ? formatted.trim() : undefined;
17105
+ return formatted;
17190
17106
  }
17191
17107
  return undefined;
17192
17108
  }
@@ -17662,7 +17578,7 @@ export class Runtime {
17662
17578
  break;
17663
17579
  }
17664
17580
  if (step.unsetVars !== undefined) {
17665
- lastArg = this.execSyncUnsetStep(step, rawState, io, monitor, touched);
17581
+ lastArg = this.execSyncUnsetStep(step, rawState, monitor, touched);
17666
17582
  rawState.status = 0;
17667
17583
  continue;
17668
17584
  }
@@ -18240,7 +18156,7 @@ export class Runtime {
18240
18156
  break;
18241
18157
  }
18242
18158
  if (step.unsetVars !== undefined) {
18243
- lastArg = this.execSyncUnsetStep(step, rawState, io, monitor, touched);
18159
+ lastArg = this.execSyncUnsetStep(step, rawState, monitor, touched);
18244
18160
  rawState.status = 0;
18245
18161
  onUpdate({ lastCmd, lastArg });
18246
18162
  continue;
@@ -18425,7 +18341,7 @@ export class Runtime {
18425
18341
  break;
18426
18342
  }
18427
18343
  if (step.unsetVars !== undefined) {
18428
- lastArg = this.execSyncUnsetStep(step, rawState, io, monitor, touched);
18344
+ lastArg = this.execSyncUnsetStep(step, rawState, monitor, touched);
18429
18345
  rawState.status = 0;
18430
18346
  continue;
18431
18347
  }
@@ -27530,17 +27446,17 @@ export class Runtime {
27530
27446
  if (st === "ceil")
27531
27447
  return typeof item === "number" ? [Math.ceil(item)] : undefined;
27532
27448
  if (st === "round")
27533
- return typeof item === "number" ? [Math.round(item)] : undefined;
27449
+ return typeof item === "number" ? [Math.sign(item) * Math.round(Math.abs(item))] : undefined;
27534
27450
  if (st === "abs")
27535
27451
  return typeof item === "number" ? [Math.abs(item)] : undefined;
27536
27452
  if (st === "utf8bytelength")
27537
- return typeof item === "string" ? [Buffer.byteLength(item, "utf8")] : undefined;
27453
+ return typeof item === "string" ? [fastSharedTextEncoder.encode(item).byteLength] : undefined;
27538
27454
  if (st === "explode")
27539
27455
  return typeof item === "string" ? [Array.from(item, c => c.codePointAt(0))] : undefined;
27540
27456
  if (st === "implode") {
27541
27457
  if (!Array.isArray(item) || !item.every(x => typeof x === "number" && Number.isInteger(x) && x >= 0 && x <= 0x10ffff))
27542
27458
  return undefined;
27543
- return [String.fromCodePoint(...item)];
27459
+ return [item.map(cp => String.fromCodePoint(cp >= 0xd800 && cp <= 0xdfff ? 0xfffd : cp)).join("")];
27544
27460
  }
27545
27461
  if (st === "transpose") {
27546
27462
  if (!Array.isArray(item) || !item.every(row => Array.isArray(row)))
@@ -27554,14 +27470,20 @@ export class Runtime {
27554
27470
  return [trans];
27555
27471
  }
27556
27472
  const idxFnM = /^(index|rindex|indices)\(\s*"([^"\\]*)"\s*\)$/.exec(st);
27557
- if (idxFnM && typeof item === "string") {
27473
+ if (idxFnM && (typeof item === "string" || Array.isArray(item))) {
27558
27474
  const fn = idxFnM[1];
27559
27475
  const sub = idxFnM[2];
27560
27476
  const found = [];
27561
- if (sub.length > 0) {
27477
+ if (Array.isArray(item)) {
27478
+ for (let i = 0; i < item.length; i++) {
27479
+ if (item[i] === sub)
27480
+ found.push(i);
27481
+ }
27482
+ }
27483
+ else if (sub.length > 0) {
27562
27484
  let pos = 0;
27563
27485
  while ((pos = item.indexOf(sub, pos)) !== -1) {
27564
- found.push(Array.from(item.slice(0, pos)).length);
27486
+ found.push(fastSharedTextEncoder.encode(item.slice(0, pos)).byteLength);
27565
27487
  pos += 1;
27566
27488
  }
27567
27489
  }
@@ -28967,6 +28889,8 @@ export class Runtime {
28967
28889
  const tm = /^(\$(?:[0-9]+|NF)|NR|NF)\s*(==|!=|>=|<=|>|<)\s*(-?[0-9]+(?:\.[0-9]+)?|"[^"$\\]*")\s*\?\s*(\$(?:[0-9]+|NF)|"[^"$\\]*"|-?[0-9]+(?:\.[0-9]+)?)\s*:\s*(\$(?:[0-9]+|NF)|"[^"$\\]*"|-?[0-9]+(?:\.[0-9]+)?)$/.exec(m[1].trim());
28968
28890
  if (!tm)
28969
28891
  return undefined;
28892
+ if (tm[2] === ">")
28893
+ return undefined; // Unparenthesized print > is output redirection.
28970
28894
  parts.push({ kind: "ternary", lhs: tm[1], op: tm[2], rhs: tm[3], yes: tm[4], no: tm[5] });
28971
28895
  }
28972
28896
  else if (m[2] !== undefined)
@@ -29080,8 +29004,10 @@ export class Runtime {
29080
29004
  else if (p.kind === "int") {
29081
29005
  const idx = p.token === "NF" ? fields.length : Number(p.token);
29082
29006
  const s = idx === 0 ? l : (idx >= 1 && idx <= fields.length ? fields[idx - 1] : "");
29083
- const n = Number(/^[ \t]*([+-]?(?:\d+(?:\.\d*)?|\.\d+))/.exec(s)?.[1] ?? 0);
29084
- out += String(Math.trunc(n));
29007
+ const n = awkNumber(awkInputValue(s));
29008
+ if (!Number.isFinite(n))
29009
+ return undefined;
29010
+ out += awkValueText(awkNumeric(Math.trunc(n)));
29085
29011
  }
29086
29012
  else if (p.kind === "ternary") {
29087
29013
  const resolveAtom = (tok) => {
@@ -29099,16 +29025,10 @@ export class Runtime {
29099
29025
  };
29100
29026
  const lv = resolveAtom(p.lhs);
29101
29027
  const rv = resolveAtom(p.rhs);
29102
- const isStrCmp = p.rhs.startsWith("\"");
29103
- let cond = false;
29104
- if (isStrCmp) {
29105
- cond = p.op === "==" ? lv === rv : p.op === "!=" ? lv !== rv : p.op === ">" ? lv > rv : p.op === "<" ? lv < rv : p.op === ">=" ? lv >= rv : lv <= rv;
29106
- }
29107
- else {
29108
- const ln = Number(lv) || 0;
29109
- const rn = Number(rv) || 0;
29110
- cond = p.op === "==" ? ln === rn : p.op === "!=" ? ln !== rn : p.op === ">" ? ln > rn : p.op === "<" ? ln < rn : p.op === ">=" ? ln >= rn : ln <= rn;
29111
- }
29028
+ const left = p.lhs === "NR" || p.lhs === "NF" ? awkNumeric(Number(lv)) : awkInputValue(lv);
29029
+ const right = p.rhs.startsWith('"') ? awkString(rv) : awkNumeric(Number(rv));
29030
+ const comparison = awkCompare(left, right, "%.6g");
29031
+ const cond = p.op === "==" ? comparison === 0 : p.op === "!=" ? comparison !== 0 : p.op === ">" ? comparison > 0 : p.op === "<" ? comparison < 0 : p.op === ">=" ? comparison >= 0 : comparison <= 0;
29112
29032
  out += resolveAtom(cond ? p.yes : p.no);
29113
29033
  }
29114
29034
  else if (p.kind === "arith") {
@@ -29373,13 +29293,14 @@ export class Runtime {
29373
29293
  if (s.length === 0)
29374
29294
  return [""];
29375
29295
  const res = [];
29296
+ const chars = Array.from(s);
29376
29297
  const escapes = { b: "\b", f: "\f", n: "\n", r: "\r", t: "\t", v: "\v", "0": "" };
29377
- for (let i = 0; i < s.length; i++) {
29378
- const ch = s[i];
29298
+ for (let i = 0; i < chars.length; i++) {
29299
+ const ch = chars[i];
29379
29300
  if (ch === "\\") {
29380
- if (i + 1 >= s.length)
29301
+ if (i + 1 >= chars.length)
29381
29302
  return undefined;
29382
- const esc = s[++i];
29303
+ const esc = chars[++i];
29383
29304
  res.push(escapes[esc] ?? esc);
29384
29305
  }
29385
29306
  else {
@@ -97606,7 +97606,8 @@ var lookupSpecialForms = {
97606
97606
  if (!args.length || args.length > 4) return error("#VALUE!");
97607
97607
  let source = args[0];
97608
97608
  while (source.kind === "parentheses") source = source.child;
97609
- let value3 = host.evaluate(source, false);
97609
+ const areaSet = source.kind === "binary" && source.op === "union";
97610
+ let value3 = host.evaluate(source, areaSet);
97610
97611
  if (value3.kind === "error") return value3;
97611
97612
  const offsets = [0, 0, 0];
97612
97613
  for (let index2 = 1; index2 < args.length; index2++) {
@@ -97616,11 +97617,17 @@ var lookupSpecialForms = {
97616
97617
  if (n === void 0) return error("#VALUE!");
97617
97618
  offsets[index2 - 1] = Math.trunc(n) - 1;
97618
97619
  }
97619
- if (source.kind === "binary" && source.op === "union") {
97620
- if (value3.kind === "matrix") {
97621
- if (offsets[2] < 0 || offsets[2] >= value3.rows.length) return error("#REF!");
97622
- value3 = value3.rows[offsets[2]][0];
97623
- } else return error("#REF!");
97620
+ if (areaSet) {
97621
+ const areas = [], pending = [value3];
97622
+ while (pending.length) {
97623
+ host.tick();
97624
+ const area = pending.pop();
97625
+ if (area.kind === "set") for (let index2 = area.values.length - 1; index2 >= 0; index2--) pending.push(area.values[index2]);
97626
+ else areas.push(area);
97627
+ }
97628
+ if (offsets[2] < 0 || offsets[2] >= areas.length) return error("#REF!");
97629
+ value3 = areas[offsets[2]];
97630
+ if (value3.kind === "error") return value3;
97624
97631
  } else if (offsets[2] !== 0) return error("#REF!");
97625
97632
  const row = offsets[0], column = offsets[1], dims = dimensions(value3);
97626
97633
  if (row < 0 || column < 0 || row >= dims.height || column >= dims.width) return error("#REF!");
@@ -140035,6 +140042,7 @@ function lotusExternalVariable(name) {
140035
140042
  async function lotusFormula(bytes, format2, group, row, column, sheetIndex, sheetName2, context, consumeOperation, functions2 = lotusFunctions, names2, legacyReferenceLayout) {
140036
140043
  const b3 = new Binary(bytes), stack = [], modern = format2 !== "wk1";
140037
140044
  const relativeReferences = /* @__PURE__ */ new Map();
140045
+ const indexRanges = /* @__PURE__ */ new Map();
140038
140046
  let at = 0;
140039
140047
  const pop = async () => {
140040
140048
  if (stack.length) return stack.pop();
@@ -140042,7 +140050,8 @@ async function lotusFormula(bytes, format2, group, row, column, sheetIndex, shee
140042
140050
  return "#REF!";
140043
140051
  };
140044
140052
  const ref = (r, c4, rr, cr) => {
140045
- if (r < 0 || c4 < 0) return "#REF!";
140053
+ const rows = modern || legacyReferenceLayout === void 0 ? 65536 : legacyReferenceLayout === "wk1" ? 2048 : 16384;
140054
+ if (r < 0 || r >= rows || c4 < 0 || c4 >= 256) return "#REF!";
140046
140055
  const a3 = formatA1(r, c4);
140047
140056
  let i = 0;
140048
140057
  while (a3[i] >= "A" && a3[i] <= "Z") i++;
@@ -140052,13 +140061,13 @@ async function lotusFormula(bytes, format2, group, row, column, sheetIndex, shee
140052
140061
  const c4 = b3.u16(p2), r = b3.u16(p2 + 2), cr = !!(c4 & 32768), rr = !!(r & 32768);
140053
140062
  if (legacyReferenceLayout === "works3" || legacyReferenceLayout === "symphony") {
140054
140063
  const axis = (raw, origin, bits) => {
140055
- if (!(raw & 32768)) return raw;
140064
+ if (!(raw & 32768)) return raw & (1 << bits) - 1;
140056
140065
  const shift = 32 - bits, boundary = 2 ** (bits - 1);
140057
140066
  let delta = raw << shift >> shift;
140058
140067
  if (delta + origin >= boundary) delta -= boundary;
140059
140068
  return origin + delta;
140060
140069
  };
140061
- let targetColumn = c4;
140070
+ let targetColumn = c4 & 255;
140062
140071
  if (legacyReferenceLayout === "symphony" && cr) {
140063
140072
  let delta = c4 & 255;
140064
140073
  if (delta & 128 && delta + column >= 256) delta -= 256;
@@ -140086,6 +140095,10 @@ async function lotusFormula(bytes, format2, group, row, column, sheetIndex, shee
140086
140095
  const target = b3.u8(p2 + 2), name = sheetName2(target);
140087
140096
  return (target === sheetIndex && !qualifySheet ? "" : quoteFormulaString(name, "'", gnumericGrammar) + "!") + ref(b3.u16(p2), b3.u8(p2 + 3), !!(flags & 2), !!(flags & 1));
140088
140097
  };
140098
+ const rangeReference = (first, last) => {
140099
+ if (first.endsWith("#REF!") || last?.endsWith("#REF!")) return "#REF!";
140100
+ return first + (last === void 0 ? "" : ":" + last);
140101
+ };
140089
140102
  while (at < bytes.length) {
140090
140103
  context.signal.throwIfAborted();
140091
140104
  const op = b3.u8(at++);
@@ -140119,8 +140132,17 @@ async function lotusFormula(bytes, format2, group, row, column, sheetIndex, shee
140119
140132
  const name = `LOTUS_SHEET_REFERENCE_${relativeReferences.size}`;
140120
140133
  relativeReferences.set(name, { kind: "reference", start: 0, end: 0, first, ...last ? { last } : {} });
140121
140134
  stack.push(name);
140122
- } else stack.push(newRef(at + 1, flags & 7, crossSheet) + (op === 2 ? `:${newRef(at + 5, flags >> 3 & 7, crossSheet)}` : ""));
140123
- } else stack.push(oldRef(at) + (op === 2 ? `:${oldRef(at + 4)}` : ""));
140135
+ } else {
140136
+ const source = rangeReference(newRef(at + 1, flags & 7, crossSheet), op === 2 ? newRef(at + 5, flags >> 3 & 7, crossSheet) : void 0);
140137
+ stack.push(source);
140138
+ if (crossSheet) indexRanges.set(source, {
140139
+ firstSheet: b3.u8(at + 3),
140140
+ lastSheet: b3.u8(at + 7),
140141
+ first: ref(b3.u16(at + 1), b3.u8(at + 4), !!(flags & 2), !!(flags & 1)),
140142
+ last: ref(b3.u16(at + 5), b3.u8(at + 8), !!(flags & 16), !!(flags & 8))
140143
+ });
140144
+ }
140145
+ } else stack.push(rangeReference(oldRef(at), op === 2 ? oldRef(at + 4) : void 0));
140124
140146
  at += length;
140125
140147
  } else if (op === 5) {
140126
140148
  const length = format2 === "123" ? 4 : 2;
@@ -140159,7 +140181,14 @@ async function lotusFormula(bytes, format2, group, row, column, sheetIndex, shee
140159
140181
  const crossSheet = range3.first.sheet !== range3.last.sheet;
140160
140182
  const endpoint = (point) => (point.sheet === sheetIndex && !crossSheet ? "" : quoteFormulaString(sheetName2(point.sheet), "'", gnumericGrammar) + "!") + ref(point.row, point.column, op === 7, op === 7);
140161
140183
  const single = range3.first.row === range3.last.row && range3.first.column === range3.last.column && range3.first.sheet === range3.last.sheet;
140162
- stack.push(endpoint(range3.first) + (single ? "" : ":" + endpoint(range3.last)));
140184
+ const source = endpoint(range3.first) + (single ? "" : ":" + endpoint(range3.last));
140185
+ stack.push(source);
140186
+ if (crossSheet) indexRanges.set(source, {
140187
+ firstSheet: range3.first.sheet,
140188
+ lastSheet: range3.last.sheet,
140189
+ first: ref(range3.first.row, range3.first.column, op === 7, op === 7),
140190
+ last: ref(range3.last.row, range3.last.column, op === 7, op === 7)
140191
+ });
140163
140192
  }
140164
140193
  } else if (modern && op >= 9 && op <= 11) {
140165
140194
  const length = op === 9 ? 4 : op === 10 ? 5 : 11;
@@ -140203,7 +140232,7 @@ async function lotusFormula(bytes, format2, group, row, column, sheetIndex, shee
140203
140232
  }
140204
140233
  const operands = [];
140205
140234
  for (let i = 0; i < args; i++) operands.unshift(await pop());
140206
- let subtract3 = 0;
140235
+ let subtract3 = info?.[3] === "wk1_year_func" ? 1900 : 0;
140207
140236
  if (functions2 === lotusFunctions) {
140208
140237
  switch (info?.[1]) {
140209
140238
  case "CHOOSE":
@@ -140221,19 +140250,36 @@ async function lotusFormula(bytes, format2, group, row, column, sheetIndex, shee
140221
140250
  case "HLOOKUP":
140222
140251
  if (operands.length === 3) operands[2] = `(${operands[2]}+1)`;
140223
140252
  break;
140253
+ case "DSUM":
140254
+ case "DAVG":
140255
+ case "DCNT":
140256
+ case "DMIN":
140257
+ case "DMAX":
140258
+ case "DVAR":
140259
+ case "DSTD":
140260
+ case "DPURECOUNT":
140261
+ if (operands.length > 1) operands[1] = `(${operands[1]}+1)`;
140262
+ break;
140224
140263
  case "INDEX":
140225
- if (operands.length === 3) {
140264
+ if (operands.length === 3 || operands.length === 4) {
140226
140265
  const [, column2, row2] = operands;
140227
140266
  operands[1] = `(${row2}+1)`;
140228
140267
  operands[2] = `(${column2}+1)`;
140268
+ if (operands.length === 4) operands[3] = `(${operands[3]}+1)`;
140269
+ const span2 = indexRanges.get(operands[0]);
140270
+ if (span2) {
140271
+ const choices = [];
140272
+ for (let index2 = Math.min(span2.firstSheet, span2.lastSheet); index2 <= Math.max(span2.firstSheet, span2.lastSheet); index2++) {
140273
+ consumeOperation();
140274
+ choices.push(quoteFormulaString(sheetName2(index2), "'", gnumericGrammar) + "!" + span2.first + ":" + span2.last);
140275
+ }
140276
+ operands[0] = `(${choices.join(",")})`;
140277
+ }
140229
140278
  }
140230
140279
  break;
140231
140280
  case "STRING":
140232
140281
  operands.push("TRUE()");
140233
140282
  break;
140234
- case "YEAR":
140235
- subtract3 = 1900;
140236
- break;
140237
140283
  case "ROUNDUP":
140238
140284
  case "ROUNDDOWN":
140239
140285
  if (operands.length === 3) operands.pop();
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  YqValueFailure,
3
3
  createYqQuerySession
4
- } from "../safe-bash/command-chunks/chunk-6QU5OLPJ.js";
4
+ } from "../safe-bash/command-chunks/chunk-4AWKMIU3.js";
5
5
  import "../safe-bash/command-chunks/chunk-S3BO2NJT.js";
6
- import "../safe-bash/command-chunks/chunk-6742OVAC.js";
6
+ import "../safe-bash/command-chunks/chunk-WX5IUIQK.js";
7
7
  import "../safe-bash/command-chunks/chunk-TPDKSK66.js";
8
8
  import "../safe-bash/command-chunks/chunk-A7SJ2FC6.js";
9
9
  import "../safe-bash/command-chunks/chunk-XZ7QGZMG.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Interpreter
3
- } from "../safe-bash/command-chunks/chunk-6742OVAC.js";
3
+ } from "../safe-bash/command-chunks/chunk-WX5IUIQK.js";
4
4
  import "../safe-bash/command-chunks/chunk-TPDKSK66.js";
5
5
  import "../safe-bash/command-chunks/chunk-A7SJ2FC6.js";
6
6
  import "../safe-bash/command-chunks/chunk-XZ7QGZMG.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  YqValueFailure,
3
3
  createYqQuerySession
4
- } from "../safe-bash/command-chunks/chunk-6QU5OLPJ.js";
4
+ } from "../safe-bash/command-chunks/chunk-4AWKMIU3.js";
5
5
  import "../safe-bash/command-chunks/chunk-S3BO2NJT.js";
6
- import "../safe-bash/command-chunks/chunk-6742OVAC.js";
6
+ import "../safe-bash/command-chunks/chunk-WX5IUIQK.js";
7
7
  import "../safe-bash/command-chunks/chunk-TPDKSK66.js";
8
8
  import "../safe-bash/command-chunks/chunk-A7SJ2FC6.js";
9
9
  import "../safe-bash/command-chunks/chunk-XZ7QGZMG.js";