Milestones

Version history

The MacSurf timeline — milestone by milestone, from the first HTTP fetch over Open Transport to CSS Grid on a beige G3.

The First ES5 JavaScript Engine on Classic Macintosh

On April 15, 2026, a Power Macintosh running Mac OS 9 executed a JavaScript program and displayed the result in a web browser window. The title bar read "MacSurf - JS OK (1+1=2)." It was the first time a modern ECMAScript engine had ever run on Classic Mac OS hardware.

By the end of that same night, MacSurf was rendering ASCII Mandelbrot fractals computed entirely in JavaScript, sorting 5,000-element arrays via quicksort, evaluating the Ackermann function to depth 1,021, and parsing JSON — all inside a Carbon application on a machine from 1998.

No consumer browser has ever done this before. Classic IE 5.x shipped JScript 5, but it predates ES5 and ran on Mac OS X, not Classic. Classilla attempted Mozilla's SpiderMonkey on OS 9 but JavaScript was its primary source of crashes and instability. MacSurf is the first browser to ship a stable, fully functional ES5 engine on this platform.


The Machine

Power Macintosh G3 Minitower (Beige), Machine ID 510

This is Gary Hansen's machine with an aftermarket Sonnet G4 processor upgrade installed — a pretty sweet find. The Sonnet Processor Upgrade 1.4.5 extension is active in the System Folder. Every line of code was compiled on it. Every screenshot was captured from it. Every benchmark was measured on it. There is no emulator in this story. System profile generated live from the machine on April 15, 2026 at 8:47 PM.


The Technology Stack

MacSurf exists because of several pieces of technology, most of them older than the machine itself:

NetSurf (netsurf-browser.org)

The browser engine. An open-source web browser written in C with no external dependencies, designed for low-resource systems. NetSurf's clean architecture — with explicit support for cooperative multitasking and non-POSIX platforms via its frontend abstraction — made the port to Mac OS 9 possible. The RISC OS and AmigaOS frontends served as direct references. MacSurf links against all five NetSurf core libraries: libparserutils, libhubbub, libdom, libcss, and libwapcaplet — approximately 125,000 lines of C across 443 source files.

macQJS — QuickJS (bellard.org/quickjs)

The JavaScript engine, and MacSurf's own port of QuickJS to Classic Mac OS. It runs ES2023 natively on the Mac, linked into the base build, evaluating page scripts directly with no transpilation step and nothing offloaded to a server. Modern JavaScript — let/const, arrow functions, classes, template literals, destructuring, generators, async/await, Promises, modern built-ins — executes as written. macQJS is what lets a full contemporary WordPress stack (jQuery 3.7.1 and a real plugin bundle) run to completion on a 1998 PowerPC.

Previously: MacSurf shipped Duktape 2.7.0, Sami Vaarala's embeddable ES5.1 interpreter in portable C89, from the April 2026 JavaScript milestone through the 1.5 line. Duktape got the project its first JavaScript on Mac OS 9 and deserves the credit for it — but ES5.1 meant every modern bundle had to go through a custom ES6→ES5 transpiler that kept corrupting the scripts it rewrote. The 1.68 "macQJS" release replaced Duktape with QuickJS, removed it from the tree entirely, and retired the transpiler along with it.

Metrowerks CodeWarrior 8 Pro

The compiler. The last professional C/C++ IDE for Classic Mac OS, running natively on the same machine it targets. CW8 compiles in strict C89 — no inline, no // comments, no designated initializers, no declarations inside for — and it has still swallowed a combined codebase well past 130,000 lines, including a full QuickJS engine and 443 files of ported NetSurf libraries. The 8.3 update's improved optimizer generates reasonable PowerPC code despite the C89 constraints.

Carbon API (Apple)

The application framework. Carbon provides the window manager, event loop, controls, QuickDraw drawing, and Open Transport networking that MacSurf uses. Designed as a bridge between Classic Mac OS and OS X, Carbon gave MacSurf access to modern (for 2001) UI primitives while remaining compatible with the cooperative multitasking model of OS 9.

Open Transport (Apple)

The networking layer. MacSurf issues *InContext Open Transport calls for TCP/IP: the Carbon application sets up an OT client context at startup and every fetcher opens its endpoints through it. Synchronous calls use OTUseSyncIdleEvents with a notifier that yields to the Thread Manager, which is how the UI stays responsive during network operations under cooperative multitasking. cy384's SSHeven and the Retro68 OT TCP demo remain the reference implementations for the underlying patterns.

macTLS (custom)

The TLS stack, written for this project and linked directly into the browser. Hand-written TLS 1.3 (RFC 8446 — X25519 and multi-curve ECDHE, ChaCha20-Poly1305 and AES-128-GCM) with TLS 1.2 fallback, the full Mozilla CA bundle of 121 anchors baked in, and its own entropy source behind it. As far as we know it is the first TLS 1.3 implementation on Classic Mac OS (v1.3, May 29 2026). This is what lets the Mac open its own HTTPS connections to origin servers.

Previously: a single Go binary on a VPS terminated TLS on the Mac's behalf — the Mac sent plain HTTP, the proxy fetched the HTTPS URL and returned plain HTTP. macTLS replaced it around May 25 2026 and the proxy has been retired since; it is no longer on the request path. Making the Mac the TLS client is also what made real logins possible, since cookies and credentials now live on the client where sites expect them.

Claude (Anthropic)

Most of MacSurf — the frontend, library ports, build system, JavaScript engine, and TLS stack — was built with Claude, an AI assistant from Anthropic. The workflow: Claude wrote C89-compatible source code and diagnosed compilation errors from logs sent back through a reverse SSH tunnel from the Mac. Runtime crashes were debugged from photographs of the physical screen. A typical cycle: write code on Linux, SCP a tar to the Mac, compile in CodeWarrior, photograph or transcribe errors, send them back, and iterate.


The Timeline

v0.1 — The Browser Shell (March-April 2026)

v0.2 — The NetSurf Core (April 15, 2026)

v0.2-moonshot — JavaScript (April 15-16, 2026)

v0.3 — Real HTML rendering (April 18-19, 2026)

v0.4 — CSS3 visible on hardware (May 13, 2026)

v0.4.x — CSS feature catch-up (May 14-19, 2026)

v0.5 — Grid V2 + font dispatch (May 20, 2026)

macTLS — HTTPS moves onto the Mac (May 2026)

v1.5 "Modernity" (June 11, 2026)

v1.68 "macQJS" — the JavaScript engine is replaced (July 7, 2026)

v2.0 (July 11, 2026)

v2.0.5 — the polish batch (July 17, 2026)

Since 2.0.5 — the 3.0 development line


The Benchmarks

Measured on the Power Macintosh G3 Minitower with Sonnet G4 400 MHz upgrade, Mac OS 9.1, 192 MB RAM. These are the original April 2026 numbers, taken on Duktape 2.7.0 (DUK_USE_NATIVE_CALL_RECLIMIT 128) — the engine of the day. They are kept here as the historical record of that first night; the browser has since moved to macQJS and has not been re-benchmarked against this suite.

Test Result Time
Linked list: 10,000 nodes + reversal Correct <1 ms
Regex: email extraction from prose 4/4 found <1 ms
Promise polyfill: 3-step chain Correct (6) <1 ms
BST: 15-node insert + in-order traversal Correct <1 ms
Matrix multiply: 30x30 Correct <1 ms
Event emitter: 1,000 events x 2 listeners 2,001 fired <1 ms
Quicksort: 5,000 random integers Verified sorted 1,000 ms
Hash table: 10,000 insert + lookup 10,000/10,000 1,000 ms
String builder: 100,000 chars (array+join) 100,000 length 2,000 ms
100K Math.sqrt + Math.sin loop Completed 3,000 ms
Ackermann(3,7) 1,021 (correct) 5,000-6,000 ms
Mandelbrot: 40x20 ASCII, 80 max iterations Renders correctly ~2,000 ms

The Screenshots

The curated milestone set in screenshots/ shows the project as it stands today:

Running on real Mac OS 9

MacSurf running in real Mac OS 9 on a G3 iMac

The fixes50 text-shadow probe page, rendered on a real Power Macintosh G3 iMac running Mac OS 9.1 with CarbonLib. Platinum theme, beige hardware, modern CSS3 in 2026.

Real CSS typography on Mac OS 9

CSS typography, custom properties, nested lists

"MacSurf — pushing the cascade." Author CSS with custom properties (var(--sans)), nested unordered and ordered lists with the bullet-glyph repair from fixes143a, definition lists, mathematical inline elements — all driven by libcss + the QuickDraw plotters.

Linear gradients + flex layout

CSS linear gradients with flex justify-content

fixes47's real per-row QuickDraw gradient painting plus flex-box justify-content distribution variants. Four gradient bars over start / end / center / between / around / evenly flex modes, all on real hardware.

Cards, callouts, tables

Border-radius cards, accent-border callouts, styled tables

border-radius cards (via FrameRoundRect / PaintRoundRect), accent-left callouts for notes and warnings, and a real CSS feature-support matrix rendered as a styled HTML table.

Text-shadow + opacity

text-shadow + opacity stipple via QuickDraw

fixes50's -macsurf-text-shadow paints drop shadows under DrawText, with QuickDraw stipple patterns providing the opacity steps from solid → invisible.

The Mandelbrot

ASCII Mandelbrot fractal computed by Duktape

An ASCII Mandelbrot set, 40x20 characters, 80 iterations per pixel, computed entirely in JavaScript on a PowerPC G3 running Mac OS 9 — by Duktape, the engine of that first night in April 2026. The fractal that proved a 1998 machine can run a scripting language at all. The browser runs macQJS today.


What's Next

Full open-issue list: Issues.


Credits

Patrick Britton — Creator, hardware wrangler, build engineer, tester, and the person who believed a 1998 Power Mac could run JavaScript in 2026.

Claude (Anthropic) — Development partner. Wrote the C code, diagnosed CW8 errors from transcribed logs, debugged crashes from photographs of a CRT monitor, and kept shipping fixes until the Mandelbrot rendered.

Sami Vaarala — Creator of Duktape. The decision to write an ES5 engine in portable C89 with a single-file amalgamation is what put JavaScript on Mac OS 9 in the first place. Duktape compiled on CodeWarrior 8 with zero source patches, and carried MacSurf from the first 1+1=2 through the 1.5 line.

Fabrice Bellard and Charlie Gordon — Creators of QuickJS. A small, portable, genuinely complete modern JavaScript engine is the reason a 1998 PowerPC can run ES2023 and execute a contemporary WordPress bundle. macQJS is MacSurf's port of their work.

NetSurf contributors — The NetSurf browser's clean C architecture, explicit POSIX-free design, and cooperative-multitasking frontend model gave MacSurf a real browser engine to build on.

cy384 — Author of SSHeven and the Retro68 OT TCP demo. The Open Transport patterns MacSurf uses for networking are directly derived from cy384's verified-working implementations.

Macintosh Garden (macintoshgarden.org) — The archive of Classic Mac software. CodeWarrior 8, ResEdit, system software, extensions, utilities — if it ran on a classic Mac and you needed it, Macintosh Garden had it. This project would not have been possible without the preservation work of that community.

Gary Hansen (1947–2002)

Gary Hansen

Gary and Kaija

Gary the mechanic

Gary's reflection in chrome

Gary Hansen was a communications lifer who rode every wave the industry threw at him. He started shooting photos and filing stories for the New Ulm Daily Journal at thirteen, landed at the Associated Press by twenty-one — covering Nixon, Bobby Kennedy, and McGovern out of the Pierre, SD bureau — and by the mid-'80s had pivoted hard into the desktop publishing revolution, training thousands of employees at shops like 3M, Honeywell, and General Mills on the Mac tools that were rewriting the rules of print. He called himself "the quintessential Renaissance Man of communications," and the resume backed it up.

By the mid-'90s Gary had founded Digital Concepts Corporation out of his home in Edina, Minnesota, building websites, managing hosting, and doing print design and photography for a stable of clients. He ran four browsers simultaneously for cross-browser testing, kept nearly 1,700 bookmarks organized across them, and was an early adopter of everything from PageMaker to cable internet to Napster. His Power Mac G3 — upgraded with a Sonnet Encore G4 processor because stock specs were never quite enough — was the nerve center for all of it.

Outside the screen, Gary was a private pilot, a certified SCUBA diver, a chess tactician, and a deeply committed motorcycle guy. He served on the board of the Minnesota Motorcycle Riders Association, designed their Freedom Review newsletter in PageMaker, lobbied for rider legislation, and eventually signed on as General Manager at Easyriders of Minneapolis — submitting a brutally honest five-page application that noted, among his weaknesses, "no tattoos."

He was a father who named every password after his daughter Kaija, a husband to Deb, and a guy who helped everyone around him get online, get a resume typed, or get a computer set up. He was 55 when he died in September 2002. The G3 that powers this browser was part of his world — and this project is a small way of keeping that machine, and the curiosity behind it, running.

The Classic Mac community — Everyone keeping these machines alive, sharing knowledge about CarbonLib, Universal Interfaces, and the art of writing software for an OS that Apple abandoned 24 years ago.


MacSurf is open source. The code, the story, and the screenshots are all real. No emulators were used. No shortcuts were taken. Gary's Power Macintosh G3 from 1998 runs JavaScript in 2026.

Discussion

Powered by GitHub Discussions — sign in with GitHub to comment.