A complete JavaScript engine and runtime environment for classic
Amiga computers. Built from scratch in C, targeting MC68000 and
AmigaOS 2.0+. Inspired by Node.js, adapted for the Amiga platform.
Features
--------
* JavaScript engine
(ES5.1 + ES6+ features)
- Arrow functions, classes with
inheritance, super(), static
- Class fields: public,
private (#field), static
- Template literals, tagged
- Destructuring, spread/rest,
default parameters
- for-of loops, labeled
break/continue
- Regex literal /pattern/flags
- Optional chaining (?.),
nullish coalescing (??)
- BigInt (123n, arithmetic,
comparison, BigInt())
- let/const block scoping,
numeric separators
- async/await, Promises,
dynamic import()
- Generators (function*, yield,
yield* delegation)
- Async generators
(async function*,
for await...of)
- Generator methods in classes
and objects
- Automatic Semicolon
Insertion (ASI)
- Closures, prototype chain
* Built-in objects and functions
- console (log, error, warn,
dir, time/timeEnd, table,
count/countReset)
- Math (27 functions incl.
cbrt/fround/clz32/imul)
- JSON (with reviver/replacer)
- Date (full API incl. UTC,
getUTC*/setUTC*)
- RegExp (lookahead,
non-capturing groups,
quantifiers, lazy,
named groups, lookbehind,
flags g/i/m/s/u/y)
- Buffer (hex/base64)
- Promise (then/catch/finally/
all/race/allSettled)
- Map, Set, WeakMap, WeakSet,
Symbol
- setTimeout/setInterval/
clearTimeout
- crypto (MD5, SHA-256),
structuredClone
- TextEncoder, TextDecoder
- Typed Arrays: Uint8Array,
Int8Array, Uint16Array,
Int16Array, Uint32Array,
Int32Array, Float32Array,
Float64Array,
Uint8ClampedArray,
ArrayBuffer, DataView
(from/of, forEach/map/
filter/find/every/some/
reduce, set/fill/slice/
subarray/reverse/indexOf/
includes/join)
- fetch() global HTTP client
- performance.now() timer
- Error.cause (ES2022)
- process.stdout.write,
process.stdin.read
- process.hrtime,
process.nextTick,
queueMicrotask
* String methods: 29+
(charAt, indexOf, slice,
split, replace, replaceAll,
trim, includes, startsWith,
padStart, normalize,
localeCompare, codePointAt,
etc.)
* Array methods: 37+
(push, pop, map, filter,
reduce, reduceRight, sort,
find, findLast,
findLastIndex, forEach,
every, some, splice, flat,
flatMap, entries, keys,
values, copyWithin, at,
Array.from/of/isArray,
toReversed, toSorted,
toSpliced, with)
* Object: keys, values, entries,
assign, create, freeze, seal,
is, fromEntries,
defineProperty/ies, hasOwn,
getPrototypeOf,
setPrototypeOf,
getOwnPropertyNames,
getOwnPropertyDescriptor(s),
preventExtensions,
isExtensible, groupBy,
getOwnPropertySymbols,
getters/setters
* Number: isInteger, isFinite,
isNaN, isSafeInteger,
parseInt, parseFloat,
toString(radix), toFixed,
toExponential, toPrecision,
constants (EPSILON,
MAX_SAFE_INTEGER,
MIN_SAFE_INTEGER,
NaN, Infinity)
* Global functions:
encodeURIComponent,
decodeURIComponent,
encodeURI, decodeURI,
parseInt, parseFloat,
isNaN, isFinite, eval(),
fetch()
* Symbol: Symbol(),
Symbol.for/keyFor,
well-known symbols,
Symbol as property key,
Iterator protocol
(Symbol.iterator)
* Amiga Intuition GUI bindings
- Open windows with title,
size, position
- Graphics: lines, rects,
circles, text, pixels
- Mouse and keyboard events
- System requesters
(alert, confirm)
- Screen information query
* GadTools GUI toolkit
(gui module)
- createWindow() with
declarative gadget layout
- 11 widget types: button,
string, text, integer,
checkbox, cycle, slider,
listview, mx, number,
scroller
- gui.gfx: drawing on
GadTools windows (setColor,
drawLine, fillRect,
drawCircle, drawText,
setPixel, setFont, etc.)
- innerSize() for drawable
area, auto GZZ offset
- Resizable windows
(GIMMEZEROZERO clipping)
- Percentage layout
(left: "50%", width: "80%")
- Negative positioning
(top: -20 = anchor bottom)
- flex: true - gadget expands
to fill available space
- minWidth/minHeight
- Event-driven:
waitEvent/pollEvent,
gadgetup/close/key
- get/set gadget values at
runtime
- setTitle, listview dynamic
item update
- Menu bar: setMenu() with
keyboard shortcuts
- ASL file requester:
fileRequest() with patterns
- ASL font requester:
fontRequest()
- Proper GadTools cleanup
* Clipboard module (clipboard)
- read() - read text from
system clipboard
- write(text) - write text
- clear() - clear clipboard
- Uses IFF FTXT/CHRS via
iffparse.library
* ARexx module (arexx)
- send(port, command) - send
ARexx command to app
- createPort(name) /
closePort()
- getMsg() / waitMsg() /
reply()
- listPorts() - list all
public message ports
- Uses rexxsyslib.library
* Interactive debugger (--debug)
- Step, next, step-out,
continue
- Breakpoints by line number
- Variable inspection
(p varname)
- Call stack backtrace (bt)
- Source listing around
current line
* Node.js-compatible modules
- require() with caching
- CommonJS exports
(module.exports)
- ES modules: import/export
(default, named, namespace)
- Dynamic import() expression
- Native modules: fs, http,
net, buffer, os,
child_process, crypto,
intuition, gui, readline,
dns, clipboard, arexx
- JS modules: path, events,
url, querystring, util,
stream, assert, repl,
timers, string_decoder,
punycode, console,
constants, zlib, iff
* File I/O (fs module)
- readFileSync, writeFileSync,
appendFileSync
- existsSync, unlinkSync,
renameSync, statSync
- readdirSync, mkdirSync,
rmdirSync, copyFileSync
- readFile, writeFile (async)
- createReadStream,
createWriteStream
- Full AmigaOS path support
(Volume:dir/file)
* HTTP/HTTPS server and client
- http.createServer()
non-blocking, 8 concurrent
- http.get(), http.post(),
http.request()
- HTTPS via AmiSSL
(build with -DENABLE_AMISSL)
- Auto redirect following
(301/302/307)
- 10-second socket timeout,
dns.lookup()
- Requires bsdsocket.library
(Roadshow, Miami, AmiTCP)
* OS integration
- process.platform
("amigaos"),
process.arch ("m68k")
- process.argv, process.env,
process.cwd(), process.exit
- os.cpus() (detects
68000/020/030/040/060)
- os.freemem(), os.version()
(Kickstart version)
- child_process.execSync()
via SystemTagList()
* Interactive REPL with command
history (arrow up/down)
* Error types: Error, TypeError,
RangeError, ReferenceError,
SyntaxError, EvalError,
URIError
* Error messages with filename
and line number
* Compiler: bundle JS +
interpreter into standalone
executable
- NodeAmiga -compile MyApp
script.js
- Automatic require() and
import dependency resolution
- All JS modules bundled into
single executable
- No NodeAmiga, no libs/
needed to run the output
Usage
-----
NodeAmiga script.js
Execute a JavaScript file
NodeAmiga -e "code"
Evaluate inline JavaScript
NodeAmiga -compile out script
Compile to standalone exe
NodeAmiga
Start interactive REPL
NodeAmiga -help
Show help
NodeAmiga -v
Show version
NodeAmiga --tree script.js
Use tree-walking interpreter
NodeAmiga --debug script.js
Run with interactive debugger
NodeAmiga --ast script.js
Print AST (debug)
Installation
------------
1. Copy NodeAmiga to C: or any
directory in your path
2. Copy the libs/ directory to
PROGDIR: (same directory as
NodeAmiga), or to LIBS:node/
3. Optional: copy examples/ for
demo scripts
Quick test:
NodeAmiga -e "console.log(
'Hello Amiga!')"
NodeAmiga examples/hello.js
NodeAmiga examples/gui_hello.js
NodeAmiga examples/fibonacci.js
Compile to standalone exe:
NodeAmiga -compile Hello
examples/hello.js
Hello
; Runs without NodeAmiga
; or libs/ !
System Requirements
-------------------
* MC68000 or higher CPU
* AmigaOS 2.04 (Kickstart 37)
or higher
* Minimum 1 MB RAM
(2+ MB recommended)
* bsdsocket.library for
networking features
(Roadshow, Miami, AmiTCP)
* No FPU required
(software floating-point)
Technical Details
-----------------
* Engine: custom-built lexer,
recursive descent parser
with Pratt precedence
climbing, bytecode VM
(default) with tree-walking
fallback
* Bytecode VM: ~8x faster
than tree-walking, lazy
compilation, direct native
dispatch
* Memory: reference counting
(no GC pauses), arena
allocator for AST,
integer cache 0-255
* Stack: auto-allocates 64 KB
via StackSwap
Included Examples
-----------------
hello.js
Platform info and greeting
fibonacci.js
Recursive/iterative benchmark
file_io.js
File read/write/append
http_server.js
HTTP server with routing
http_client.js
HTTP GET and POST requests
classes.js
ES6 classes with inheritance
closures.js
Closures, IIFE, module pat.
array_fun.js
map/filter/reduce/sort
regex.js
RegExp /literal/ and methods
events.js
EventEmitter custom events
promises.js
Promise chains, all, race
timers.js
setTimeout and setInterval
buffer.js
Binary data manipulation
streams.js
Readable/Writable/Transform
sysinfo.js
Full system info display
todo_app.js
TODO app with persistence
mini_grep.js
Pattern search in files
url_parser.js
URL and query string parsing
calculator.js
Recursive descent expr parser
json_db.js
JSON file-based database
myip.js
Fetch public IP from internet
nettime.js
Internet time via HTTP API
weather.js
Weather info for a city
download.js
Download file and save
gui_hello.js
Simplest Intuition window
gui_demo.js
Interactive drawing + mouse
gui_calculator.js
GadTools calculator (320x200)
3d.js
Rotating 3D wireframe cube
3d_tunnel.js
Wireframe tunnel fly-through
pong.js
Bouncing ball (XOR, circle)
gui_translator.js
Google Translate with GUI
gui_window.js
GadTools widget gallery
gui_menu.js
Menu bar + ASL requesters
gui_drawing.js
gui.gfx primitives (4 scenes)
gui_gfx_clock.js
Analog clock (resizable)
gui_keyboard_and_scrolls.js
Arrow keys + scrollers demo
gui_weather.js
Weather app with GadTools GUI
aminet_browser.js
Aminet archive browser + GUI
clipboard.js
System clipboard read/write
arexx.js
ARexx port communication
dns_lookup.js
DNS hostname resolution
readline_chat.js
Interactive readline + prompt
iff_info.js
IFF/ILBM/8SVX file viewer
Known Limitations
-----------------
* No Proxy
* await is synchronous
(spin-waits on event loop)
Version History
---------------
0.18.1 (2026-04-14)
Scroller & gadget pos. fixes
- FIX: Scroller drag ID --
switching between scrollers
no longer emits stale IDs
- FIX: Non-GZZ window gadget
coords aligned with
gfx.innerSize()
(WA_InnerWidth double-sub
removed)
- FIX: MOUSEMOVE identifies
gadget from pointer, not
from stale active_gad_id
0.18.0 (2026-04-13)
Keyboard nav + Scroller enh.
- NEW: Arrow keys, F1-F10,
Help key events via
IDCMP_RAWKEY (evt.key =
"ArrowUp"/"ArrowDown"/
"ArrowLeft"/"ArrowRight"/
"F1".."F10"/"Help") --
both gui and intuition
- NEW: Vertical scroller
orientation (vertical:true)
- NEW: gui.set() scroller
accepts object
{top, total, visible}
- FIX: Duplicate key events
prevented (RAWKEY filtered
for VANILLAKEY codes)
- FIX: Modifier keys filtered
from RAWKEY
- Example:
gui_keyboard_and_scrolls.js
0.17.0 (2026-04-12)
GUI drawing + Intuition fix
- NEW: gui.gfx sub-module --
drawing primitives on
GadTools windows: setColor,
setBColor, setDrawMode,
moveTo, lineTo, drawLine,
drawRect, fillRect,
drawCircle, fillCircle,
drawEllipse, drawText,
setPixel, getPixel, clear,
innerSize, setFont, waitTOF
- FIX: Intuition openWindow
uses WA_InnerWidth/Height
so dimensions match
drawable area (was outer)
- FIX: Intuition gfx.clear
uses EraseRect (GZZ-safe)
instead of SetRast
- FIX: Intuition resize events
update win.width/height
- FIX: Intuition keypress
includes 'key' property
- Examples: gui_drawing.js,
gui_gfx_clock.js
0.16.2 (2026-04-12)
Bytecode VM string compare fix
- FIX: VM comparison ops
(<, >, <=, >=) handle
string operands with
lexicographic comparison
(was converting to NaN)
- FIX: OP_RETURN cleans up
try_depth for handlers
in the current frame
0.16.1 (2026-04-11)
GUI stability + VM fixes
- FIX: Bytecode VM
break/continue leaked
locals on stack
- FIX: GUI MOUSEMOVE reading
garbage GadgetID from
Window pointer
- FIX: Internal GadTools
events leaking to JS
- FIX: REFRESHWINDOW handled
internally
- FIX: Gadget pointer fallback
in GADGETUP/GADGETDOWN
- Benchmark: 40 MB RAM check
0.15.0 (2026-04-09)
Clipboard, ARexx, Debugger,
GUI Menus
- NEW: clipboard module
(read/write/clear)
- NEW: arexx module
(send/receive commands,
port management)
- NEW: Interactive debugger
(--debug flag) step, next,
step-out, breakpoints,
variable inspect, backtrace
- NEW: gui.setMenu() --
GadTools menu bar with
keyboard shortcuts
- NEW: gui.fileRequest() --
ASL file requester
- NEW: gui.fontRequest() --
ASL font requester
- NEW: IDCMP_MENUPICK events
- FIX: ARexx race condition
(Forbid wraps
FindPort+PutMsg)
- FIX: Clipboard chunk size
validation
- FIX: Bus error crash --
BcCompiler/BcVM
heap-allocated
- FIX: Pool memory exhaustion
in tree-walking mode
- FIX: Bytecode compiler
double-realloc pointer
- FIX: Module cache memory
leak (cleanup on exit)
- FIX: VM cascade cleanup
crash (freelist pointer)
0.14.0 (2026-03-28)
Bytecode VM (8x faster)
- NEW: Bytecode compiler +
virtual machine (default)
~8x faster than tree-walk
on benchmarks. Lazy
compilation, direct native
dispatch. Use --tree for
tree-walking fallback.
- NEW: gfx.setDrawMode()
JAM1/JAM2/COMPLEMENT(XOR)
- NEW: gfx.waitTOF() vsync
- NEW: win.innerWidth,
win.innerHeight properties
- NEW: 3d_tunnel.js, pong.js
- FIX: NaN === NaN returned
true (pointer equality bug)
- FIX: Arrays missing
prototype
- FIX: Buffer overflow in
toFixed for numbers > 1e24
- FIX: Buffer overflow in
regex replace zero-length
- FIX: Use-after-free on
borrowed refs in fn calls
0.13.0 (2026-03-27)
Typed Arrays + fetch + streams
- NEW: Typed Arrays
(Uint8Array, Int8Array,
Uint16Array, Int16Array,
Uint32Array, Int32Array,
Float32Array, Float64Array,
Uint8ClampedArray)
- NEW: ArrayBuffer, DataView
- NEW: TypedArray.from(),
TypedArray.of()
- NEW: TypedArray iterator
methods (forEach/map/
filter/find/every/some/
reduce)
- NEW: Typed array indexed
assignment
- NEW: Array.toReversed(),
toSorted(), toSpliced(),
with() (ES2023)
- NEW: Object
.getOwnPropertySymbols()
- NEW: Error.cause (ES2022)
- NEW: fetch() global HTTP
client
- NEW: fs.readFile(),
fs.writeFile() async
- NEW: fs.createReadStream(),
fs.createWriteStream()
- NEW: TypedArray sort(),
copyWithin(), toString()
- NEW: console.count(),
console.countReset()
- NEW: performance.now()
(20ms via DateStamp)
- NEW: zlib module (DEFLATE/
INFLATE, gzip/gunzip,
CRC32)
- NEW: punycode module
(RFC 3492)
- NEW: constants module
- NEW: console module
- NEW: Resizable GUI windows
with responsive layout
- NEW: gui.createWindow
minWidth/minHeight
- NEW: Negative position
values (anchor bottom/right)
- NEW: Keyboard events:
evt.key string property
- NEW: dns.resolve(),
dns.resolveSync()
- NEW: readline: on('line'/
'close'), setPrompt()
- NEW: assert.rejects(),
assert.doesNotReject()
- NEW: HTTP server custom
headers in writeHead()
- NEW: iff module
(IFF/ILBM/8SVX parser)
- FIX: Date.now() returns int
- FIX: Buffer overflow in
toFixed for numbers > 1e24
- FIX: Use-after-free on
borrowed refs in fn calls
- FIX: BigInt mixed-type ops
throw TypeError
- FIX: zlib inflate EOF
- FIX: punycode.decode ASCII
- Tests: 1700+ assertions
0.12.0 (2026-03-27)
Generators + Class Fields
- NEW: Generator functions
(function*, yield)
- NEW: yield* delegation
- NEW: gen.next(value),
gen.throw(err)
- NEW: Generator methods in
classes and objects
- NEW: for...of integration
- NEW: Class fields (public,
static, private #field)
- NEW: Dynamic import()
- NEW: Object.groupBy()
- NEW: Async generators
(async function*,
for await...of)
- NEW: RegExp lookbehind
- NEW: BigInt type (123n)
- NEW: GadTools GUI module
(require('gui')) --
button, string, text,
integer, checkbox, cycle,
slider, listview, mx,
number, scroller
- NEW: URL class,
URLSearchParams
- NEW: path.normalize,
isAbsolute, parse, format,
relative
- NEW: assert.deepStrictEqual,
ifError, match
- NEW: stream.pipeline(),
finished(), backpressure
- NEW: stream.Readable.from()
- NEW: string_decoder module
- NEW: timers.setInterval
async iterator
- NEW: os.endianness,
os.release,
os.networkInterfaces,
os.userInfo
- FIX: Memory leaks in array
methods (forEach, map,
filter, reduce, sort,
flatMap, entries)
- FIX: Use-after-free in
array_reduce
- FIX: String.concat overflow
- FIX: String.match/search
memory leaks
- FIX: JSON \uXXXX produces
proper UTF-8
- FIX: BigInt from double
- FIX: Switch fall-through
- FIX: Spread in fn calls
- FIX: ** right-associative
- FIX: fn.call()/fn.apply()
propagate exceptions
- FIX: for-of string/iterator
memory leaks
- FIX: Class method leaks
- FIX: yield* delegation
iterator/result leaks
- FIX: Array.from() leaks
- FIX: Error constructor leaks
- FIX: Object.entries leaks
- FIX: RegExp constructor leak
- FIX: crypto hash double-
digest crash
- FIX: fs.statSync directory
detection via Lock()
- FIX: Import path buffer
overflow
- FIX: NULL dereference in
equality
- FIX: Object property delete
getter/setter leak
- FIX: Async class methods
- FIX: Math.random() seed
- FIX: encodeURI preserves
reserved characters
- FIX: 60+ total bug fixes
- NEW: Web runtime addon
(addons/web/) -- run GUI
scripts in browser,
Amiga WB3.x look
- NEW: Edge case test suite
(test_edge.js, 430+ asserts)
- FIX: Function property
assignment
- FIX: JSON.parse reviver
use-after-free crash
- FIX: Spread in new expr
- FIX: Unicode \u{XXXX}
braced escapes (ES6)
- FIX: REPL arena
use-after-free
- FIX: Generator throw
propagation
- FIX: Array.from() mapper
memory leaks
- FIX: \uNNNN > 0x7F UTF-8
- FIX: AmiSSL lazy init
- FIX: HTTPS check order
- FIX: Labeled break/continue
- FIX: Buffer indexed access
- FIX: Symbol.toString() crash
- FIX: Date/RegExp/Promise
instanceof
- FIX: require("buffer")
.Buffer self-reference
- FIX: Computed property
read/write on functions
- FIX: 90+ total bug fixes
- Tests: 1550+ assertions
0.11.0 (2026-03-25)
Mega Mega Update
- NEW: fs.readdirSync,
mkdirSync, rmdirSync,
copyFileSync
- NEW: Array: reduceRight,
entries, keys, values,
findLast, findLastIndex,
copyWithin
- NEW: Object:
getOwnPropertyNames,
hasOwn, getPrototypeOf,
getOwnPropertyDescriptor,
setPrototypeOf,
preventExtensions,
isExtensible
- NEW: Number.toExponential,
toPrecision
- NEW: Math: cbrt, fround,
clz32, imul + constants
- NEW: String: codePointAt,
fromCodePoint,
localeCompare, normalize,
raw, replace with callback
- NEW: encodeURI/decodeURI,
encodeURIComponent/
decodeURIComponent
- NEW: console.dir
- NEW: ES modules
(import/export)
- NEW: RegExp: {n}/{n,}/{n,m}
quantifiers, lazy, non-
capturing groups, lookahead,
named groups, flags s/u/y
- NEW: Symbol as property key,
Iterator protocol
- NEW: eval() global function
- NEW: EvalError, URIError
- NEW: Date.UTC(),
getUTC*/setUTC*
- NEW: Class static methods
- NEW: Destructuring assignment
without var/let/const
- NEW: Compiler (-compile) --
bundle JS into standalone
- FIX: Function.prototype
.bind() partial application
- FIX: ES module export
function declarations
- FIX: instanceof Error for
all Error subtypes
- Tests: 960+ assertions
0.10.0 (2026-03-25)
- FIX: String.fromCharCode,
Number.isInteger/isFinite/
isNaN/isSafeInteger
- FIX: Number.prototype
.toString(radix)
- FIX: querystring.unescape
percent decoding
- Removed 68040/68060 builds
0.9.0 (2026-03-24)
- HTTPS support via AmiSSL
- Interactive REPL with
readline and history
- Buffer hex/base64 encoding
- Tagged template literals
- Promise chain fixes
0.8.0 (2026-03-23)
- Map, Set, WeakMap, WeakSet,
Symbol
- Regex literal /pattern/flags
- async/await support
- Destructuring, spread/rest
- for-of loops, optional
chaining (?.)
Credits
-------
Juen/Project R3D+Appendix
+Nah-Kolor
|