git ssb

0+

wanderer🌟 / js-primea-wasm-container



Tree: 77b66a231e256f16677cb9764d1b82c32599005a

Files: 77b66a231e256f16677cb9764d1b82c32599005a / index.js

2892 bytesRaw
1const ReferanceMap = require('./referanceMap.js')
2
3module.exports = class WasmContainer {
4 /**
5 * The wasm container runs wasm code and provides a basic API for wasm
6 * interfaces for interacting with the exoInterface
7 * @param {object} exoInterface - the exoInterface instance
8 * @param {object} imports - a map of imports to expose to the wasm binary
9 */
10 constructor (exoInterface, imports) {
11 this.exoInterface = exoInterface
12 this.imports = imports
13 this.referanceMap = new ReferanceMap()
14 }
15
16 /**
17 * Runs the wasm VM given a message
18 * @param {object} message
19 * @returns {Promise} a promise that resolves once the compuation is finished
20 */
21 async run (message) {
22 /**
23 * Builds a import map with an array of given interfaces
24 */
25 const importMap = {}
26 for (const name in this.imports) {
27 importMap[name] = {}
28 const Import = this.imports[name]
29 const newInterface = new Import(this)
30 const props = Object.getOwnPropertyNames(Import.prototype)
31
32 // bind the methods to the correct 'this'
33 for (const prop of props) {
34 if (prop !== 'constructor') {
35 importMap[name][prop] = newInterface[prop].bind(newInterface)
36 }
37 }
38 }
39
40 const result = await WebAssembly.instantiate(this.exoInterface.state['/'].code, importMap)
41 this.instance = result.instance
42 // runs the wasm code
43 this.instance.exports.main()
44 return this.onDone()
45 }
46
47 /**
48 * returns a promise that resolves when the wasm instance is done running
49 * @returns {Promise}
50 */
51 async onDone () {
52 let prevOps
53 while (prevOps !== this._opsQueue) {
54 prevOps = this._opsQueue
55 await prevOps
56 }
57 this.referanceMap.clear()
58 }
59
60 /**
61 * Pushed an async operation to the a promise queue that
62 * @returns {Promise} the returned promise resolves in the order the intail
63 * operation was pushed to the queue
64 */
65 pushOpsQueue (promise) {
66 this._opsQueue = Promise.all([this._opsQueue, promise])
67 return this._opsQueue
68 }
69
70 /**
71 * executes a callback given an index in the exported callback container
72 * @param {integer} cb
73 * @param {*} val - a value to return to the callback function
74 */
75 execute (cb, val) {
76 this.instance.exports.table.get(cb)(val)
77 }
78
79 /**
80 * returns a section of memory from the wasm instance
81 * @param {integer} offset
82 * @param {integer} length
83 * @returns {Uint8Array}
84 */
85 getMemory (offset, length) {
86 return new Uint8Array(this.instance.exports.memory.buffer, offset, length)
87 }
88
89 /**
90 * creates the intail state for a wasm contract
91 * @param {ArrayBuffer} wasm - the wasm code
92 * @returns {Object}
93 */
94 static createState (wasm) {
95 if (!WebAssembly.validate(wasm)) {
96 throw new Error('invalid wasm binary')
97 }
98
99 return {
100 nonce: [0],
101 ports: {},
102 code: wasm
103 }
104 }
105}
106

Built with git-ssb-web