Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Update #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 25, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Simplify to use new DefaultRubyVM
  • Loading branch information
kddnewton committed Feb 25, 2023
commit 14c06e7a21a91d929953414074408df2f7eed28a
21 changes: 0 additions & 21 deletions bin/build

This file was deleted.

22 changes: 22 additions & 0 deletions bin/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import esbuild from "esbuild";
import url from "url";
import wasmPlugin from "./wasmPlugin.mjs";

const entryPoint = url.fileURLToPath(new URL("../src/index.ts", import.meta.url));
const outdir = url.fileURLToPath(new URL("../docs", import.meta.url));

const { metafile } = await esbuild.build({
bundle: true,
entryPoints: [entryPoint],
format: "esm",
metafile: true,
minify: true,
outdir,
plugins: [wasmPlugin],
sourcemap: true,
splitting: true,
target: "es6"
});

const analysis = await esbuild.analyzeMetafile(metafile);
console.log(analysis);
25 changes: 0 additions & 25 deletions bin/serve

This file was deleted.

20 changes: 20 additions & 0 deletions bin/serve.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import esbuild from "esbuild";
import url from "url";
import wasmPlugin from "./wasmPlugin.mjs";

const entryPoint = url.fileURLToPath(new URL("../src/index.ts", import.meta.url));
const outdir = url.fileURLToPath(new URL("../docs", import.meta.url));

const ctx = await esbuild.context({
bundle: true,
entryPoints: [entryPoint],
format: "esm",
outdir,
plugins: [wasmPlugin],
sourcemap: true,
splitting: true,
target: "esnext"
});

const { host, port } = await ctx.serve({ servedir: outdir });
console.log(`Listening at ${host}:${port}`);
11 changes: 6 additions & 5 deletions bin/wasmPlugin.js → bin/wasmPlugin.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module.exports = {
import path from 'node:path';
import fs from 'node:fs';

export default {
name: 'wasm',
setup(build) {
let path = require('path')
let fs = require('fs')

// Resolve ".wasm" files to a path with a namespace
build.onResolve({ filter: /\.wasm$/ }, args => {
// If this is the import inside the stub module, import the
Expand Down Expand Up @@ -37,7 +37,7 @@ module.exports = {
// binary itself is imported from a second virtual module.
build.onLoad({ filter: /.*/, namespace: 'wasm-stub' }, async (args) => ({
contents: `import wasm from ${JSON.stringify(args.path)}
export default (imports) => WebAssembly.instantiate(wasm, imports).then((result) => result.instance)`,
export default () => WebAssembly.compile(wasm)`,
}))

// Virtual modules in the "wasm-binary" namespace contain the
Expand All @@ -50,3 +50,4 @@ module.exports = {
}))
},
}

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
{
"license": "MIT",
"scripts": {
"build": "bin/build",
"serve": "bin/serve"
"build": "node bin/build.mjs",
"serve": "node bin/serve.mjs"
},
"dependencies": {
"@monaco-editor/loader": "^1.3.2",
"@wasmer/wasi": "^0.12.0",
"@wasmer/wasmfs": "^0.12.0",
"mermaid": "^9.4.0",
"mermaid": "^10.0.0",
"path-browserify": "^1.0.1",
"ruby-head-wasm-wasi": "^0.3.0"
"ruby-head-wasm-wasi": "^0.6.0"
},
"devDependencies": {
"@types/node": "^17.0.33",
"@types/node": "^18.14.1",
"@types/path-browserify": "^1.0.0",
"esbuild": "^0.14.39",
"monaco-editor": "^0.33.0"
"esbuild": "^0.17.10",
"monaco-editor": "^0.36.0"
}
}
68 changes: 7 additions & 61 deletions src/createRuby.ts
Original file line number Diff line number Diff line change
@@ -1,71 +1,17 @@
import { WASI } from "@wasmer/wasi";
import { WasmFs } from "@wasmer/wasmfs";
import path from "path-browserify";
import { RubyVM } from "ruby-head-wasm-wasi/dist/index";
import { DefaultRubyVM } from "ruby-head-wasm-wasi/dist/browser.esm.js";

import load from "./app.wasm";

// This overwrites the default writeSync function used by the WasmFs to instead
// pipe it out to the console.
function createWriter(originalWriter: Function) {
return function () {
let text: string;

if (arguments.length === 4) {
text = arguments[1];
} else {
text = new TextDecoder("utf-8").decode(arguments[1]);
}

switch (arguments[0]) {
case 1:
console.log(text);
break;
case 2:
console.warn(text);
break;
}

return originalWriter.call(arguments);
}
}

export default async function createRuby() {
// First, create a new file system that we can use internally within the Ruby
// WASM VM.
const wasmFs = new WasmFs();
wasmFs.fs.mkdirSync("/tmp", 0o777);
wasmFs.fs.writeSync = createWriter(wasmFs.fs.writeSync.bind(wasmFs.fs));

// Next, create a new WASI instance with the correct options overridden from
// the defaults.
const wasi = new WASI({
bindings: { ...WASI.defaultBindings, fs: wasmFs.fs, path: path },
preopens: { "/": "/tmp" }
});

// Then, create a new Ruby VM instance that we can use to store the memory for
// our application.
const ruby = new RubyVM();
const imports = { wasi_snapshot_preview1: wasi.wasiImport };
ruby.addToImports(imports);

// Set the WASI memory to use the memory for our application.
const instance = await load(imports);
wasi.setMemory(instance.exports.memory);

// Load our application into the virtual machine.
instance.exports._initialize();
await ruby.setInstance(instance);

// Initial our virtual machine and return it. It should now be able to
// evaluate and execute Ruby code.
ruby.initialize();
const { vm } = await DefaultRubyVM(await load())

// Once our virtual machine is booted, we're going to require the necessary
// files to make it work. I'm not sure why I need to explicitly require
// did_you_mean here, but it doesn't work without it.
ruby.eval(`
vm.eval(`
require "rubygems"
require "did_you_mean"
require "json"
Expand All @@ -81,7 +27,7 @@ export default async function createRuby() {
const jsonSource = JSON.stringify(JSON.stringify(source));
const rubySource = `RubyVM::InstructionSequence.compile(JSON.parse(${jsonSource})).disasm`;

return ruby.eval(rubySource).toString();
return vm.eval(rubySource).toString();
},
mermaid(source: string) {
const jsonSource = JSON.stringify(JSON.stringify(source));
Expand All @@ -90,23 +36,23 @@ export default async function createRuby() {
SyntaxTree.parse(source).to_mermaid
`;

return ruby.eval(rubySource).toString();
return vm.eval(rubySource).toString();
},
// A function that calls through to the SyntaxTree.format function to get
// the pretty-printed version of the source.
format(source: string) {
const jsonSource = JSON.stringify(JSON.stringify(source));
const rubySource = `SyntaxTree.format(JSON.parse(${jsonSource}))`;

return ruby.eval(rubySource).toString();
return vm.eval(rubySource).toString();
},
// A function that calls through to PP to get the pretty-printed version of
// the syntax tree.
prettyPrint(source: string) {
const jsonSource = JSON.stringify(JSON.stringify(source));
const rubySource = `PP.pp(SyntaxTree.parse(JSON.parse(${jsonSource})), +"", 80)`;

return ruby.eval(rubySource).toString();
return vm.eval(rubySource).toString();
}
};
};
Expand Down
Loading