Updates
This commit is contained in:
@@ -740,6 +740,17 @@ export function tokenize(line) {
|
||||
i++
|
||||
let inner = ''
|
||||
while (i < line.length && line[i] !== '"') {
|
||||
if (line[i] === '$' && line[i + 1] === '(' && line[i + 2] === '(') {
|
||||
const close = findArithmeticClose(line, i + 3)
|
||||
if (close < 0) {
|
||||
inner += line.slice(i)
|
||||
i = line.length
|
||||
break
|
||||
}
|
||||
inner += line.slice(i, close + 2)
|
||||
i = close + 2
|
||||
continue
|
||||
}
|
||||
if (line[i] === '\\' && i + 1 < line.length) {
|
||||
i++
|
||||
inner += line[i++]
|
||||
@@ -751,6 +762,17 @@ export function tokenize(line) {
|
||||
parts.push({ q: 'd', t: inner })
|
||||
continue
|
||||
}
|
||||
if (ch === '$' && line[i + 1] === '(' && line[i + 2] === '(') {
|
||||
const close = findArithmeticClose(line, i + 3)
|
||||
if (close < 0) {
|
||||
cur.t += line.slice(i)
|
||||
i = line.length
|
||||
break
|
||||
}
|
||||
cur.t += line.slice(i, close + 2)
|
||||
i = close + 2
|
||||
continue
|
||||
}
|
||||
if (
|
||||
/\s/.test(ch) ||
|
||||
ch === '|' ||
|
||||
|
||||
@@ -3012,6 +3012,15 @@ test('tokenize records quote parts for glob (literal * in quotes)', async (t) =>
|
||||
t.is(lit.parts[0].t, '*')
|
||||
})
|
||||
|
||||
test('tokenize keeps arithmetic expansion in one word token', async (t) => {
|
||||
const toks = tokenize('n=$((n+1)); echo "$((n+2))"')
|
||||
const words = toks.filter((x) => x.type === 'word').map((x) => x.value)
|
||||
t.ok(words.includes('n=$((n+1))'))
|
||||
t.ok(words.includes('$((n+2))'))
|
||||
t.is(toks.filter((x) => x.type === 'op' && x.value === '(').length, 0)
|
||||
t.is(toks.filter((x) => x.type === 'op' && x.value === ')').length, 0)
|
||||
})
|
||||
|
||||
test('execShellLine pathname glob and noglob', async (t) => {
|
||||
const dir = testCorestoreDir('shglob')
|
||||
const store = new Corestore(dir)
|
||||
@@ -4499,6 +4508,10 @@ async function run(ctx) {
|
||||
lines.length = 0
|
||||
await execShellLine(ctx, 'if false; then echo x; fi')
|
||||
t.ok(!lines.some((l) => l.includes('x')))
|
||||
ctx.exitCode = 0
|
||||
await execShellLine(ctx, 'n=0; if true; then n=$((n+1)); fi; echo $n')
|
||||
t.is(ctx.exitCode, 0)
|
||||
t.ok(lines.some((l) => l.includes('1')))
|
||||
await store.close()
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
})
|
||||
@@ -6323,6 +6336,16 @@ test('tier-1 sh -c executes command and sets positional args', async (t) => {
|
||||
await runBinCommand(ctx, ['sh', '-c', 'false'])
|
||||
t.is(ctx.exitCode, 1)
|
||||
|
||||
lines.length = 0
|
||||
ctx.exitCode = 0
|
||||
await runBinCommand(ctx, [
|
||||
'sh',
|
||||
'-c',
|
||||
'n=0; if true; then n=$((n+1)); fi; echo $n'
|
||||
])
|
||||
t.is(ctx.exitCode, 0)
|
||||
t.ok(lines.includes('1'))
|
||||
|
||||
await store.close()
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
@@ -95,6 +95,15 @@ test('run_command wraps compound shell with sh -c before capture redirection', a
|
||||
t.ok(seen[0].startsWith("sh -c 'for x in a b; do if true; then echo $x; fi; done'"))
|
||||
})
|
||||
|
||||
test('run_command wraps combined if + arithmetic expansion probe', async (t) => {
|
||||
const { ctx, seen } = makeCtx()
|
||||
const probe = 'n=0; if true; then n=$((n+1)); fi; echo $n'
|
||||
const out = await callRunCommand(ctx, probe)
|
||||
t.ok(out.ok)
|
||||
t.ok(seen.length >= 1)
|
||||
t.ok(seen[0].startsWith(`sh -c '${probe}'`))
|
||||
})
|
||||
|
||||
test('run_command keeps simple command direct with capture redirection', async (t) => {
|
||||
const { ctx, seen } = makeCtx()
|
||||
const out = await callRunCommand(ctx, 'echo hi')
|
||||
|
||||
Reference in New Issue
Block a user