@poe-platform/safe-bash 0.1.523 → 0.1.525

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.
@@ -33508,8 +33508,8 @@ async function entities(text3, budget) {
33508
33508
  const name2 = match[1];
33509
33509
  if (name2[0] !== "#") result2.append(Object.hasOwn(named, name2) ? named[name2] : match[0]);
33510
33510
  else {
33511
- const hexadecimal = name2[1]?.toLowerCase() === "x";
33512
- const value2 = Number.parseInt(name2.slice(hexadecimal ? 2 : 1), hexadecimal ? 16 : 10);
33511
+ const hexadecimal2 = name2[1]?.toLowerCase() === "x";
33512
+ const value2 = Number.parseInt(name2.slice(hexadecimal2 ? 2 : 1), hexadecimal2 ? 16 : 10);
33513
33513
  result2.append(value2 === 0 || value2 > 1114111 || value2 >= 55296 && value2 <= 57343 ? "\uFFFD" : String.fromCodePoint(value2));
33514
33514
  }
33515
33515
  offset += match[0].length;
@@ -38126,7 +38126,8 @@ shell: command substitution: line ${line}: \`${sourceLine}'
38126
38126
  } else if (!literal && (inner === "$" || inner === "`")) {
38127
38127
  this.expansion(parts, true);
38128
38128
  const part = parts.at(-1);
38129
- nameListing ||= part.kind === "variable" && part.prefixNames === "@";
38129
+ const selector = getArraySelector(part);
38130
+ nameListing ||= part.kind === "variable" && (part.prefixNames === "@" || !!part.transform && (part.name === "@" || selector?.kind === "members" && selector.separator === "@"));
38130
38131
  } else if (inner === "\\" && /[$`"\\\n]/u.test(this.source[this.position + 1] ?? "")) {
38131
38132
  const escaped3 = this.source[this.position + 1];
38132
38133
  if (escaped3 !== "\n") text3(escaped3, true, false, this.position, this.position + 2);
@@ -38329,7 +38330,14 @@ shell: command substitution: line ${line}: \`${sourceLine}'
38329
38330
  if (end < 0) this.error("Unterminated indexed-array subscript");
38330
38331
  selector = arraySelector(this.source.slice(start, end), start, this.budget);
38331
38332
  this.position = end + 1;
38332
- if (this.source[this.position] !== "}") this.error("Unsupported indexed-array operator");
38333
+ if (this.source[this.position] !== "}" && this.source[this.position] !== "@") this.error("Unsupported indexed-array operator");
38334
+ }
38335
+ let transform2;
38336
+ if (this.source[this.position] === "@") {
38337
+ const operation2 = this.source[this.position + 1];
38338
+ if (length || prefixNames || operation2 !== "Q" && operation2 !== "E" || this.source[this.position + 2] !== "}") this.error("Unsupported parameter transform");
38339
+ transform2 = operation2;
38340
+ this.position += 2;
38333
38341
  }
38334
38342
  const operator = /^(?::[-=+?]|##|%%|\/\/|\/[#%]?|[-=+?#%])/u.exec(this.source.slice(this.position))?.[0];
38335
38343
  let alternate;
@@ -38373,7 +38381,7 @@ shell: command substitution: line ${line}: \`${sourceLine}'
38373
38381
  parts.push({ kind: "failed-parameter", source: this.source.slice(parameterStart, this.position), line, quoted: quoted2 });
38374
38382
  } else {
38375
38383
  this.position++;
38376
- const part = { kind: "variable", name: name2, quoted: quoted2, line, ...prefixNames ? { prefixNames } : {}, ...length ? { length } : {}, ...operator ? { operator, alternate } : {}, ...replacement ? { replacement } : {}, ...substring ? { substring } : {} };
38384
+ const part = { kind: "variable", name: name2, quoted: quoted2, line, ...prefixNames ? { prefixNames } : {}, ...transform2 ? { transform: transform2 } : {}, ...length ? { length } : {}, ...operator ? { operator, alternate } : {}, ...replacement ? { replacement } : {}, ...substring ? { substring } : {} };
38377
38385
  if (selector) setArraySelector(part, selector);
38378
38386
  parts.push(part);
38379
38387
  }
@@ -41609,6 +41617,138 @@ function* pathTargets(name2, path, limits, signal, fail4) {
41609
41617
  }
41610
41618
  }
41611
41619
 
41620
+ // packages/safe-bash/src/shell/parameter-transforms.ts
41621
+ init_platform();
41622
+ function hexadecimal(byte) {
41623
+ return byte >= 48 && byte <= 57 ? byte - 48 : byte >= 65 && byte <= 70 ? byte - 55 : byte >= 97 && byte <= 102 ? byte - 87 : -1;
41624
+ }
41625
+ function utf8Unit(bytes3, offset) {
41626
+ const first = bytes3[offset];
41627
+ if (first < 128) return { point: first, size: 1 };
41628
+ const size = first >= 194 && first <= 223 ? 2 : first >= 224 && first <= 239 ? 3 : first >= 240 && first <= 244 ? 4 : 0;
41629
+ if (!size || offset + size > bytes3.length) return { point: -1, size: 1 };
41630
+ let point = first & 127 >> size;
41631
+ for (let index = 1; index < size; index++) {
41632
+ const byte = bytes3[offset + index];
41633
+ if (byte < 128 || byte > 191) return { point: -1, size: 1 };
41634
+ point = point * 64 + (byte & 63);
41635
+ }
41636
+ if (point < (size === 2 ? 128 : size === 3 ? 2048 : 65536) || point > 1114111 || point >= 55296 && point <= 57343) return { point: -1, size: 1 };
41637
+ return { point, size };
41638
+ }
41639
+ var controlEscapes = { 7: 97, 8: 98, 9: 116, 10: 110, 11: 118, 12: 102, 13: 114, 27: 69 };
41640
+ var decodedEscapes = { 97: 7, 98: 8, 116: 9, 110: 10, 118: 11, 102: 12, 114: 13, 101: 27, 69: 27, 92: 92, 39: 39, 34: 34, 63: 63 };
41641
+ async function transformParameter(value2, operator, options3) {
41642
+ const { work, allocation, maximumBytes } = options3;
41643
+ work.signal.throwIfAborted();
41644
+ if (typeof value2 === "string") {
41645
+ if (value2.length > maximumBytes) work.exhausted();
41646
+ if ((await scanString(value2, work)).bytes > maximumBytes) work.exhausted();
41647
+ } else if (shellValueByteLength(value2) > maximumBytes) work.exhausted();
41648
+ const input3 = shellValueBytes(value2, allocation);
41649
+ let ansi = false;
41650
+ if (operator === "Q") {
41651
+ for (let offset = 0; offset < input3.length; ) {
41652
+ const pending = stringCheckpoint(work);
41653
+ if (pending) await pending;
41654
+ const unit2 = options3.byteLocale ? { point: input3[offset], size: 1 } : utf8Unit(input3, offset);
41655
+ const printable = unit2.point >= 32 && unit2.point < 127 || !options3.byteLocale && unit2.point >= 128 && !/[\p{Cc}\p{Cf}\p{Cn}]/u.test(String.fromCodePoint(unit2.point));
41656
+ if (!printable) ansi = true;
41657
+ offset += unit2.size;
41658
+ }
41659
+ }
41660
+ let output2 = void 0;
41661
+ let size = 0;
41662
+ const emit2 = (byte) => {
41663
+ if (size >= maximumBytes) work.exhausted();
41664
+ if (output2) output2[size] = byte;
41665
+ size++;
41666
+ };
41667
+ const ascii2 = (text3) => {
41668
+ for (let index = 0; index < text3.length; index++) emit2(text3.charCodeAt(index));
41669
+ };
41670
+ const scan = async () => {
41671
+ size = 0;
41672
+ if (operator === "Q") {
41673
+ ascii2(ansi ? "$'" : "'");
41674
+ for (let offset = 0; offset < input3.length; ) {
41675
+ const pending = stringCheckpoint(work);
41676
+ if (pending) await pending;
41677
+ const unit2 = options3.byteLocale ? { point: input3[offset], size: 1 } : utf8Unit(input3, offset);
41678
+ const printable = unit2.point >= 32 && unit2.point < 127 || !options3.byteLocale && unit2.point >= 128 && !/[\p{Cc}\p{Cf}\p{Cn}]/u.test(String.fromCodePoint(unit2.point));
41679
+ if (ansi && !printable) {
41680
+ if (unit2.size === 1 && controlEscapes[input3[offset]] !== void 0) {
41681
+ emit2(92);
41682
+ emit2(controlEscapes[input3[offset]]);
41683
+ } else for (let index = 0; index < unit2.size; index++) ascii2("\\" + input3[offset + index].toString(8).padStart(3, "0"));
41684
+ } else if (unit2.point === 39) ascii2(ansi ? "\\'" : "'\\''");
41685
+ else if (ansi && unit2.point === 92) ascii2("\\\\");
41686
+ else for (let index = 0; index < unit2.size; index++) emit2(input3[offset + index]);
41687
+ offset += unit2.size;
41688
+ }
41689
+ emit2(39);
41690
+ return;
41691
+ }
41692
+ for (let offset = 0; offset < input3.length; ) {
41693
+ const pending = stringCheckpoint(work);
41694
+ if (pending) await pending;
41695
+ let byte = input3[offset++];
41696
+ if (byte === 92 && offset < input3.length) {
41697
+ const escape = input3[offset++];
41698
+ if (decodedEscapes[escape] !== void 0) byte = decodedEscapes[escape];
41699
+ else if (escape >= 48 && escape <= 55) {
41700
+ byte = escape - 48;
41701
+ for (let count2 = 1; count2 < 3 && offset < input3.length && input3[offset] >= 48 && input3[offset] <= 55; count2++) byte = byte * 8 + input3[offset++] - 48;
41702
+ byte &= 255;
41703
+ } else if (escape === 120 || escape === 117 || escape === 85) {
41704
+ const maximum = escape === 120 ? 2 : escape === 117 ? 4 : 8;
41705
+ let point = 0;
41706
+ let count2 = 0;
41707
+ while (count2 < maximum && offset < input3.length && hexadecimal(input3[offset]) >= 0) {
41708
+ point = point * 16 + hexadecimal(input3[offset++]);
41709
+ count2++;
41710
+ }
41711
+ if (!count2) {
41712
+ emit2(92);
41713
+ emit2(escape);
41714
+ continue;
41715
+ }
41716
+ if (escape === 120) byte = point;
41717
+ else {
41718
+ if (!point || point >= 2147483648) return;
41719
+ if (options3.byteLocale && point >= 55296 && point <= 57343) ascii2(`\\u${point.toString(16).toUpperCase().padStart(4, "0")}`);
41720
+ else {
41721
+ const width = point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : point < 2097152 ? 4 : point < 67108864 ? 5 : 6;
41722
+ if (width === 1) emit2(point);
41723
+ else {
41724
+ const divisor = 64 ** (width - 1);
41725
+ emit2(256 - 2 ** (8 - width) + Math.floor(point / divisor));
41726
+ for (let shift = width - 2; shift >= 0; shift--) emit2(128 + Math.floor(point / 64 ** shift) % 64);
41727
+ }
41728
+ }
41729
+ continue;
41730
+ }
41731
+ } else if (escape === 99 && offset < input3.length) {
41732
+ const control = input3[offset++];
41733
+ if (control === 92 && input3[offset] === 92) offset++;
41734
+ byte = control === 63 ? 127 : control & 31;
41735
+ } else {
41736
+ emit2(92);
41737
+ byte = escape;
41738
+ }
41739
+ }
41740
+ if (!byte) return;
41741
+ emit2(byte);
41742
+ }
41743
+ };
41744
+ await scan();
41745
+ allocation.reserve(size + 64, 1);
41746
+ output2 = new Uint8Array(size);
41747
+ await scan();
41748
+ work.signal.throwIfAborted();
41749
+ return shellValueFromBytes(output2, allocation);
41750
+ }
41751
+
41612
41752
  // packages/safe-bash/src/shell/runtime.ts
41613
41753
  var defaultLimits = {
41614
41754
  maxParseUnits: defaultMaxParseUnits,
@@ -43815,6 +43955,7 @@ var Runtime = class _Runtime {
43815
43955
  async document(document, state, io, line = document.endLine) {
43816
43956
  this.signal.throwIfAborted();
43817
43957
  let value2 = "";
43958
+ let fragments;
43818
43959
  let size = 0;
43819
43960
  let words = 0;
43820
43961
  const warnings = [];
@@ -43824,16 +43965,25 @@ var Runtime = class _Runtime {
43824
43965
  for (const warning of warnings.splice(0)) await writeDiagnostic(io.stderr, `shell: warning: ${warning}
43825
43966
  `);
43826
43967
  if (++words % 128 === 0) await yieldTurn(this.signal);
43827
- const part = (await this.word(word, state, { ...io, nameExpansionContext: "document" }, false)).join("");
43828
- size += import_buffer.Buffer.byteLength(part);
43968
+ const part = concatShellValues(await this.valueWord(word, state, { ...io, nameExpansionContext: "document" }, false), io[valueScope]);
43969
+ size += shellValueByteLength(part);
43829
43970
  if (size > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
43830
- value2 += part;
43971
+ if (!fragments && typeof part === "string") value2 += part;
43972
+ else {
43973
+ if (!fragments) {
43974
+ io[valueScope]?.reserve(64 + value2.length * 2, 0);
43975
+ fragments = [value2];
43976
+ value2 = "";
43977
+ }
43978
+ io[valueScope]?.reserve(32 + (typeof part === "string" ? part.length * 2 : 0), 0);
43979
+ fragments.push(part);
43980
+ }
43831
43981
  }
43832
43982
  } finally {
43833
43983
  for (const warning of warnings.splice(0)) await writeDiagnostic(io.stderr, `shell: warning: ${warning}
43834
43984
  `);
43835
43985
  }
43836
- return value2;
43986
+ return fragments ? concatShellValues(fragments, io[valueScope]) : value2;
43837
43987
  }
43838
43988
  async redirect(redirects, state, io, inputs2, outputs, isolatedInlineInput = false, persistMoves = false, fileShortcut = false, line) {
43839
43989
  this.signal.throwIfAborted();
@@ -43862,6 +44012,7 @@ var Runtime = class _Runtime {
43862
44012
  const stdinIsDefault = descriptor2?.input ? descriptor2.stdinIsDefault : false;
43863
44013
  return {
43864
44014
  [invocationScope]: io[invocationScope],
44015
+ ...io[valueScope] === void 0 ? {} : { [valueScope]: io[valueScope] },
43865
44016
  ...io.execution === void 0 ? {} : { execution: io.execution },
43866
44017
  ...io.diagnosticLine === void 0 ? {} : { diagnosticLine: io.diagnosticLine },
43867
44018
  ...io.diagnosticOffset === void 0 ? {} : { diagnosticOffset: io.diagnosticOffset },
@@ -43882,7 +44033,7 @@ var Runtime = class _Runtime {
43882
44033
  const hereString = redirect.operator === "<<<";
43883
44034
  let value2;
43884
44035
  try {
43885
- value2 = redirect.document ? await this.document(redirect.document, state, currentIO(), line) : (await this.word(redirect.target, state, currentIO(), false, false, hereString)).join("");
44036
+ value2 = redirect.document ? await this.document(redirect.document, state, currentIO(), line) : concatShellValues(await this.valueWord(redirect.target, state, currentIO(), false, false, hereString), io[valueScope]);
43886
44037
  } catch (error) {
43887
44038
  if (error instanceof NounsetFailure) throw error;
43888
44039
  if (error instanceof ParameterExpansionFailure && !isolatedInlineInput) throw error;
@@ -43891,10 +44042,10 @@ var Runtime = class _Runtime {
43891
44042
  throw error;
43892
44043
  }
43893
44044
  if (hereString) {
43894
- if (import_buffer.Buffer.byteLength(value2) >= this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
43895
- value2 += "\n";
44045
+ if (shellValueByteLength(value2) >= this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
44046
+ value2 = concatShellValues([value2, "\n"], io[valueScope]);
43896
44047
  }
43897
- const input3 = new ShellInput(toByteSource(value2), this.budget, this.signal);
44048
+ const input3 = new ShellInput(toByteSource(typeof value2 === "string" ? value2 : shellValueBytes(value2, io[valueScope])), this.budget, this.signal);
43898
44049
  inputs2.add(input3);
43899
44050
  descriptors.set(redirect.descriptor, { input: input3, stdinIsDefault: false });
43900
44051
  continue;
@@ -44241,6 +44392,7 @@ var Runtime = class _Runtime {
44241
44392
  }
44242
44393
  async dispatchScoped(name2, values, state, io, assignments2, bypassFunctions) {
44243
44394
  const { [invocationScope]: scope, ...publicIO } = io;
44395
+ Reflect.deleteProperty(publicIO, valueScope);
44244
44396
  const allocation = this.budget.values.scope();
44245
44397
  scope.register(() => allocation.close());
44246
44398
  const argumentValues = this.admitArguments(values, allocation);
@@ -44289,7 +44441,13 @@ var Runtime = class _Runtime {
44289
44441
  scope.assertOpen();
44290
44442
  const forwardedValues = getCommandArguments(forwarded);
44291
44443
  const admitted = forwardedValues === argumentValues ? argumentValues : this.admitArguments(forwardedValues.values, allocation);
44292
- const context3 = { ...forwarded, args: admitted.args, argumentValues: admitted, [invocationScope]: scope };
44444
+ const context3 = {
44445
+ ...forwarded,
44446
+ args: admitted.args,
44447
+ argumentValues: admitted,
44448
+ [invocationScope]: scope,
44449
+ ...io[valueScope] === void 0 ? {} : { [valueScope]: io[valueScope] }
44450
+ };
44293
44451
  const previous = /* @__PURE__ */ new Map();
44294
44452
  const cwd = state.cwd;
44295
44453
  const directoryStackCwdPublication = state.directoryStackCwdPublication;
@@ -44886,6 +45044,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
44886
45044
  return invocation2;
44887
45045
  }
44888
45046
  };
45047
+ Reflect.deleteProperty(context2, invocationScope);
45048
+ Reflect.deleteProperty(context2, valueScope);
44889
45049
  bindCommandIO(context2);
44890
45050
  bindFileOutputBudget(context2, (sink) => this.budget.sink(sink, runtime.signal));
44891
45051
  if (argumentValues.values.every((value2) => typeof value2 === "string")) Reflect.deleteProperty(context2, "argumentValues");
@@ -46447,6 +46607,31 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
46447
46607
  }
46448
46608
  }
46449
46609
  async valuePart(part, state, io, hereString = false) {
46610
+ if (part.kind === "variable" && part.transform) {
46611
+ const selector2 = getArraySelector(part);
46612
+ if (selector2?.kind === "members" || part.name === "@" || part.name === "*") {
46613
+ const members = selector2 ? await this.arrayMembers(part.name, state) : this.positionalValues(state);
46614
+ const ifs = state.variables.IFS ?? " ";
46615
+ const separator = ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
46616
+ const fragments = [];
46617
+ let bytes3 = 0;
46618
+ for (const member2 of members) {
46619
+ const value3 = await this.transformValue(member2, part.transform, state, io);
46620
+ bytes3 += shellValueByteLength(value3) + (fragments.length ? import_buffer.Buffer.byteLength(separator) : 0);
46621
+ if (bytes3 > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
46622
+ io[valueScope]?.reserve(32, 0);
46623
+ if (fragments.length) fragments.push(separator);
46624
+ fragments.push(value3);
46625
+ }
46626
+ return concatShellValues(fragments, io[valueScope]);
46627
+ }
46628
+ const base = { ...part };
46629
+ delete base.transform;
46630
+ copyArraySelector(part, base);
46631
+ const existing2 = selector2?.kind === "element" ? arrayStore(state)?.get(part.name)?.get(numericIndex(selector2.index) ?? -1) ?? (numericIndex(selector2.index) === 0 ? this.variable(state, part.name) : void 0) : /^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(part.name) ? this.variable(state, part.name) : /^[1-9][0-9]*$/u.test(part.name) ? state.positional[Number(part.name) - 1] : "";
46632
+ const value2 = await this.valuePart(base, state, io, hereString);
46633
+ return existing2 === void 0 ? "" : this.transformValue(value2, part.transform, state, io);
46634
+ }
46450
46635
  if (part.kind === "variable" && part.prefixNames) {
46451
46636
  const ifs = state.variables.IFS ?? " ";
46452
46637
  const separator = io.nameExpansionContext === "document" || io.nameExpansionContext === "conditional" && part.prefixNames === "@" ? " " : ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
@@ -46483,6 +46668,19 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
46483
46668
  if (state.depth + parameterDepth > 64) throw new ShellSyntaxError("Syntax nesting exceeds 64", word.offset);
46484
46669
  return { ...io, parameterDepth };
46485
46670
  }
46671
+ async transformValue(value2, operator, state, io) {
46672
+ const allocation = io[valueScope] ?? this.budget.values.scope();
46673
+ try {
46674
+ return await transformParameter(value2, operator, {
46675
+ maximumBytes: this.budget.limits.maxExpansionBytes,
46676
+ byteLocale: byteLocale(state.variables),
46677
+ allocation,
46678
+ work: { remaining: Math.min(Number.MAX_SAFE_INTEGER, this.budget.limits.maxExpansionBytes * 8 + 1024), signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") }
46679
+ });
46680
+ } finally {
46681
+ if (!io[valueScope]) allocation.close();
46682
+ }
46683
+ }
46486
46684
  async partValue(part, state, io, hereString) {
46487
46685
  this.signal.throwIfAborted();
46488
46686
  if (part.kind === "compound-substitution-eof") {
@@ -46852,7 +47050,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
46852
47050
  return fields3;
46853
47051
  }
46854
47052
  const arrayOwned = word.parts.some((part) => part.kind === "variable" && !part.prefixNames && (getArraySelector(part) !== void 0 || arrayStore(state)?.get(part.name) !== void 0));
46855
- const prefixOwned = word.parts.some((part) => part.kind === "variable" && part.prefixNames === "@");
47053
+ const prefixOwned = word.parts.some((part) => part.kind === "variable" && (part.prefixNames === "@" || part.transform && part.name === "@"));
46856
47054
  const owner = arrayOwned ? requireArrays(state).owner : void 0;
46857
47055
  const holding = owner?.hold();
46858
47056
  const scratch = !owner && split4 && state.variables.IFS !== "" && word.parts.some((part) => !part.quoted && part.kind !== "text") ? this.budget.values.scope() : void 0;
@@ -46982,19 +47180,25 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
46982
47180
  emptyNameGroups ??= /* @__PURE__ */ new Set();
46983
47181
  emptyNameGroups.add(quoteGroup);
46984
47182
  }
46985
- } else if (part.kind === "variable" && selector?.kind === "members" && !part.length && split4 && (!part.quoted || selector.separator === "@")) {
46986
- const members = await this.arrayMembers(part.name, state);
47183
+ } else if (part.kind === "variable" && split4 && (selector?.kind === "members" && !part.length && (!part.quoted || selector.separator === "@") || part.transform && part.name === "@")) {
47184
+ const members = selector?.kind === "members" ? await this.arrayMembers(part.name, state) : this.positionalValues(state);
46987
47185
  for (let position = 0; position < members.length; position++) {
46988
47186
  if (position > 0) addField();
46989
- const value2 = members[position];
46990
- if (part.quoted || state.variables.IFS === "") append(value2, !part.quoted, part.quoted || value2.length > 0);
47187
+ const original = members[position];
47188
+ const value2 = part.transform ? await this.transformValue(original, part.transform, state, partIO) : original;
47189
+ if (part.quoted || state.variables.IFS === "") append(value2, !part.quoted, part.quoted || shellValueByteLength(value2) > 0);
46991
47190
  else await appendSplit(value2);
46992
47191
  }
47192
+ if (part.transform && members.length === 0 && quoteGroup) {
47193
+ io[valueScope]?.reserve(32, 0);
47194
+ emptyNameGroups ??= /* @__PURE__ */ new Set();
47195
+ emptyNameGroups.add(quoteGroup);
47196
+ }
46993
47197
  } else if (part.kind === "text" && !splitText) {
46994
47198
  let value2 = invokedValues.get(part) ?? part.byteValue ?? part.value;
46995
47199
  if (typeof value2 === "string" && index === 0 && !part.quoted && /^~(?:\/|$)/u.test(value2)) value2 = (state.variables.HOME ?? "~") + value2.slice(1);
46996
47200
  append(value2, !part.quoted, quotedPresence || shellValueByteLength(value2) > 0);
46997
- } else if (part.kind === "variable" && part.name === "@" && part.quoted && !part.operator && split4) {
47201
+ } else if (part.kind === "variable" && part.name === "@" && part.quoted && !part.operator && !part.transform && split4) {
46998
47202
  for (let position = 0; position < state.positional.length; position++) {
46999
47203
  if (position > 0) addField();
47000
47204
  append(stateMonitor(state)?.positionals.get(String(position), state.positional[position]) ?? state.positional[position], false, true);
@@ -49994,15 +50198,15 @@ function* entities2(text3) {
49994
50198
  const predefined = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
49995
50199
  if (Object.hasOwn(predefined, entity)) result2 += predefined[entity];
49996
50200
  else {
49997
- const hexadecimal = entity.startsWith("#x");
49998
- const digits = entity.slice(hexadecimal ? 2 : 1);
50201
+ const hexadecimal2 = entity.startsWith("#x");
50202
+ const digits = entity.slice(hexadecimal2 ? 2 : 1);
49999
50203
  if (!entity.startsWith("#") || !digits.length) invalid("undeclared entity");
50000
50204
  let point = 0;
50001
50205
  for (let index = 0; index < digits.length; index++) {
50002
50206
  const code = digits.charCodeAt(index);
50003
- const digit3 = code >= 48 && code <= 57 ? code - 48 : hexadecimal && code >= 65 && code <= 70 ? code - 55 : hexadecimal && code >= 97 && code <= 102 ? code - 87 : -1;
50207
+ const digit3 = code >= 48 && code <= 57 ? code - 48 : hexadecimal2 && code >= 65 && code <= 70 ? code - 55 : hexadecimal2 && code >= 97 && code <= 102 ? code - 87 : -1;
50004
50208
  if (digit3 < 0) invalid("undeclared entity");
50005
- point = point * (hexadecimal ? 16 : 10) + digit3;
50209
+ point = point * (hexadecimal2 ? 16 : 10) + digit3;
50006
50210
  if (point > 1114111) invalid("invalid character reference");
50007
50211
  if ((index + 1) % 512 === 0) yield 512;
50008
50212
  }