@sjawhar/pi-legion-envoy 5.16.6 → 5.16.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/legion.js +157 -28
  2. package/package.json +1 -1
package/dist/legion.js CHANGED
@@ -33415,7 +33415,7 @@ import { logger } from "@oh-my-pi/pi-utils";
33415
33415
  // package.json
33416
33416
  var package_default = {
33417
33417
  name: "@sjawhar/pi-legion-envoy",
33418
- version: "5.16.6",
33418
+ version: "5.16.7",
33419
33419
  type: "module",
33420
33420
  omp: {
33421
33421
  extensions: [
@@ -41227,6 +41227,15 @@ function scanIpythonShell(source, sinks) {
41227
41227
  }
41228
41228
 
41229
41229
  // src/legion/pane-guard.ts
41230
+ var definitions = new WeakMap;
41231
+ function trapSignal(operand) {
41232
+ const name = operand.toUpperCase();
41233
+ if (name === "0")
41234
+ return "EXIT";
41235
+ return name.startsWith("SIG") && name !== "SIGEXIT" ? name.slice(3) : name;
41236
+ }
41237
+ var UNREADABLE_CONDITION = "an unreadable condition";
41238
+
41230
41239
  class Refusal extends Error {
41231
41240
  snippet;
41232
41241
  line;
@@ -41252,7 +41261,7 @@ function wrapRefusal(error48, site, label) {
41252
41261
  throw new Refusal(site.snippet, site.line, `line ${error48.line} of ${source}, \`${error48.snippet}\`: ${error48.detail}`);
41253
41262
  }
41254
41263
  var MAX_DEPTH = 8;
41255
- var MAX_WALK_STEPS = 1e4;
41264
+ var MAX_WALK_STEPS = 1e5;
41256
41265
  var MAX_ALTERNATIVES = 64;
41257
41266
  var MAX_SCRIPT_BYTES = 1024 * 1024;
41258
41267
  var FRESH_TEMP_NAME = "tmp.XXXXXXXXXX";
@@ -41570,12 +41579,22 @@ function substitution(script, text, st, ctx) {
41570
41579
  }
41571
41580
  const only = script?.commands.length === 1 ? script.commands[0]?.command : undefined;
41572
41581
  const invocation = substitutionInvocation(only, st, ctx);
41573
- const definition = invocation === undefined ? undefined : st.functions.get(invocation.base);
41574
- if (definition !== undefined && invocation !== undefined) {
41575
- const output = functionOutput(invocation.base, definition, invocation.rest, st, ctx);
41576
- if (output !== undefined)
41577
- return output.map((value) => [...value]);
41582
+ const callee = invocation === undefined ? undefined : st.functions.get(invocation.base);
41583
+ if (callee !== undefined && invocation !== undefined) {
41584
+ const alternatives = [];
41585
+ let external2 = false;
41586
+ for (const definition of callee) {
41587
+ const output = definition === undefined ? undefined : functionOutput(invocation.base, definition, invocation.rest, st, ctx);
41588
+ if (output !== undefined)
41589
+ alternatives.push(...output.map((value) => [...value]));
41590
+ else
41591
+ external2 = true;
41592
+ }
41593
+ return external2 ? [...alternatives, ...commandOutput(only, invocation, text, st, ctx)] : alternatives;
41578
41594
  }
41595
+ return commandOutput(only, invocation, text, st, ctx);
41596
+ }
41597
+ function commandOutput(only, invocation, text, st, ctx) {
41579
41598
  if (invocation !== undefined) {
41580
41599
  if (invocation.base === "pwd" && invocation.rest.length === 0 && st.cwd !== undefined) {
41581
41600
  return [[literal2(st.cwd)]];
@@ -41813,7 +41832,7 @@ function walkSubstitution(script, inner, text, st, ctx) {
41813
41832
  throw new Refusal(text, 1, `the guard could not read the command in \`${text}\``);
41814
41833
  }
41815
41834
  const source = parsed.source ?? (script === undefined ? inner ?? "" : st.source);
41816
- walkScript(parsed, { ...clone2(st), source }, ctx);
41835
+ walkScript(parsed, subshell(st, { source }), ctx);
41817
41836
  }
41818
41837
  function clone2(st) {
41819
41838
  return {
@@ -41856,6 +41875,8 @@ function merge2(target, branches) {
41856
41875
  target.arrays.set(name, new Map([[UNKNOWN_ARRAY_INDEX, unknownElement]]));
41857
41876
  }
41858
41877
  }
41878
+ const positionals = branches.map((branch) => JSON.stringify(branch.positional ?? null));
41879
+ target.positional = positionals.every((value) => value === positionals[0]) ? branches[0]?.positional : undefined;
41859
41880
  const cwds = new Set(branches.map((branch) => branch.cwd));
41860
41881
  if (cwds.size > 1) {
41861
41882
  target.cwd = undefined;
@@ -41869,6 +41890,46 @@ function merge2(target, branches) {
41869
41890
  target.exported.add(name);
41870
41891
  target.backgroundStarted ||= branch.backgroundStarted;
41871
41892
  }
41893
+ const functionNames = new Set;
41894
+ for (const branch of branches)
41895
+ for (const name of branch.functions.keys())
41896
+ functionNames.add(name);
41897
+ const functions = new Map;
41898
+ for (const name of functionNames) {
41899
+ const callees = branches.map((branch) => branch.functions.get(name));
41900
+ const first = callees[0];
41901
+ if (first !== undefined && callees.every((callee) => callee === first)) {
41902
+ functions.set(name, first);
41903
+ continue;
41904
+ }
41905
+ const candidates = new Set;
41906
+ for (const callee of callees)
41907
+ for (const definition of callee ?? [undefined])
41908
+ candidates.add(definition);
41909
+ functions.set(name, [...candidates]);
41910
+ }
41911
+ target.functions = functions;
41912
+ const lifted = [];
41913
+ let merged;
41914
+ for (const branch of branches) {
41915
+ for (const trap of branch.traps) {
41916
+ if (target.traps.includes(trap))
41917
+ continue;
41918
+ merged ??= new Map(target.vars);
41919
+ lifted.push({ ...trap, vars: handlerVars(trap, branch.vars), merged });
41920
+ }
41921
+ }
41922
+ target.traps = [...target.traps, ...lifted];
41923
+ }
41924
+ function handlerVars(trap, vars) {
41925
+ const { vars: branch, merged } = trap;
41926
+ if (branch === undefined || merged === undefined)
41927
+ return vars;
41928
+ const out = new Map(vars);
41929
+ for (const [name, value] of branch)
41930
+ if (vars.get(name) === merged.get(name))
41931
+ out.set(name, value);
41932
+ return out;
41872
41933
  }
41873
41934
  function lineOf(source, pos) {
41874
41935
  let line = 1;
@@ -41894,13 +41955,19 @@ function walkScript(script, st, ctx, runTraps = true) {
41894
41955
  }
41895
41956
  for (const statement of script.commands)
41896
41957
  walkNode(statement, st, ctx, false);
41897
- if (!runTraps)
41898
- return;
41958
+ if (runTraps)
41959
+ runSetTraps(st, ctx);
41960
+ }
41961
+ function subshell(st, patch) {
41962
+ return { ...clone2(st), traps: [], ...patch };
41963
+ }
41964
+ function runSetTraps(st, ctx) {
41899
41965
  for (const trap of st.traps) {
41966
+ const vars = new Map([...handlerVars(trap, st.vars), ...trap.pids ?? []]);
41900
41967
  try {
41901
- runText(trap.text, "the EXIT trap", { ...clone2(st), source: trap.file, traps: [] }, ctx, trap.site);
41902
- } catch (error49) {
41903
- locateRefusal(error49, trap.file);
41968
+ runText(trap.text, "the EXIT trap", subshell(st, { source: trap.file, vars }), ctx, trap.site);
41969
+ } catch (error48) {
41970
+ locateRefusal(error48, trap.file);
41904
41971
  }
41905
41972
  }
41906
41973
  }
@@ -41919,20 +41986,34 @@ function walkNode(node, st, ctx, pipeIn) {
41919
41986
  switch (node.type) {
41920
41987
  case "Statement": {
41921
41988
  checkRedirects(node.redirects, undefined, siteOf(node, st), st, ctx);
41922
- walkNode(node.command, st, ctx, pipeIn);
41923
- if (node.background)
41989
+ if (node.background) {
41990
+ const before = st.output;
41991
+ const child = subshell(st);
41992
+ walkNode(node.command, child, ctx, pipeIn);
41993
+ runSetTraps(child, ctx);
41994
+ if (outputChanged(before, child.output))
41995
+ st.output = undefined;
41924
41996
  st.backgroundStarted = true;
41997
+ return;
41998
+ }
41999
+ walkNode(node.command, st, ctx, pipeIn);
41925
42000
  return;
41926
42001
  }
41927
42002
  case "Command":
41928
42003
  handleCommand(node, st, ctx, pipeIn);
41929
42004
  return;
41930
42005
  case "Pipeline": {
42006
+ if (node.commands.length === 1) {
42007
+ for (const command of node.commands)
42008
+ walkNode(command, st, ctx, pipeIn);
42009
+ return;
42010
+ }
41931
42011
  const before = st.output;
41932
42012
  const parts = [];
41933
42013
  for (const [index, command] of node.commands.entries()) {
41934
- const part = clone2(st);
42014
+ const part = subshell(st);
41935
42015
  walkNode(command, part, ctx, index > 0);
42016
+ runSetTraps(part, ctx);
41936
42017
  parts.push(part);
41937
42018
  }
41938
42019
  if (parts.some((part) => outputChanged(before, part.output)))
@@ -41951,8 +42032,9 @@ function walkNode(node, st, ctx, pipeIn) {
41951
42032
  return;
41952
42033
  case "Subshell": {
41953
42034
  const before = st.output;
41954
- const child = clone2(st);
42035
+ const child = subshell(st);
41955
42036
  walkList(node.body.commands, child, ctx);
42037
+ runSetTraps(child, ctx);
41956
42038
  if (outputChanged(before, child.output))
41957
42039
  st.output = undefined;
41958
42040
  return;
@@ -42041,14 +42123,21 @@ function walkNode(node, st, ctx, pipeIn) {
42041
42123
  st.output = undefined;
42042
42124
  return;
42043
42125
  }
42044
- case "Function":
42045
- st.functions.set(node.name.value, { body: node.body, source: st.source, file: st.script });
42126
+ case "Function": {
42127
+ let callee = definitions.get(node);
42128
+ if (callee === undefined) {
42129
+ callee = [{ body: node.body, source: st.source, file: st.script }];
42130
+ definitions.set(node, callee);
42131
+ }
42132
+ st.functions.set(node.name.value, callee);
42046
42133
  checkRedirects(node.redirects, undefined, siteOf(node, st), st, ctx);
42047
42134
  return;
42135
+ }
42048
42136
  case "Coproc": {
42049
42137
  const before = st.output;
42050
- const child = clone2(st);
42138
+ const child = subshell(st);
42051
42139
  walkNode(node.body, child, ctx, false);
42140
+ runSetTraps(child, ctx);
42052
42141
  if (outputChanged(before, child.output))
42053
42142
  st.output = undefined;
42054
42143
  checkRedirects(node.redirects, undefined, siteOf(node, st), st, ctx);
@@ -42359,9 +42448,24 @@ function dispatch(invocation, outer, ctx) {
42359
42448
  const base = path4.basename(name);
42360
42449
  const rest = argv.slice(1);
42361
42450
  const site = invocation.site;
42362
- const functionDefinition = outer.functions.get(base);
42363
- if (functionDefinition !== undefined) {
42364
- runFunction(base, functionDefinition, rest, outer, ctx);
42451
+ const callee = outer.functions.get(base);
42452
+ if (callee !== undefined) {
42453
+ const [only] = callee;
42454
+ if (callee.length === 1 && only !== undefined) {
42455
+ runFunction(base, only, rest, outer, ctx);
42456
+ return;
42457
+ }
42458
+ const runs = callee.map((definition) => {
42459
+ const run = clone2(outer);
42460
+ if (definition !== undefined)
42461
+ runFunction(base, definition, rest, run, ctx);
42462
+ else {
42463
+ run.functions.delete(base);
42464
+ dispatch(invocation, run, ctx);
42465
+ }
42466
+ return run;
42467
+ });
42468
+ merge2(outer, runs);
42365
42469
  return;
42366
42470
  }
42367
42471
  const stdoutRedirected = invocation.redirects.some((redirect) => (redirect.fileDescriptor === undefined || redirect.fileDescriptor === 1) && [">", ">>", ">|", "&>", "&>>", ">&"].includes(redirect.operator));
@@ -42453,11 +42557,34 @@ function dispatch(invocation, outer, ctx) {
42453
42557
  return;
42454
42558
  }
42455
42559
  case "trap": {
42456
- const text = literalText(operands(rest, "").operands[0]?.exp);
42560
+ const [handler, ...conditions] = operands(rest, "").operands;
42561
+ if (handler === undefined)
42562
+ return;
42563
+ const text = literalText(handler.exp);
42564
+ const readable = conditions.map((arg) => literalText(arg.exp));
42565
+ const signals = readable.map((condition) => condition === undefined ? UNREADABLE_CONDITION : trapSignal(condition));
42566
+ const handled = signals.length === 0 ? ["EXIT"] : signals;
42567
+ const file2 = outer.script ?? outer.source;
42457
42568
  if (text === "-") {
42458
- outer.traps = [];
42459
- } else if (text !== undefined && !text.startsWith("-")) {
42460
- outer.traps = [...outer.traps, { text, site, file: outer.script ?? outer.source }];
42569
+ const named = readable.flatMap((condition) => condition === undefined ? [] : [trapSignal(condition)]);
42570
+ outer.traps = outer.traps.flatMap((trap) => {
42571
+ const signals2 = trap.signals.filter((signal) => !named.includes(signal));
42572
+ return signals2.length === 0 ? [] : [{ ...trap, signals: signals2 }];
42573
+ });
42574
+ } else if (text === undefined && handler.exp.every((piece) => piece.kind === "literal" || piece.descendantPid)) {
42575
+ const pids = new Map;
42576
+ const handlerText = handler.exp.map((piece) => {
42577
+ if (piece.kind === "literal")
42578
+ return piece.text;
42579
+ const name2 = `__legion_guard_trap_pid_${pids.size}`;
42580
+ pids.set(name2, [piece]);
42581
+ return `\${${name2}}`;
42582
+ }).join("");
42583
+ outer.traps = [...outer.traps, { text: handlerText, site, signals: handled, file: file2, pids }];
42584
+ } else if (text === undefined) {
42585
+ throw new Refusal(site.snippet, site.line, `the guard cannot read the handler this \`trap\` sets, \`${handler.text}\` (${handler.exp.find((piece) => piece.kind !== "literal")?.why ?? "a value the guard cannot know"}), so it cannot check what runs when this shell exits; write the handler out, or put it in a function`);
42586
+ } else if (!text.startsWith("-")) {
42587
+ outer.traps = [...outer.traps, { text, site, signals: handled, file: file2 }];
42461
42588
  }
42462
42589
  return;
42463
42590
  }
@@ -43139,9 +43266,11 @@ function runFile(file2, positional, st, ctx, site, kind, source = false) {
43139
43266
  throw new Refusal(site.snippet, site.line, "the guard stops following scripts this deep; run the inner script directly");
43140
43267
  }
43141
43268
  const child = { ...clone2(st), source: content, script: abs, depth: st.depth + 1 };
43142
- child.positional = positional.map((arg) => arg.exp);
43269
+ const operands2 = positional.map((arg) => arg.exp);
43270
+ child.positional = source && operands2.length === 0 ? st.positional : operands2;
43143
43271
  walkScript(parse5(content), child, ctx, !source);
43144
43272
  if (source) {
43273
+ st.positional = operands2.length === 0 ? child.positional : child.positional === operands2 ? st.positional : undefined;
43145
43274
  st.vars = child.vars;
43146
43275
  st.exported = child.exported;
43147
43276
  st.arrays.clear();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "5.16.6",
3
+ "version": "5.16.7",
4
4
  "type": "module",
5
5
  "omp": {
6
6
  "extensions": [