1
- import crypto from "crypto" ;
2
1
import { WASI } from "@wasmer/wasi" ;
3
2
import { WasmFs } from "@wasmer/wasmfs" ;
4
- import path from "path-browserify" ;
5
3
import { RubyVM } from "ruby-head-wasm-wasi/dist/index" ;
6
4
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
+ } ;
8
14
9
15
// This overwrites the default writeSync function used by the WasmFs to instead
10
16
// pipe it out to the console.
@@ -31,7 +37,18 @@ function createWriter(originalWriter: Function) {
31
37
}
32
38
}
33
39
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 > {
35
52
// First, create a new file system that we can use internally within the Ruby
36
53
// WASM VM.
37
54
const wasmFs = new WasmFs ( ) ;
@@ -41,12 +58,7 @@ export default async function createRuby() {
41
58
// Next, create a new WASI instance with the correct options overridden from
42
59
// the defaults.
43
60
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 } ,
50
62
preopens : { "/" : "/tmp" }
51
63
} ) ;
52
64
@@ -57,7 +69,11 @@ export default async function createRuby() {
57
69
rubyVM . addToImports ( imports ) ;
58
70
59
71
// 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.
61
77
wasi . setMemory ( instance . exports . memory ) ;
62
78
63
79
// Load our application into the virtual machine.
@@ -83,22 +99,43 @@ export default async function createRuby() {
83
99
84
100
return {
85
101
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
+ }
95
107
} ;
96
108
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
+ } ;
101
140
}
102
141
} ;
103
-
104
- export type Ruby = Awaited < ReturnType < typeof createRuby > > ;
0 commit comments