diff --git a/Makefile b/Makefile index 4c22bab4..11c5edaa 100644 --- a/Makefile +++ b/Makefile @@ -24,10 +24,10 @@ format: clang-format -i src/*.{c,h} test: - ./$(BUILD_DIR)/tjs tests/run.js tests/ + ./$(BUILD_DIR)/tjs run tests/run.js tests/ test-advanced: cd tests/advanced && npm install - ./$(BUILD_DIR)/tjs tests/run.js tests/advanced/ + ./$(BUILD_DIR)/tjs run tests/run.js tests/advanced/ .PHONY: all build debug install clean distclean format test test-advanced diff --git a/src/js/runMain.js b/src/js/runMain.js index 9a474deb..a56e1c91 100644 --- a/src/js/runMain.js +++ b/src/js/runMain.js @@ -13,14 +13,31 @@ const { } = tjs[Symbol.for('tjs.internal')]; const exeName = path.basename(tjs.args[0]); -const help = `Usage: ${exeName} [options] [file] +const help = `Usage: ${exeName} [options] [subcommand] Options: - -v, --version print version - -h, --help list options - -e, --eval EXPR evaluate EXPR - --memory-limit LIMIT set the memory limit - --stack-size STACKSIZE set max stack size`; + -v, --version + Print version information + + -h, --help + Print help + + --memory-limit LIMIT + Set the memory limit for the JavaScript runtime + + --stack-size STACKSIZE + Set the maximum JavaScript stack size + +Subcommands: + run + Run a JavaScript program + + eval + Evaluate a JavaScript expression`; + +const helpEval = `Usage: ${exeName} eval EXPRESSION`; + +const helpRun = `Usage: ${exeName} run FILE`; const options = getopts(tjs.args.slice(1), { alias: { @@ -56,18 +73,37 @@ if (options.help) { setMaxStackSize(parseNumberOption(stackSize, 'stack-size')); } - const [ filename ] = options._; + const [ command, ...subargv ] = options._; + + if (!command) { + if (isStdinTty()) { + runRepl(); + } else { + evalStdin(); + } + } else if (command === 'eval') { + const [ expr ] = subargv; + + if (!expr) { + console.log(helpEval); + tjs.exit(1); + } + + evalScript(expr); + } else if (command === 'run') { + const [ filename ] = subargv; + + if (!filename) { + console.log(helpRun); + tjs.exit(1); + } - if (options.eval) { - evalScript(options.eval); - } else if (filename) { // XXX: This looks weird. This file is being JS_Eval'd when we call `evalFile`, // which does another JS_Eval, and something get's messed up :-( globalThis.queueMicrotask(() => evalFile(filename)); - } else if (isStdinTty()) { - runRepl(); } else { - evalStdin(); + console.log(help); + tjs.exit(1); } } diff --git a/tests/run.js b/tests/run.js index b171fcba..6f924142 100644 --- a/tests/run.js +++ b/tests/run.js @@ -31,7 +31,7 @@ class Test { } run() { - const args = [ tjs.exepath, this._fileName ]; + const args = [ tjs.exepath, 'run', this._fileName ]; this._proc = tjs.spawn(args, { stdout: 'pipe', stderr: 'pipe' }); this._stdout = this._slurpStdio(this._proc.stdout); this._stderr = this._slurpStdio(this._proc.stderr); @@ -93,7 +93,7 @@ function printResult(result) { } (async function() { - const dir = await tjs.realpath(tjs.args[2] || import.meta.dirname); + const dir = await tjs.realpath(tjs.args[3] || import.meta.dirname); const dirIter = await tjs.readdir(dir); const tests = []; diff --git a/tests/test-abort-on-unhandled-rejection.js b/tests/test-abort-on-unhandled-rejection.js index 7580a058..711a1281 100644 --- a/tests/test-abort-on-unhandled-rejection.js +++ b/tests/test-abort-on-unhandled-rejection.js @@ -5,6 +5,7 @@ import { path } from '@tjs/std'; (async () => { const args = [ tjs.exepath, + 'run', path.join(import.meta.dirname, 'helpers', 'unhandled-rejection.js') ]; const proc = tjs.spawn(args, { stdout: 'ignore', stderr: 'pipe' }); diff --git a/tests/test-eval-as-module.js b/tests/test-eval-as-module.js index 2a59da59..9c34e372 100644 --- a/tests/test-eval-as-module.js +++ b/tests/test-eval-as-module.js @@ -5,6 +5,7 @@ import { path } from '@tjs/std'; (async () => { const args = [ tjs.exepath, + 'run', path.join(import.meta.dirname, 'helpers', 'log-import-meta.js') ]; const proc = tjs.spawn(args); diff --git a/tests/test-mem-limit.js b/tests/test-mem-limit.js index fe18bb84..30700190 100644 --- a/tests/test-mem-limit.js +++ b/tests/test-mem-limit.js @@ -5,7 +5,7 @@ import assert from './assert.js'; tjs.exepath, '--memory-limit', '10485760', - '-e', + 'eval', 'new Uint8Array(104857600)' ]; const proc = tjs.spawn(args, { stdout: 'ignore', stderr: 'pipe' }); diff --git a/tests/test-wasm-wasi.js b/tests/test-wasm-wasi.js index 30691d33..90b75917 100644 --- a/tests/test-wasm-wasi.js +++ b/tests/test-wasm-wasi.js @@ -5,6 +5,7 @@ import { path } from '@tjs/std'; (async () => { const args = [ tjs.exepath, + 'run', path.join(import.meta.dirname, 'wasi', 'launcher.js'), 'test.wasm' ]; diff --git a/tests/wasi/launcher.js b/tests/wasi/launcher.js index b883d135..65f91420 100644 --- a/tests/wasi/launcher.js +++ b/tests/wasi/launcher.js @@ -2,8 +2,8 @@ import { path } from '@tjs/std'; (async () => { - const script = tjs.args[2]; - const args = tjs.args.slice(3); + const script = tjs.args[3]; + const args = tjs.args.slice(4); const bytes = await tjs.readFile(path.join(import.meta.dirname,script)); const module = new WebAssembly.Module(bytes); const wasi = new WebAssembly.WASI({ args });