git ssb

0+

wanderer🌟 / wasm-persist



Tree: 4e096af3ebfb0c5d79f60581ec24ed4f444a312e

Files: 4e096af3ebfb0c5d79f60581ec24ed4f444a312e / injectGettersSetters.js

6773 bytesRaw
1const leb128 = require('leb128').unsigned
2const Pipe = require('buffer-pipe')
3const Iterator = require('wasm-json-toolkit').Iterator
4
5const EXTERNAL_KIND = {
6 'function': 0,
7 'table': 1,
8 'memory': 2,
9 'global': 3
10}
11
12module.exports = function prepare (wasm, include, symbol) {
13 let globalI64SetterIndex, globalI32SetterIndex, globalGetterIndex, funcSection
14 let numOfFuncs = 0
15 let numOfImports = 0
16 const addedCodeEntries = []
17 const globalsGetterSetters = []
18
19 const needExporting = {
20 'function': [],
21 'global': []
22 }
23
24 const it = new Iterator(wasm)
25
26 for (const section of it) {
27 if (section.type === 'type') {
28 const numOfTypes = section.count
29 // form: func, 1 param, i32, no return
30 const globalI32SetterType = Buffer.from([0x60, 0x01, 0x7f, 0x0])
31 // form: func, 2 param, i32, i32, no return
32 const globalI64SetterType = Buffer.from([0x60, 0x02, 0x7f, 0x7f, 0x0])
33 // form: func, 0 param, i32, 1 return
34 const globalGetterType = Buffer.from([0x60, 0x00, 0x1, 0x7f])
35 section.appendEntries([globalI32SetterType, globalI64SetterType, globalGetterType])
36
37 globalI32SetterIndex = leb128.encode(numOfTypes)
38 globalI64SetterIndex = leb128.encode(numOfTypes + 1)
39 globalGetterIndex = leb128.encode(numOfTypes + 2)
40 } else if (section.type === 'import') {
41 // parse the import section to build the function indexes
42 const json = section.toJSON()
43 numOfImports = json.entries.filter(entry => entry.kind === 'function').length
44 } else if (section.type === 'function') {
45 // mark functions to be exported
46 numOfFuncs = section.count
47 funcSection = section
48 needExporting['function'] = Array(section.count).fill(true)
49 } else if (section.type === 'table') {
50 needExporting['table'] = true && include.table
51 } else if (section.type === 'memory') {
52 needExporting['memory'] = true && include.memory
53 } else if (section.type === 'global') {
54 const json = section.toJSON()
55 const addedFuncs = []
56 if (!include.globals) {
57 include.globals = new Array(json.entries.length).fill(true)
58 }
59 for (const i in json.entries) {
60 const type = json.entries[i].type
61 const lebIndex = leb128.encode(i)
62 if (type.mutability && include.globals[i]) {
63 if (type.contentType === 'i32') {
64 globalsGetterSetters.push(type.contentType)
65 addedFuncs.push(globalGetterIndex)
66 addedFuncs.push(globalI32SetterIndex)
67 // getter
68 // size, local count, get_global, index, end
69 addedCodeEntries.push(Buffer.concat([
70 Buffer.from([0x03 + lebIndex.length, 0x00, 0x23]),
71 lebIndex,
72 Buffer.from([0x0b])
73 ]))
74 // setter
75 // size, local count, get_local, index , set_global, index, end
76 addedCodeEntries.push(Buffer.concat([
77 Buffer.from([0x05 + lebIndex.length, 0x00, 0x20, 0x0, 0x24]),
78 lebIndex,
79 Buffer.from([0x0b])
80 ]))
81 } else {
82 globalsGetterSetters.push(type.contentType)
83 addedFuncs.push(globalGetterIndex)
84 addedFuncs.push(globalGetterIndex)
85 addedFuncs.push(globalI64SetterIndex)
86 // 64 bit
87 // getter high
88 addedCodeEntries.push(Buffer.concat([
89 Buffer.from([0x07 + lebIndex.length, 0x00, 0x23]),
90 lebIndex,
91 Buffer.from([0x42, 0x20, 0x88, 0xa7, 0x0b])
92 ]))
93
94 // get low
95 addedCodeEntries.push(Buffer.concat([
96 Buffer.from([0x04 + lebIndex.length, 0x00, 0x23]),
97 lebIndex,
98 Buffer.from([0xa7, 0x0b])
99 ]))
100 // (set_global $b
101 // (i64.add
102 // (i64.shl (i64.extend_u/i32 (get_local 0)) (i64.const 32))
103 // (i64.extend_u/i32 (get_local 1))))
104 // setter
105 addedCodeEntries.push(Buffer.concat([
106 Buffer.from([0x0d + lebIndex.length, 0x00, 0x20, 0x01, 0xad, 0x42, 0x20, 0x86, 0x20, 0x00, 0xad, 0x7c, 0x24]),
107 lebIndex,
108 Buffer.from([0x0b])
109 ]))
110 }
111 }
112 }
113 funcSection.appendEntries(addedFuncs)
114 } else if (section.type === 'export') {
115 // export the memory
116 const addedExports = []
117 if (needExporting['memory']) {
118 const funcExp = generateFuncExport(`${symbol}memory`, 0, 'memory')
119 addedExports.push(funcExp)
120 }
121
122 // export the table
123 if (needExporting['table']) {
124 const funcExp = generateFuncExport(`${symbol}table`, 0, 'table')
125 addedExports.push(funcExp)
126 }
127
128 // export functions
129 const funcs = needExporting['function']
130 for (let index in funcs) {
131 index = Number(index)
132 const funcExp = generateFuncExport(`${symbol}func_${index + numOfImports}`, numOfImports + index, 'function')
133 addedExports.push(funcExp)
134 }
135
136 // export globals
137 let globalFuncIndex = 0
138 for (let index in globalsGetterSetters) {
139 const type = globalsGetterSetters[index]
140 const funcIndex = numOfImports + numOfFuncs + globalFuncIndex
141 if (type === 'i32') {
142 // getter
143 const getter = generateFuncExport(`${symbol}global_getter_${type}_${index}`, funcIndex, 'function')
144 addedExports.push(getter)
145
146 // setter
147 const setter = generateFuncExport(`${symbol}global_setter_${type}_${index}`, funcIndex + 1, 'function')
148 addedExports.push(setter)
149 globalFuncIndex += 2
150 } else {
151 // i64s
152 // setter high
153 const setterHigh = generateFuncExport(`${symbol}global_getter_${type}_${index}_high`, funcIndex, 'function')
154 addedExports.push(setterHigh)
155 // setter Low
156 const setterLow = generateFuncExport(`${symbol}global_getter_${type}_${index}_low`, funcIndex + 1, 'function')
157 addedExports.push(setterLow)
158 // getter
159 const getter = generateFuncExport(`${symbol}global_setter_${type}_${index}`, funcIndex + 2, 'function')
160 addedExports.push(getter)
161 globalFuncIndex += 3
162 }
163 }
164 section.appendEntries(addedExports)
165 } else if (section.type === 'code') {
166 section.appendEntries(addedCodeEntries)
167 }
168 }
169 return it.wasm
170}
171
172function generateFuncExport (name, index, type) {
173 const setterHigh = new Pipe()
174 const fieldString = Buffer.from(name)
175 leb128.write(fieldString.length, setterHigh)
176 setterHigh.write(fieldString)
177 setterHigh.write(Buffer.from([EXTERNAL_KIND[type]]))
178 leb128.write(index, setterHigh)
179 return setterHigh.buffer
180}
181

Built with git-ssb-web