1- import crypto from "crypto" ;
21import { WASI } from "@wasmer/wasi" ;
32import { WasmFs } from "@wasmer/wasmfs" ;
4- import path from "path-browserify" ;
53import { RubyVM } from "ruby-head-wasm-wasi/dist/index" ;
64
7- import load from "./app.wasm" ;
5+ import { randomFillSync } from "randomfill" ;
6+ import path from "path-browserify" ;
7+
8+ import app from "./app.wasm" ;
9+
10+ type AppExports = {
11+ _initialize : ( ) => void ;
12+ memory : WebAssembly . Memory ;
13+ } ;
814
915// This overwrites the default writeSync function used by the WasmFs to instead
1016// pipe it out to the console.
@@ -31,7 +37,18 @@ function createWriter(originalWriter: Function) {
3137 }
3238}
3339
34- export default async function createRuby ( ) {
40+ type SyntaxTreeHandler = {
41+ format ( source : string ) : string ;
42+ parse ( source : string ) : string ;
43+ read ( filepath : string ) : string ;
44+ } ;
45+
46+ export type SyntaxTree = {
47+ rubyVM : RubyVM ;
48+ handlers : Record < "haml" | "ruby" , SyntaxTreeHandler > ;
49+ } ;
50+
51+ export default async function createSyntaxTree ( ) : Promise < SyntaxTree > {
3552 // First, create a new file system that we can use internally within the Ruby
3653 // WASM VM.
3754 const wasmFs = new WasmFs ( ) ;
@@ -41,12 +58,7 @@ export default async function createRuby() {
4158 // Next, create a new WASI instance with the correct options overridden from
4259 // the defaults.
4360 const wasi = new WASI ( {
44- bindings : {
45- ...WASI . defaultBindings ,
46- fs : wasmFs . fs ,
47- path : path ,
48- randomFillSync : crypto . randomFillSync as typeof WASI . defaultBindings . randomFillSync ,
49- } ,
61+ bindings : { ...WASI . defaultBindings , fs : wasmFs . fs , path, randomFillSync } ,
5062 preopens : { "/" : "/tmp" }
5163 } ) ;
5264
@@ -57,7 +69,11 @@ export default async function createRuby() {
5769 rubyVM . addToImports ( imports ) ;
5870
5971 // Set the WASI memory to use the memory for our application.
60- const instance = await load ( imports ) ;
72+ const instance = await WebAssembly . instantiate ( app , imports ) . then ( ( result ) => {
73+ return result . instance as WebAssembly . Instance & { exports : AppExports } ;
74+ } ) ;
75+
76+ // Make sure WASI and our web assembly instance share their memory.
6177 wasi . setMemory ( instance . exports . memory ) ;
6278
6379 // Load our application into the virtual machine.
@@ -83,22 +99,43 @@ export default async function createRuby() {
8399
84100 return {
85101 rubyVM,
86- formatHAML ( source : string ) {
87- return format ( source , ".haml" ) ;
88- } ,
89- formatRuby ( source : string ) {
90- return format ( source , ".rb" ) ;
91- } ,
92- // formatRBS(source: string) {
93- // return format(source, ".rbs");
94- // }
102+ handlers : {
103+ haml : makeSyntaxTreeHandler ( ".haml" ) ,
104+ // rbs: makeSyntaxTreeHandler(".rbs"),
105+ ruby : makeSyntaxTreeHandler ( ".rb" )
106+ }
95107 } ;
96108
97- function format ( source : string , kind : string ) {
98- const jsonSource = JSON . stringify ( JSON . stringify ( source ) ) ;
99- const rubySource = `SyntaxTree::HANDLERS.fetch("${ kind } ").format(JSON.parse(${ jsonSource } ))` ;
100- return rubyVM . eval ( rubySource ) . toString ( ) ;
109+ function makeSyntaxTreeHandler ( extension : string ) : SyntaxTreeHandler {
110+ return {
111+ format ( source ) {
112+ const jsonSource = JSON . stringify ( JSON . stringify ( source ) ) ;
113+ const rubySource = `
114+ handler = SyntaxTree::HANDLERS["${ extension } "]
115+ handler.format(JSON.parse(${ jsonSource } ))
116+ ` ;
117+
118+ return rubyVM . eval ( rubySource ) . toString ( ) ;
119+ } ,
120+ parse ( source ) {
121+ const jsonSource = JSON . stringify ( JSON . stringify ( source ) ) ;
122+ const rubySource = `
123+ handler = SyntaxTree::HANDLERS["${ extension } "]
124+ node = handler.parse(JSON.parse(${ jsonSource } ))
125+ PP.pp(node, +"", 80)
126+ ` ;
127+
128+ return rubyVM . eval ( rubySource ) . toString ( ) ;
129+ } ,
130+ read ( filepath ) {
131+ const jsonSource = JSON . stringify ( JSON . stringify ( filepath ) ) ;
132+ const rubySource = `
133+ handler = SyntaxTree::HANDLERS["${ extension } "]
134+ handler.read(JSON.parse(${ jsonSource } ))
135+ ` ;
136+
137+ return rubyVM . eval ( rubySource ) . toString ( ) ;
138+ }
139+ } ;
101140 }
102141} ;
103-
104- export type Ruby = Awaited < ReturnType < typeof createRuby > > ;
0 commit comments