Smalltalk in your browser

Run Squeak, Pharo and Cuis images right in the browser — pure JavaScript, no plugins, no server. Built on SqueakJS, the original project, extended by Agustín Martínez with support for more Smalltalks and a Web-Worker runtime.

What you get

Getting there took a dozen VM fixes — 64-bit indexable arrays, the Sista push thisProcess bytecode, file-attribute and working-directory primitives, semaphores that accept subclasses, the 16- and 64-bit array formats Cuis 7.x relies on, a JIT fault that now falls back to the plain interpreter instead of killing the image — plus startup scripts that hand Pharo's 64-bit builds back the display and event classes they dropped when they moved to SDL2.

Run an image from your device

Drag a Smalltalk image onto this page (together with its changes and sources files, if any) to run it.

Drop images and other files here, or

Files are stored in your browser's database; clicking a name above exports it to your Downloads.

Or run one of these from the internet

Each link is the build its own project publishes today. First run downloads and caches the image in your browser; later starts are much faster. If a bundle ships both a 32- and 64-bit image, the 32-bit build is used. The links name the project's own server, which is where the bytes come from. GitHub sends the CORS headers a browser requires, so Cuis is fetched directly; files.squeak.org and files.pharo.org don't, so the launcher routes those two through a small proxy of ours.

About Pharo: 10, 11, 12 and 13 all run, 32- and 64-bit — drop any of them on this page, your own images included. The 64-bit builds render through SDL2 and dropped the classic display classes, so they need a startup script that puts those back; the launcher reads the image to work out which of the two it wants (10 and 11 still carry DisplayScreen, 12 and 13 removed it outright) and installs it for you. Git/Iceberg needs native FFI, which a browser can't provide, so that startup step is skipped rather than left to open a debugger — Pharo runs git-less, exactly as on a machine without libgit2. Pharo 14, still in development, does not run yet. The live Morphic demo is Pharo with the IDE cleared away and an application in its place, saved as an image that opens with it already running: bubbles you can drag, and a shockwave where you click.

Embed it on your own site

The easy way is an <iframe> pointed at this launcher: input, cursor, clipboard, sound, save-to-Downloads and the file picker all come wired — see it running here, with the Pharo app embedded in an ordinary page.

To drive the VM from your own page instead, talk to the worker directly. This much boots an image and paints it:

<canvas id="sq"></canvas>
<script type="module">
  import "./squeak.js";   // brings the virtual file system along

  // an image expects its .changes (and .sources) beside it
  for (const f of ["my.changes", "my.sources"]) {
    const buf = await (await fetch(f)).arrayBuffer();
    await new Promise(ok => { if (!Squeak.filePut("/" + f, buf, ok)) ok(); });
  }
  const canvas = document.getElementById("sq");
  canvas.width = innerWidth; canvas.height = innerHeight;
  const offscreen = canvas.transferControlToOffscreen();
  const worker = new Worker("squeak_worker.js", { type: "module" });
  const settings = {};    // a worker has no localStorage: hand it a snapshot
  for (let i = 0; i < localStorage.length; i++)
    settings[localStorage.key(i)] = localStorage.getItem(localStorage.key(i));
  worker.postMessage({
    type: "init", canvas: offscreen,
    width: canvas.width, height: canvas.height,
    image: "my.image",   // a URL, or the image bytes (ArrayBuffer)
    name:  "/my.image",  // full path, including .image
    settings,
  }, [offscreen]);
  // then forward mouse/keyboard and handle cursor/clipboard/sound —
  // see run/index.html for the complete wiring.
</script>

Skip the file-system part and the image still boots, but Squeak and Cuis will greet you with a debugger the moment they look for their changes file. The file contents live in IndexedDB, shared with the worker; only the directory listing has to be passed in. For a classic single-thread embed you can still use SqueakJS.runSqueak("my.image", canvas, {…}) from squeak.js.

Credits & source

SmalltalkJsVm is free software (MIT). It builds on SqueakJS, the original project — written by Vanessa Freudenberg, who showed a decade ago that a full Smalltalk VM could live in a browser tab. Everything here stands on that work. The Pharo and Cuis 7.x compatibility, the Web Worker runtime and the usability additions live in this fork by Agustín Martínez. Bug reports and pull requests welcome.

Have fun! — SmalltalkJsVm is free software (MIT).