refactor: simplify pass (trekexecute)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
63fd33daaf
commit
cc277c476c
2 changed files with 15 additions and 12 deletions
|
|
@ -365,13 +365,13 @@ function blockArgs(unquoted, unreadable) {
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The quote state at `to` of `text` read from `from` for quotes only: 'none'
|
// The quote state at `to` of `text` read from its start for quotes only: 'none'
|
||||||
// (outside every quote), 'open' (inside '...' or "...", or inside an earlier
|
// (outside every quote), 'open' (inside '...' or "...", or inside an earlier
|
||||||
// heredoc's body) or 'unknown' (the scan cannot follow the shell here).
|
// heredoc's body) or 'unknown' (the scan cannot follow the shell here).
|
||||||
// `state`, when given, lets the calls on one text resume where the last stopped.
|
// `state` lets the calls on one text resume where the last stopped; a call
|
||||||
function argsQuoteScan(text, from, to, openers, state) {
|
// before that point starts over from the start of the text.
|
||||||
const fresh = (pos) => ({ pos, mode: 'none', pending: null, bodyEnd: -1 });
|
function argsQuoteScan(text, to, openers, state) {
|
||||||
const st = state ? (state.pos <= to ? state : fresh(0)) : fresh(from);
|
const st = state.pos <= to ? state : { pos: 0, mode: 'none', pending: null, bodyEnd: -1 };
|
||||||
let p = st.pos;
|
let p = st.pos;
|
||||||
let mode = st.mode;
|
let mode = st.mode;
|
||||||
let pending = st.pending;
|
let pending = st.pending;
|
||||||
|
|
@ -418,7 +418,6 @@ function argsQuoteScan(text, from, to, openers, state) {
|
||||||
if (c === '\\') {
|
if (c === '\\') {
|
||||||
// The scan never decides a backslash without the character it escapes.
|
// The scan never decides a backslash without the character it escapes.
|
||||||
if (p + 1 >= to) return unknown();
|
if (p + 1 >= to) return unknown();
|
||||||
if (mode === 'double' && d === '\n') return unknown();
|
|
||||||
if (d === '\n') return unknown(); // scan: a continuation cannot be followed
|
if (d === '\n') return unknown(); // scan: a continuation cannot be followed
|
||||||
p += 2;
|
p += 2;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -495,7 +494,7 @@ function argsEscapedLt(text, i, lim, openers) {
|
||||||
let b = 0;
|
let b = 0;
|
||||||
while (i - 1 - b >= 0 && text[i - 1 - b] === '\\') b += 1;
|
while (i - 1 - b >= 0 && text[i - 1 - b] === '\\') b += 1;
|
||||||
const s = i - b;
|
const s = i - b;
|
||||||
return b % 2 === 1 && argsQuoteScan(text, 0, s, openers, lim.state) === 'none';
|
return b % 2 === 1 && argsQuoteScan(text, s, openers, lim.state) === 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
// An opener whose raw span holds a backslash-newline. The regex reading cannot
|
// An opener whose raw span holds a backslash-newline. The regex reading cannot
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import { dirname, join } from 'node:path';
|
||||||
import { fileURLToPath, pathToFileURL } from 'node:url';
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
||||||
import { runHook, runHookWithEnv } from '../helpers/hook-helper.mjs';
|
import { runHook, runHookWithEnv } from '../helpers/hook-helper.mjs';
|
||||||
import { tmp, pluginCopy } from './guard-helpers.mjs';
|
import { tmp, pluginCopy } from './guard-helpers.mjs';
|
||||||
|
import { fastestWithin } from '../helpers/timing.mjs';
|
||||||
|
|
||||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||||
const ROOT = join(HERE, '..', '..');
|
const ROOT = join(HERE, '..', '..');
|
||||||
|
|
@ -305,9 +306,12 @@ test('part-A scan: a long command with many escaped < is read in linear time', a
|
||||||
// scan resumes where its last call stopped, so the text is read once.
|
// scan resumes where its last call stopped, so the text is read once.
|
||||||
const many = ('\\<' + 'x'.repeat(40) + ' ').repeat(20000);
|
const many = ('\\<' + 'x'.repeat(40) + ' ').repeat(20000);
|
||||||
const command = `echo ${many}<<'${D}'\nbrief.md\n${D}`;
|
const command = `echo ${many}<<'${D}'\nbrief.md\n${D}`;
|
||||||
const started = Date.now();
|
let last = { code: null, stderr: '' };
|
||||||
const { code, stderr } = await runHook(PRE_BASH, bashInput(command));
|
const timing = await fastestWithin(15000, async () => {
|
||||||
const elapsed = Date.now() - started;
|
const started = Date.now();
|
||||||
assert.strictEqual(code, 0, `the guard did not pass the long command (exit ${code}): ${stderr.slice(0, 300)}`);
|
last = await runHook(PRE_BASH, bashInput(command));
|
||||||
assert.ok(elapsed < 15000, `the guard took ${elapsed} ms on ${command.length} characters (limit 15000 ms)`);
|
return Date.now() - started;
|
||||||
|
});
|
||||||
|
assert.strictEqual(last.code, 0, `the guard did not pass the long command (exit ${last.code}): ${last.stderr.slice(0, 300)}`);
|
||||||
|
assert.ok(timing.ok, `the guard took ${timing.fastest} ms at best (runs ${timing.runs.join(', ')}) on ${command.length} characters (limit 15000 ms)`);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue