From c8e4eafa573fa1252b76995c59972dddb0a3034e Mon Sep 17 00:00:00 2001 From: theMackabu Date: Thu, 9 Apr 2026 12:23:36 -0700 Subject: [PATCH] clean up dead code in promise path --- .github/agents/route_validation.js | 6 +- AGENTS.md | 7 +- docs/repo/testing.md | 4 + examples/jit/run.js | 164 +++++++++++++++++++++++++++++ include/sugar.h | 3 +- package.json | 3 +- src/ant.c | 20 +--- src/silver/ops/async.h | 10 +- 8 files changed, 187 insertions(+), 30 deletions(-) create mode 100644 examples/jit/run.js diff --git a/.github/agents/route_validation.js b/.github/agents/route_validation.js index 7c126971..126877a7 100644 --- a/.github/agents/route_validation.js +++ b/.github/agents/route_validation.js @@ -121,7 +121,11 @@ function main() { filePath === 'src/shapes.c' ) { addRecommendation(recommendations, 'meson compile -C build', 'runtime or engine core changed'); - addRecommendation(recommendations, './build/ant examples/spec/run.js', 'engine-level behavior can affect broad language semantics'); + addRecommendation( + recommendations, + './build/ant examples/spec/run.js ', + 'engine-level behavior can affect broad language semantics' + ); } if ( diff --git a/AGENTS.md b/AGENTS.md index 1fa7e8f8..7ea1d967 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,7 +22,7 @@ entire repository into context. - Build from an existing configured tree: `meson compile -C build` - Fresh local setup: `maid setup` - Run a focused test file: `./build/ant tests/test_.cjs` -- Run the spec suite: `./build/ant examples/spec/run.js` +- Run the spec suite: `./build/ant examples/spec/run.js --all` - Run the individual harness steps when needed: `maid validate_changes`, `maid structure`, `maid knowledge` @@ -56,6 +56,11 @@ guidance. - When touching build or runtime invariants, document the reasoning in [docs/exec-plans/index.md](docs/exec-plans/index.md) or a linked plan if the work spans multiple steps. +- Builds and broad validation runs (for example `maid build` or + spec runs with `--all`) may need broader system access; pause and get + explicit user approval before proceeding when sandbox escalation is required. +- Check [docs/repo/testing.md](docs/repo/testing.md) before choosing validation + scope or retrying a failing broad test command. - Before finalizing most code changes, run `maid preflight` and then execute any additional build or spec commands it recommends, or explain why they were not run. diff --git a/docs/repo/testing.md b/docs/repo/testing.md index 945fcc75..50b820c8 100644 --- a/docs/repo/testing.md +++ b/docs/repo/testing.md @@ -41,6 +41,10 @@ This guide keeps validation proportional to the change while still protecting ru - Keep new tests close to the behavior they protect so future agent runs can discover the expected pattern quickly. +- In sandboxed agent sessions, builds and broad validation commands such as + `maid build`, or `./build/ant examples/spec/run.js --all` may need broader system access. + Pause and get explicit user approval before retrying them with sandbox + escalation. - In sandboxed agent sessions, `./build/ant examples/spec/run.js --all` can fail in the `fetch` spec because outbound network access is blocked. Treat that as an expected sandbox limitation, and prefer targeted spec files when the diff --git a/examples/jit/run.js b/examples/jit/run.js new file mode 100644 index 00000000..58437a15 --- /dev/null +++ b/examples/jit/run.js @@ -0,0 +1,164 @@ +import fs from 'ant:fs'; +import path from 'ant:path'; +import { spawnSync } from 'child_process'; + +const GREEN = '\x1b[32m'; +const RED = '\x1b[31m'; +const CYAN = '\x1b[36m'; +const BOLD = '\x1b[1m'; +const DIM = '\x1b[2m'; +const RESET = '\x1b[0m'; + +const jitDir = path.dirname(import.meta.url.replace('file://', '')); +const repoRoot = path.resolve(jitDir, '..', '..'); +const antBinary = path.join(repoRoot, 'build', 'ant'); +const helperFiles = new Set(['run.js']); + +const allFiles = fs + .readdirSync(jitDir) + .filter(file => file.endsWith('.js') && !helperFiles.has(file)) + .sort(); + +const cliArgs = process.argv.slice(2); +const runAll = cliArgs.length === 0 || cliArgs.includes('--all'); +const requestedFiles = cliArgs.filter(arg => arg !== '--all'); + +function normalizeFileName(arg) { + const base = path.basename(arg); + return base.endsWith('.js') ? base.slice(0, -3) : base; +} + +const fileByName = new Map(allFiles.map(file => [path.basename(file, '.js'), file])); +const files = (() => { + if (runAll) return allFiles; + + const selected = []; + const seen = new Set(); + const missing = []; + + for (const raw of requestedFiles) { + const name = normalizeFileName(raw); + const file = fileByName.get(name); + + if (!file) { + missing.push(raw); + continue; + } + + if (seen.has(file)) continue; + seen.add(file); + selected.push(file); + } + + if (missing.length > 0) { + console.log(`${RED}Unknown JIT file(s):${RESET} ${missing.join(', ')}`); + } + if (selected.length === 0) process.exit(1); + + return selected; +})(); + +function collectFailureReasons(output, result) { + const reasons = []; + const exitCode = result.status ?? result.exitCode; + const signalCode = result.signal ?? result.signalCode; + + if (exitCode !== 0) reasons.push(`exit code ${exitCode}`); + if (signalCode !== null && signalCode !== undefined) reasons.push(`signal ${signalCode}`); + if (/^FAIL\b/m.test(output)) reasons.push('reported FAIL lines'); + if (/\bok:\s*false\b/.test(output)) reasons.push('reported ok: false'); + if (/\bok=false\b/.test(output)) reasons.push('reported ok=false'); + if (/\bresults match:\s*false\b/.test(output)) reasons.push('reported results match: false'); + if (/\ball [^\n]* passed:\s*false\b/i.test(output)) reasons.push('reported final all-passed check as false'); + + const failedMatches = [...output.matchAll(/\bfailed:\s*(\d+)\b/gi)]; + for (const match of failedMatches) { + if (Number(match[1]) > 0) { + reasons.push(`reported failed count ${match[1]}`); + break; + } + } + + return reasons; +} + +function printCaptured(stream, output) { + if (!output) return; + stream.write(output); + if (!output.endsWith('\n')) stream.write('\n'); +} + +let filesPassed = 0; +let filesFailed = 0; +const fileTimes = []; +const failures = []; + +console.log(`\n${BOLD}${CYAN}Running ${files.length} JIT files...${RESET}\n`); +const totalStart = performance.now(); + +for (const file of files) { + const relativeFile = path.join('examples', 'jit', file); + const start = performance.now(); + + console.log(`=== Running ${relativeFile} ===`); + + let result; + try { + result = spawnSync(antBinary, [relativeFile], { cwd: repoRoot }); + } catch (error) { + const elapsed = performance.now() - start; + const message = error && error.stack ? String(error.stack) : String(error); + + console.log(`${RED}✗${RESET} ${path.basename(file, '.js')} ${DIM}(spawn error, ${elapsed.toFixed(0)}ms)${RESET}`); + console.log(message); + console.log(); + + filesFailed++; + fileTimes.push({ name: path.basename(file, '.js'), elapsed }); + failures.push({ name: path.basename(file, '.js'), reasons: ['spawn error'] }); + continue; + } + + printCaptured(process.stdout, result.stdout); + printCaptured(process.stderr, result.stderr); + + const elapsed = performance.now() - start; + const name = path.basename(file, '.js'); + const output = `${result.stdout || ''}\n${result.stderr || ''}`; + const reasons = collectFailureReasons(output, result); + + if (reasons.length === 0) { + console.log(`${GREEN}✓${RESET} ${name} ${DIM}(${elapsed.toFixed(0)}ms)${RESET}`); + filesPassed++; + } else { + console.log(`${RED}✗${RESET} ${name} ${DIM}(${elapsed.toFixed(0)}ms)${RESET}`); + console.log(`${DIM} ${reasons.join('; ')}${RESET}`); + filesFailed++; + failures.push({ name, reasons }); + } + + console.log(); + fileTimes.push({ name, elapsed }); +} + +const totalElapsed = performance.now() - totalStart; + +console.log(`${BOLD}Results:${RESET}`); +console.log(` ${GREEN}${filesPassed} files passed${RESET}`); +console.log(` ${RED}${filesFailed} files failed${RESET}`); + +console.log(`\n${BOLD}Timing:${RESET}`); +for (const { name, elapsed } of fileTimes) { + console.log(` ${DIM}${name.padEnd(30)}${RESET} ${elapsed.toFixed(0)}ms`); +} +console.log(`\n ${BOLD}Total${RESET}${' '.padEnd(26)}${totalElapsed.toFixed(0)}ms\n`); + +if (failures.length > 0) { + console.log(`${BOLD}${RED}Failed Files:${RESET}`); + for (const { name, reasons } of failures) { + console.log(` ${name}: ${reasons.join('; ')}`); + } + console.log(); +} + +process.exit(filesFailed > 0 ? 1 : 0); diff --git a/include/sugar.h b/include/sugar.h index 00e9387b..42f842f5 100644 --- a/include/sugar.h +++ b/include/sugar.h @@ -77,8 +77,7 @@ typedef struct { typedef enum { JS_AWAIT_PENDING = 0, - JS_AWAIT_FULFILLED, - JS_AWAIT_REJECTED, + JS_AWAIT_ERROR, } js_await_state_t; typedef struct { diff --git a/package.json b/package.json index a5e57de3..56442f90 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "ant", "type": "module", "scripts": { - "spec": "./build/ant examples/spec/run.js" + "spec": "./build/ant examples/spec/run.js", + "jit": "./build/ant examples/jit/run.js" }, "dependencies": {}, "devDependencies": {} diff --git a/src/ant.c b/src/ant.c index 3f69382a..20526c3a 100644 --- a/src/ant.c +++ b/src/ant.c @@ -10098,28 +10098,14 @@ js_await_result_t js_promise_await_coroutine(ant_t *js, ant_value_t promise, cor ant_promise_state_t *pd = get_promise_data(js, promise, false); if (!pd) { - result.state = JS_AWAIT_FULFILLED; + result.state = JS_AWAIT_ERROR; + result.value = js_mkerr(js, "invalid promise state"); return result; } - // if (pd->state == 1) { - // result.state = JS_AWAIT_FULFILLED; - // result.value = pd->value; - // return result; - // } - // - // if (pd->state == 2) { - // if (pd->unhandled_reported) js_fire_rejection_handled(js, promise, pd->value); - // pd->has_rejection_handler = true; - // pd->unhandled_reported = false; - // result.state = JS_AWAIT_REJECTED; - // result.value = pd->value; - // return result; - // } - promise_handler_t h = { js_mkundef(), js_mkundef(), js_mkundef(), coro }; if (!promise_handler_append(pd, &h)) { - result.state = JS_AWAIT_REJECTED; + result.state = JS_AWAIT_ERROR; result.value = js_mkerr(js, "out of memory"); return result; } diff --git a/src/silver/ops/async.h b/src/silver/ops/async.h index 4188141e..0f0fb669 100644 --- a/src/silver/ops/async.h +++ b/src/silver/ops/async.h @@ -518,14 +518,8 @@ static inline ant_value_t sv_await_value(ant_t *js, ant_value_t value) { coro->is_settled = false; coro->is_ready = false; js_await_result_t await_result = js_promise_await_coroutine(js, value, coro); - - if (await_result.state == JS_AWAIT_FULFILLED) { - coro->is_settled = false; - coro->awaited_promise = js_mkundef(); - return await_result.value; - } - - if (await_result.state == JS_AWAIT_REJECTED) { + + if (await_result.state == JS_AWAIT_ERROR) { coro->is_settled = false; coro->awaited_promise = js_mkundef(); return js_throw(js, await_result.value); -- knotmirror 0.0.1