Spaces:
Running
Running
| // This is a minimal headless SqueakJS VM | |
| // | |
| // The headless SqueakJS VM can be used inside a browser. | |
| // The VM can run in the main (UI) thread or in a WebWorker thread. Some browsers | |
| // do not support ES6 modules yet for WebWorker scripts. Please use or create | |
| // a Javascript bundle of the VM in that case. | |
| // | |
| // A special ConsolePlugin is loaded which allows sending messages to the console. | |
| // Add the following method to the Smalltalk image (to Object for example): | |
| // | |
| // primLog: messageString level: levelString | |
| // | |
| // "Log messageString to the console. The specified level should be one of: | |
| // 'log' | |
| // 'info' | |
| // 'warn' | |
| // 'error' | |
| // " | |
| // | |
| // <primitive: 'primitiveLog:level:' module: 'ConsolePlugin'> | |
| // ^ self | |
| // | |
| // | |
| // There is no default file support loaded. If needed add the relevant modules/plugins like: | |
| // import "./vm.files.browser.js"; | |
| // import "./vm.plugins.file.browser.js"; | |
| // Load VM and the internal plugins | |
| import "./globals.js"; | |
| import "./vm.js"; | |
| import "./vm.object.js"; | |
| import "./vm.object.spur.js"; | |
| import "./vm.image.js"; | |
| import "./vm.interpreter.js"; | |
| import "./vm.interpreter.proxy.js"; | |
| import "./vm.instruction.stream.js"; | |
| import "./vm.instruction.stream.sista.js"; | |
| import "./vm.instruction.printer.js"; | |
| import "./vm.primitives.js"; | |
| import "./jit.js"; | |
| import "./vm.display.js"; | |
| import "./vm.display.headless.js"; // use headless display to prevent image crashing/becoming unresponsive | |
| import "./vm.input.js"; | |
| import "./vm.input.headless.js"; // use headless input to prevent image crashing/becoming unresponsive | |
| import "./vm.plugins.js"; | |
| import "./plugins/ConsolePlugin.js"; | |
| // Run image by starting interpreter on it | |
| function runImage(imageData, imageName, options) { | |
| // Create Squeak image from raw data | |
| var image = new Squeak.Image(imageName.replace(/\.image$/i, "")); | |
| image.readFromBuffer(imageData, function startRunning() { | |
| // Create fake display and create interpreter | |
| var display = { vmOptions: [ "-vm-display-null", "-nodisplay" ] }; | |
| var vm = new Squeak.Interpreter(image, display); | |
| function run() { | |
| try { | |
| vm.interpret(50, function runAgain(ms) { | |
| // Ignore display.quitFlag when requested. | |
| // Some Smalltalk images quit when no display is found. | |
| if (options.ignoreQuit || !display.quitFlag) { | |
| setTimeout(run, ms === "sleep" ? 10 : ms); | |
| } | |
| }); | |
| } catch(e) { | |
| console.error("Failure during Squeak run: ", e); | |
| } | |
| } | |
| // Start the interpreter | |
| run(); | |
| }); | |
| } | |
| function fetchImageAndRun(imageName, options) { | |
| fetch(imageName, { | |
| method: "GET", | |
| mode: "cors", | |
| cache: "no-store" | |
| }).then(function(response) { | |
| if (!response.ok) { | |
| throw new Error("Response not OK: " + response.status); | |
| } | |
| return response.arrayBuffer(); | |
| }).then(function(imageData) { | |
| runImage(imageData, imageName, options); | |
| }).catch(function(error) { | |
| console.error("Failed to retrieve image", error); | |
| }); | |
| } | |
| // Extend Squeak with settings and options to fetch and run image | |
| Object.extend(Squeak, { | |
| vmPath: "/", | |
| platformSubtype: "Browser", | |
| osVersion: navigator.userAgent, // might want to parse | |
| windowSystem: "headless", | |
| fetchImageAndRun: fetchImageAndRun, | |
| }); | |
| // Retrieve image name from URL | |
| var searchParams = (new URL(self.location)).searchParams; | |
| var imageName = searchParams.get("imageName"); | |
| if (imageName) { | |
| var options = { | |
| ignoreQuit: searchParams.get("ignoreQuit") !== null | |
| }; | |
| fetchImageAndRun(imageName, options); | |
| } | |