Commit ef2bd6aff34a889b871ba0df64660c209670a621
nit
Signed-off-by: wanderer <mjbecze@gmail.com>wanderer committed on 4/25/2018, 4:52:59 AM
Files changed
.travis.yml | ||
---|---|---|
@@ -1,0 +1,24 @@ | ||
1 … | +language: node_js | |
2 … | +node_js: | |
3 … | + - "9" | |
4 … | +env: | |
5 … | + global: | |
6 … | + - CXX=g++-4.8 | |
7 … | + matrix: | |
8 … | + - TEST_SUITE=test | |
9 … | +addons: | |
10 … | + apt: | |
11 … | + sources: | |
12 … | + - ubuntu-toolchain-r-test | |
13 … | + packages: | |
14 … | + - g++-4.8 | |
15 … | +matrix: | |
16 … | + fast_finish: true | |
17 … | + include: | |
18 … | + - os: linux | |
19 … | + node_js: "9" | |
20 … | + env: TEST_SUITE=coveralls | |
21 … | + - os: linux | |
22 … | + node_js: "9" | |
23 … | + env: TEST_SUITE=lint | |
24 … | +script: npm run $TEST_SUITE |
LICENSE | ||
---|---|---|
@@ -1,0 +1,373 @@ | ||
1 … | +Mozilla Public License Version 2.0 | |
2 … | +================================== | |
3 … | + | |
4 … | +1. Definitions | |
5 … | +-------------- | |
6 … | + | |
7 … | +1.1. "Contributor" | |
8 … | + means each individual or legal entity that creates, contributes to | |
9 … | + the creation of, or owns Covered Software. | |
10 … | + | |
11 … | +1.2. "Contributor Version" | |
12 … | + means the combination of the Contributions of others (if any) used | |
13 … | + by a Contributor and that particular Contributor's Contribution. | |
14 … | + | |
15 … | +1.3. "Contribution" | |
16 … | + means Covered Software of a particular Contributor. | |
17 … | + | |
18 … | +1.4. "Covered Software" | |
19 … | + means Source Code Form to which the initial Contributor has attached | |
20 … | + the notice in Exhibit A, the Executable Form of such Source Code | |
21 … | + Form, and Modifications of such Source Code Form, in each case | |
22 … | + including portions thereof. | |
23 … | + | |
24 … | +1.5. "Incompatible With Secondary Licenses" | |
25 … | + means | |
26 … | + | |
27 … | + (a) that the initial Contributor has attached the notice described | |
28 … | + in Exhibit B to the Covered Software; or | |
29 … | + | |
30 … | + (b) that the Covered Software was made available under the terms of | |
31 … | + version 1.1 or earlier of the License, but not also under the | |
32 … | + terms of a Secondary License. | |
33 … | + | |
34 … | +1.6. "Executable Form" | |
35 … | + means any form of the work other than Source Code Form. | |
36 … | + | |
37 … | +1.7. "Larger Work" | |
38 … | + means a work that combines Covered Software with other material, in | |
39 … | + a separate file or files, that is not Covered Software. | |
40 … | + | |
41 … | +1.8. "License" | |
42 … | + means this document. | |
43 … | + | |
44 … | +1.9. "Licensable" | |
45 … | + means having the right to grant, to the maximum extent possible, | |
46 … | + whether at the time of the initial grant or subsequently, any and | |
47 … | + all of the rights conveyed by this License. | |
48 … | + | |
49 … | +1.10. "Modifications" | |
50 … | + means any of the following: | |
51 … | + | |
52 … | + (a) any file in Source Code Form that results from an addition to, | |
53 … | + deletion from, or modification of the contents of Covered | |
54 … | + Software; or | |
55 … | + | |
56 … | + (b) any new file in Source Code Form that contains any Covered | |
57 … | + Software. | |
58 … | + | |
59 … | +1.11. "Patent Claims" of a Contributor | |
60 … | + means any patent claim(s), including without limitation, method, | |
61 … | + process, and apparatus claims, in any patent Licensable by such | |
62 … | + Contributor that would be infringed, but for the grant of the | |
63 … | + License, by the making, using, selling, offering for sale, having | |
64 … | + made, import, or transfer of either its Contributions or its | |
65 … | + Contributor Version. | |
66 … | + | |
67 … | +1.12. "Secondary License" | |
68 … | + means either the GNU General Public License, Version 2.0, the GNU | |
69 … | + Lesser General Public License, Version 2.1, the GNU Affero General | |
70 … | + Public License, Version 3.0, or any later versions of those | |
71 … | + licenses. | |
72 … | + | |
73 … | +1.13. "Source Code Form" | |
74 … | + means the form of the work preferred for making modifications. | |
75 … | + | |
76 … | +1.14. "You" (or "Your") | |
77 … | + means an individual or a legal entity exercising rights under this | |
78 … | + License. For legal entities, "You" includes any entity that | |
79 … | + controls, is controlled by, or is under common control with You. For | |
80 … | + purposes of this definition, "control" means (a) the power, direct | |
81 … | + or indirect, to cause the direction or management of such entity, | |
82 … | + whether by contract or otherwise, or (b) ownership of more than | |
83 … | + fifty percent (50%) of the outstanding shares or beneficial | |
84 … | + ownership of such entity. | |
85 … | + | |
86 … | +2. License Grants and Conditions | |
87 … | +-------------------------------- | |
88 … | + | |
89 … | +2.1. Grants | |
90 … | + | |
91 … | +Each Contributor hereby grants You a world-wide, royalty-free, | |
92 … | +non-exclusive license: | |
93 … | + | |
94 … | +(a) under intellectual property rights (other than patent or trademark) | |
95 … | + Licensable by such Contributor to use, reproduce, make available, | |
96 … | + modify, display, perform, distribute, and otherwise exploit its | |
97 … | + Contributions, either on an unmodified basis, with Modifications, or | |
98 … | + as part of a Larger Work; and | |
99 … | + | |
100 … | +(b) under Patent Claims of such Contributor to make, use, sell, offer | |
101 … | + for sale, have made, import, and otherwise transfer either its | |
102 … | + Contributions or its Contributor Version. | |
103 … | + | |
104 … | +2.2. Effective Date | |
105 … | + | |
106 … | +The licenses granted in Section 2.1 with respect to any Contribution | |
107 … | +become effective for each Contribution on the date the Contributor first | |
108 … | +distributes such Contribution. | |
109 … | + | |
110 … | +2.3. Limitations on Grant Scope | |
111 … | + | |
112 … | +The licenses granted in this Section 2 are the only rights granted under | |
113 … | +this License. No additional rights or licenses will be implied from the | |
114 … | +distribution or licensing of Covered Software under this License. | |
115 … | +Notwithstanding Section 2.1(b) above, no patent license is granted by a | |
116 … | +Contributor: | |
117 … | + | |
118 … | +(a) for any code that a Contributor has removed from Covered Software; | |
119 … | + or | |
120 … | + | |
121 … | +(b) for infringements caused by: (i) Your and any other third party's | |
122 … | + modifications of Covered Software, or (ii) the combination of its | |
123 … | + Contributions with other software (except as part of its Contributor | |
124 … | + Version); or | |
125 … | + | |
126 … | +(c) under Patent Claims infringed by Covered Software in the absence of | |
127 … | + its Contributions. | |
128 … | + | |
129 … | +This License does not grant any rights in the trademarks, service marks, | |
130 … | +or logos of any Contributor (except as may be necessary to comply with | |
131 … | +the notice requirements in Section 3.4). | |
132 … | + | |
133 … | +2.4. Subsequent Licenses | |
134 … | + | |
135 … | +No Contributor makes additional grants as a result of Your choice to | |
136 … | +distribute the Covered Software under a subsequent version of this | |
137 … | +License (see Section 10.2) or under the terms of a Secondary License (if | |
138 … | +permitted under the terms of Section 3.3). | |
139 … | + | |
140 … | +2.5. Representation | |
141 … | + | |
142 … | +Each Contributor represents that the Contributor believes its | |
143 … | +Contributions are its original creation(s) or it has sufficient rights | |
144 … | +to grant the rights to its Contributions conveyed by this License. | |
145 … | + | |
146 … | +2.6. Fair Use | |
147 … | + | |
148 … | +This License is not intended to limit any rights You have under | |
149 … | +applicable copyright doctrines of fair use, fair dealing, or other | |
150 … | +equivalents. | |
151 … | + | |
152 … | +2.7. Conditions | |
153 … | + | |
154 … | +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted | |
155 … | +in Section 2.1. | |
156 … | + | |
157 … | +3. Responsibilities | |
158 … | +------------------- | |
159 … | + | |
160 … | +3.1. Distribution of Source Form | |
161 … | + | |
162 … | +All distribution of Covered Software in Source Code Form, including any | |
163 … | +Modifications that You create or to which You contribute, must be under | |
164 … | +the terms of this License. You must inform recipients that the Source | |
165 … | +Code Form of the Covered Software is governed by the terms of this | |
166 … | +License, and how they can obtain a copy of this License. You may not | |
167 … | +attempt to alter or restrict the recipients' rights in the Source Code | |
168 … | +Form. | |
169 … | + | |
170 … | +3.2. Distribution of Executable Form | |
171 … | + | |
172 … | +If You distribute Covered Software in Executable Form then: | |
173 … | + | |
174 … | +(a) such Covered Software must also be made available in Source Code | |
175 … | + Form, as described in Section 3.1, and You must inform recipients of | |
176 … | + the Executable Form how they can obtain a copy of such Source Code | |
177 … | + Form by reasonable means in a timely manner, at a charge no more | |
178 … | + than the cost of distribution to the recipient; and | |
179 … | + | |
180 … | +(b) You may distribute such Executable Form under the terms of this | |
181 … | + License, or sublicense it under different terms, provided that the | |
182 … | + license for the Executable Form does not attempt to limit or alter | |
183 … | + the recipients' rights in the Source Code Form under this License. | |
184 … | + | |
185 … | +3.3. Distribution of a Larger Work | |
186 … | + | |
187 … | +You may create and distribute a Larger Work under terms of Your choice, | |
188 … | +provided that You also comply with the requirements of this License for | |
189 … | +the Covered Software. If the Larger Work is a combination of Covered | |
190 … | +Software with a work governed by one or more Secondary Licenses, and the | |
191 … | +Covered Software is not Incompatible With Secondary Licenses, this | |
192 … | +License permits You to additionally distribute such Covered Software | |
193 … | +under the terms of such Secondary License(s), so that the recipient of | |
194 … | +the Larger Work may, at their option, further distribute the Covered | |
195 … | +Software under the terms of either this License or such Secondary | |
196 … | +License(s). | |
197 … | + | |
198 … | +3.4. Notices | |
199 … | + | |
200 … | +You may not remove or alter the substance of any license notices | |
201 … | +(including copyright notices, patent notices, disclaimers of warranty, | |
202 … | +or limitations of liability) contained within the Source Code Form of | |
203 … | +the Covered Software, except that You may alter any license notices to | |
204 … | +the extent required to remedy known factual inaccuracies. | |
205 … | + | |
206 … | +3.5. Application of Additional Terms | |
207 … | + | |
208 … | +You may choose to offer, and to charge a fee for, warranty, support, | |
209 … | +indemnity or liability obligations to one or more recipients of Covered | |
210 … | +Software. However, You may do so only on Your own behalf, and not on | |
211 … | +behalf of any Contributor. You must make it absolutely clear that any | |
212 … | +such warranty, support, indemnity, or liability obligation is offered by | |
213 … | +You alone, and You hereby agree to indemnify every Contributor for any | |
214 … | +liability incurred by such Contributor as a result of warranty, support, | |
215 … | +indemnity or liability terms You offer. You may include additional | |
216 … | +disclaimers of warranty and limitations of liability specific to any | |
217 … | +jurisdiction. | |
218 … | + | |
219 … | +4. Inability to Comply Due to Statute or Regulation | |
220 … | +--------------------------------------------------- | |
221 … | + | |
222 … | +If it is impossible for You to comply with any of the terms of this | |
223 … | +License with respect to some or all of the Covered Software due to | |
224 … | +statute, judicial order, or regulation then You must: (a) comply with | |
225 … | +the terms of this License to the maximum extent possible; and (b) | |
226 … | +describe the limitations and the code they affect. Such description must | |
227 … | +be placed in a text file included with all distributions of the Covered | |
228 … | +Software under this License. Except to the extent prohibited by statute | |
229 … | +or regulation, such description must be sufficiently detailed for a | |
230 … | +recipient of ordinary skill to be able to understand it. | |
231 … | + | |
232 … | +5. Termination | |
233 … | +-------------- | |
234 … | + | |
235 … | +5.1. The rights granted under this License will terminate automatically | |
236 … | +if You fail to comply with any of its terms. However, if You become | |
237 … | +compliant, then the rights granted under this License from a particular | |
238 … | +Contributor are reinstated (a) provisionally, unless and until such | |
239 … | +Contributor explicitly and finally terminates Your grants, and (b) on an | |
240 … | +ongoing basis, if such Contributor fails to notify You of the | |
241 … | +non-compliance by some reasonable means prior to 60 days after You have | |
242 … | +come back into compliance. Moreover, Your grants from a particular | |
243 … | +Contributor are reinstated on an ongoing basis if such Contributor | |
244 … | +notifies You of the non-compliance by some reasonable means, this is the | |
245 … | +first time You have received notice of non-compliance with this License | |
246 … | +from such Contributor, and You become compliant prior to 30 days after | |
247 … | +Your receipt of the notice. | |
248 … | + | |
249 … | +5.2. If You initiate litigation against any entity by asserting a patent | |
250 … | +infringement claim (excluding declaratory judgment actions, | |
251 … | +counter-claims, and cross-claims) alleging that a Contributor Version | |
252 … | +directly or indirectly infringes any patent, then the rights granted to | |
253 … | +You by any and all Contributors for the Covered Software under Section | |
254 … | +2.1 of this License shall terminate. | |
255 … | + | |
256 … | +5.3. In the event of termination under Sections 5.1 or 5.2 above, all | |
257 … | +end user license agreements (excluding distributors and resellers) which | |
258 … | +have been validly granted by You or Your distributors under this License | |
259 … | +prior to termination shall survive termination. | |
260 … | + | |
261 … | +************************************************************************ | |
262 … | +* * | |
263 … | +* 6. Disclaimer of Warranty * | |
264 … | +* ------------------------- * | |
265 … | +* * | |
266 … | +* Covered Software is provided under this License on an "as is" * | |
267 … | +* basis, without warranty of any kind, either expressed, implied, or * | |
268 … | +* statutory, including, without limitation, warranties that the * | |
269 … | +* Covered Software is free of defects, merchantable, fit for a * | |
270 … | +* particular purpose or non-infringing. The entire risk as to the * | |
271 … | +* quality and performance of the Covered Software is with You. * | |
272 … | +* Should any Covered Software prove defective in any respect, You * | |
273 … | +* (not any Contributor) assume the cost of any necessary servicing, * | |
274 … | +* repair, or correction. This disclaimer of warranty constitutes an * | |
275 … | +* essential part of this License. No use of any Covered Software is * | |
276 … | +* authorized under this License except under this disclaimer. * | |
277 … | +* * | |
278 … | +************************************************************************ | |
279 … | + | |
280 … | +************************************************************************ | |
281 … | +* * | |
282 … | +* 7. Limitation of Liability * | |
283 … | +* -------------------------- * | |
284 … | +* * | |
285 … | +* Under no circumstances and under no legal theory, whether tort * | |
286 … | +* (including negligence), contract, or otherwise, shall any * | |
287 … | +* Contributor, or anyone who distributes Covered Software as * | |
288 … | +* permitted above, be liable to You for any direct, indirect, * | |
289 … | +* special, incidental, or consequential damages of any character * | |
290 … | +* including, without limitation, damages for lost profits, loss of * | |
291 … | +* goodwill, work stoppage, computer failure or malfunction, or any * | |
292 … | +* and all other commercial damages or losses, even if such party * | |
293 … | +* shall have been informed of the possibility of such damages. This * | |
294 … | +* limitation of liability shall not apply to liability for death or * | |
295 … | +* personal injury resulting from such party's negligence to the * | |
296 … | +* extent applicable law prohibits such limitation. Some * | |
297 … | +* jurisdictions do not allow the exclusion or limitation of * | |
298 … | +* incidental or consequential damages, so this exclusion and * | |
299 … | +* limitation may not apply to You. * | |
300 … | +* * | |
301 … | +************************************************************************ | |
302 … | + | |
303 … | +8. Litigation | |
304 … | +------------- | |
305 … | + | |
306 … | +Any litigation relating to this License may be brought only in the | |
307 … | +courts of a jurisdiction where the defendant maintains its principal | |
308 … | +place of business and such litigation shall be governed by laws of that | |
309 … | +jurisdiction, without reference to its conflict-of-law provisions. | |
310 … | +Nothing in this Section shall prevent a party's ability to bring | |
311 … | +cross-claims or counter-claims. | |
312 … | + | |
313 … | +9. Miscellaneous | |
314 … | +---------------- | |
315 … | + | |
316 … | +This License represents the complete agreement concerning the subject | |
317 … | +matter hereof. If any provision of this License is held to be | |
318 … | +unenforceable, such provision shall be reformed only to the extent | |
319 … | +necessary to make it enforceable. Any law or regulation which provides | |
320 … | +that the language of a contract shall be construed against the drafter | |
321 … | +shall not be used to construe this License against a Contributor. | |
322 … | + | |
323 … | +10. Versions of the License | |
324 … | +--------------------------- | |
325 … | + | |
326 … | +10.1. New Versions | |
327 … | + | |
328 … | +Mozilla Foundation is the license steward. Except as provided in Section | |
329 … | +10.3, no one other than the license steward has the right to modify or | |
330 … | +publish new versions of this License. Each version will be given a | |
331 … | +distinguishing version number. | |
332 … | + | |
333 … | +10.2. Effect of New Versions | |
334 … | + | |
335 … | +You may distribute the Covered Software under the terms of the version | |
336 … | +of the License under which You originally received the Covered Software, | |
337 … | +or under the terms of any subsequent version published by the license | |
338 … | +steward. | |
339 … | + | |
340 … | +10.3. Modified Versions | |
341 … | + | |
342 … | +If you create software not governed by this License, and you want to | |
343 … | +create a new license for such software, you may create and use a | |
344 … | +modified version of this License if you rename the license and remove | |
345 … | +any references to the name of the license steward (except to note that | |
346 … | +such modified license differs from this License). | |
347 … | + | |
348 … | +10.4. Distributing Source Code Form that is Incompatible With Secondary | |
349 … | +Licenses | |
350 … | + | |
351 … | +If You choose to distribute Source Code Form that is Incompatible With | |
352 … | +Secondary Licenses under the terms of this version of the License, the | |
353 … | +notice described in Exhibit B of this License must be attached. | |
354 … | + | |
355 … | +Exhibit A - Source Code Form License Notice | |
356 … | +------------------------------------------- | |
357 … | + | |
358 … | + This Source Code Form is subject to the terms of the Mozilla Public | |
359 … | + License, v. 2.0. If a copy of the MPL was not distributed with this | |
360 … | + file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
361 … | + | |
362 … | +If it is not possible or desirable to put the notice in a particular | |
363 … | +file, then You may include the notice in a location (such as a LICENSE | |
364 … | +file in a relevant directory) where a recipient would be likely to look | |
365 … | +for such a notice. | |
366 … | + | |
367 … | +You may add additional accurate notices of copyright ownership. | |
368 … | + | |
369 … | +Exhibit B - "Incompatible With Secondary Licenses" Notice | |
370 … | +--------------------------------------------------------- | |
371 … | + | |
372 … | + This Source Code Form is "Incompatible With Secondary Licenses", as | |
373 … | + defined by the Mozilla Public License, v. 2.0. |
README.md | ||
---|---|---|
@@ -1,0 +1,46 @@ | ||
1 … | +# SYNOPSIS | |
2 … | +[![NPM Package](https://img.shields.io/npm/v/wasm-persist.svg?style=flat-square)](https://www.npmjs.org/package/wasm-persist) | |
3 … | +[![Build Status](https://img.shields.io/travis/dfinity/wasm-persist.svg?branch=master&style=flat-square)](https://travis-ci.org/dfinity/wasm-persist) | |
4 … | +[![Coverage Status](https://img.shields.io/coveralls/dfinity/wasm-persist.svg?style=flat-square)](https://coveralls.io/r/dfinity/wasm-persist) | |
5 … | + | |
6 … | +[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) | |
7 … | + | |
8 … | +This allows you to hibernate a WebAssembly instance and later start it up again | |
9 … | +at the exact place you left off | |
10 … | + | |
11 … | +# INSTALL | |
12 … | +`npm install wasm-persist` | |
13 … | + | |
14 … | +# USAGE | |
15 … | + | |
16 … | +```javascript | |
17 … | +const persist = require('wasm-persist') | |
18 … | +... | |
19 … | +wasm = persit.prepare(wasm) | |
20 … | +const {instance} = await WebAssembly.instantiate(wasm) | |
21 … | +// call some exported functions on your instance | |
22 … | +// then when you are done | |
23 … | +const state = persit.hibernate(instance) | |
24 … | + | |
25 … | +... | |
26 … | + | |
27 … | +// later you can revive the wasm instance | |
28 … | +const {instance} = await WebAssembly.instantiate(wasm) | |
29 … | +// just call persist.resume with the old state | |
30 … | +persit.resume(instance, state) | |
31 … | +``` | |
32 … | +# DESCIPTION | |
33 … | +The Idea for wasm-perist came from [orthongal persistance](https://en.wikipedia.org/wiki/Persistence_(computer_science)#Orthogonal_or_transparent_persistence) | |
34 … | +wasm-persist injects getter and setter function for each global and exports the | |
35 … | +memory and table if they exist. Hibernate calls the getters and creates an Object | |
36 … | +that contains the memory (as a typedArray) the globals and the function table. | |
37 … | +Resume does the opposite and calls the setters for the globals and updates the | |
38 … | +memory and the table. Forgein function on the table are not handled currently. | |
39 … | + | |
40 … | +# API | |
41 … | +[./docs/](./docs/index.md) | |
42 … | + | |
43 … | +# LICENSE | |
44 … | +[MPL-2.0][LICENSE] | |
45 … | + | |
46 … | +[LICENSE]: https://tldrlegal.com/license/mozilla-public-license-2.0-(mpl-2) |
docs/index.md | ||
---|---|---|
@@ -1,0 +1,62 @@ | ||
1 … | +<!-- Generated by documentation.js. Update this documentation by updating the source code. --> | |
2 … | + | |
3 … | +### Table of Contents | |
4 … | + | |
5 … | +- [prepare][1] | |
6 … | +- [hibernate][2] | |
7 … | +- [resume][3] | |
8 … | + | |
9 … | +## prepare | |
10 … | + | |
11 … | +Prepares a binary by injecting getter and setter function for memory, globals and tables. | |
12 … | + | |
13 … | +**Parameters** | |
14 … | + | |
15 … | +- `binary` **[ArrayBuffer][4]** a wasm binary | |
16 … | +- `include` **[Object][5]** (optional, default `{memory:true,table:true}`) | |
17 … | + - `include.memory` **[Boolean][6]** whether or not to included memory (optional, default `true`) | |
18 … | + - `include.table` **[Boolean][6]** whether or not to included the function table (optional, default `true`) | |
19 … | + - `include.globals` **[Array][7]<[Boolean][6]>** whether or not to | |
20 … | + included a given global. Each index in the array stands for a global index. | |
21 … | + Indexes that are set to false or left undefined will not be persisted. By | |
22 … | + default all globals are persisted. (optional, default `Array.<true>`) | |
23 … | +- `symbol` **[String][8]** a sting used to prefix the injected setter and getter functions (optional, default `'_'`) | |
24 … | + | |
25 … | +Returns **[ArrayBuffer][4]** the resulting wasm binary | |
26 … | + | |
27 … | +## hibernate | |
28 … | + | |
29 … | +Given a wasm Instance this will produce an Object containing the current state of | |
30 … | +the instance | |
31 … | + | |
32 … | +**Parameters** | |
33 … | + | |
34 … | +- `instance` **Webassembly.Instance** | |
35 … | +- `symbol` **[String][8]** the symbol that will be used to find the injected functions (optional, default `'_'`) | |
36 … | + | |
37 … | +Returns **[Object][5]** the state of the wasm instance | |
38 … | + | |
39 … | +## resume | |
40 … | + | |
41 … | +resumes a prevously hibranted webassembly instance | |
42 … | + | |
43 … | +**Parameters** | |
44 … | + | |
45 … | +- `instance` **WebAssemby.Instance** | |
46 … | +- `state` **[Object][5]** the pervous state of the wasm instance | |
47 … | + | |
48 … | +[1]: #prepare | |
49 … | + | |
50 … | +[2]: #hibernate | |
51 … | + | |
52 … | +[3]: #resume | |
53 … | + | |
54 … | +[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer | |
55 … | + | |
56 … | +[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object | |
57 … | + | |
58 … | +[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean | |
59 … | + | |
60 … | +[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array | |
61 … | + | |
62 … | +[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String |
index.js | ||
---|---|---|
@@ -1,0 +1,108 @@ | ||
1 … | +const inject = require('./injectGettersSetters.js') | |
2 … | + | |
3 … | +/** | |
4 … | + * Prepares a binary by injecting getter and setter function for memory, globals and tables. | |
5 … | + * @param {ArrayBuffer} binary - a wasm binary | |
6 … | + * @param {Object} include | |
7 … | + * @param {Boolean} [include.memory=true] - whether or not to included memory | |
8 … | + * @param {Boolean} [include.table=true] - whether or not to included the function table | |
9 … | + * @param {Array.<Boolean>} [include.globals=Array.<true>] - whether or not to | |
10 … | + * included a given global. Each index in the array stands for a global index. | |
11 … | + * Indexes that are set to false or left undefined will not be persisted. By | |
12 … | + * default all globals are persisted. | |
13 … | + * @param {String} [symbol = '_'] - a sting used to prefix the injected setter and getter functions | |
14 … | + * @return {ArrayBuffer} the resulting wasm binary | |
15 … | + */ | |
16 … | +function prepare (binary, include = {memory: true, table: true}, symbol = '_') { | |
17 … | + return inject(binary, include, symbol) | |
18 … | +} | |
19 … | + | |
20 … | +/** | |
21 … | + * Given a wasm Instance this will produce an Object containing the current state of | |
22 … | + * the instance | |
23 … | + * @param {Webassembly.Instance} instance | |
24 … | + * @param {String} symbol - the symbol that will be used to find the injected functions | |
25 … | + * @returns {Object} the state of the wasm instance | |
26 … | + */ | |
27 … | +function hibernate (instance, symbol = '_') { | |
28 … | + const json = { | |
29 … | + globals: [], | |
30 … | + table: [], | |
31 … | + symbol | |
32 … | + } | |
33 … | + for (const key in instance.exports) { | |
34 … | + const val = instance.exports[key] | |
35 … | + if (key.startsWith(symbol)) { | |
36 … | + const keyElems = key.slice(symbol.length).split('_') | |
37 … | + // save the memory | |
38 … | + if (val instanceof WebAssembly.Memory) { | |
39 … | + json.memory = new Uint32Array(val.buffer) | |
40 … | + } else if (val instanceof WebAssembly.Table) { | |
41 … | + // mark the tables, (do something for external function?) | |
42 … | + // the external functions should have a callback | |
43 … | + for (let i = 0; i < val.length; i++) { | |
44 … | + const func = val.get(i) | |
45 … | + if (func === instance.exports[`${symbol}func_${func.name}`]) { | |
46 … | + json.table.push(func.name) | |
47 … | + } | |
48 … | + } | |
49 … | + } else if (keyElems[0] === 'global' && keyElems[1] === 'getter') { | |
50 … | + // save the globals | |
51 … | + const last = keyElems.pop() | |
52 … | + if (last === 'high') { | |
53 … | + json.globals.push([instance.exports[key]()]) | |
54 … | + } else if (last === 'low') { | |
55 … | + json.globals[json.globals.length - 1].push(instance.exports[key]()) | |
56 … | + } else { | |
57 … | + json.globals.push(instance.exports[key]()) | |
58 … | + } | |
59 … | + } | |
60 … | + } | |
61 … | + } | |
62 … | + instance.__hibrenated = true | |
63 … | + return json | |
64 … | +} | |
65 … | + | |
66 … | +/** | |
67 … | + * resumes a prevously hibranted webassembly instance | |
68 … | + * @param {WebAssemby.Instance} instance | |
69 … | + * @param {Object} state - the pervous state of the wasm instance | |
70 … | + * @retrun {WebAssembly.Instance} | |
71 … | + */ | |
72 … | +function resume (instance, state) { | |
73 … | + if (instance.__hibrenated) { | |
74 … | + instance.__hibrenated = false | |
75 … | + } else { | |
76 … | + // initailize memory | |
77 … | + const mem = instance.exports[`${state.symbol}memory`] | |
78 … | + if (mem) { | |
79 … | + // console.log(mem.length) | |
80 … | + (new Uint32Array(mem.buffer)).set(state.memory, 0) | |
81 … | + } | |
82 … | + | |
83 … | + // initailize table | |
84 … | + if (instance.exports._table) { | |
85 … | + for (const index in state.table) { | |
86 … | + const funcIndex = state.table[index] | |
87 … | + instance.exports._table.set(index, instance.exports[`${state.symbol}func_${funcIndex}`]) | |
88 … | + } | |
89 … | + } | |
90 … | + | |
91 … | + // intialize globals | |
92 … | + for (const index in state.globals) { | |
93 … | + const val = state.globals[index] | |
94 … | + if (Array.isArray(val)) { | |
95 … | + instance.exports[`${state.symbol}global_setter_i64_${index}`](val[1], val[0]) | |
96 … | + } else { | |
97 … | + instance.exports[`${state.symbol}global_setter_i32_${index}`](val) | |
98 … | + } | |
99 … | + } | |
100 … | + } | |
101 … | + return instance | |
102 … | +} | |
103 … | + | |
104 … | +module.exports = { | |
105 … | + prepare, | |
106 … | + hibernate, | |
107 … | + resume | |
108 … | +} |
injectGettersSetters.js | |||
---|---|---|---|
@@ -1,0 +1,180 @@ | |||
1 … | +const leb128 = require('leb128').unsigned | ||
2 … | +const Pipe = require('buffer-pipe') | ||
3 … | +const Iterator = require('wasm-json-toolkit').Iterator | ||
4 … | + | ||
5 … | +const EXTERNAL_KIND = { | ||
6 … | + 'function': 0, | ||
7 … | + 'table': 1, | ||
8 … | + 'memory': 2, | ||
9 … | + 'global': 3 | ||
10 … | +} | ||
11 … | + | ||
12 … | +module.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 … | + | ||
172 … | +function 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 … | +} |
package-lock.json | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 0 bytes New file size: 331017 bytes |
package.json | ||
---|---|---|
@@ -1,0 +1,40 @@ | ||
1 … | +{ | |
2 … | + "name": "wasm-persist", | |
3 … | + "version": "0.0.0", | |
4 … | + "description": "a JS module for creating orthogonal persistent WebAssembly instances", | |
5 … | + "main": "index.js", | |
6 … | + "scripts": { | |
7 … | + "coveralls": "npm run coverage && nyc report --reporter=text-lcov | coveralls", | |
8 … | + "coverage": "nyc npm test", | |
9 … | + "lint": "standard", | |
10 … | + "test": "node ./tests/index.js", | |
11 … | + "build:docs": "documentation build --github -f md ./index.js > ./docs/index.md" | |
12 … | + }, | |
13 … | + "keywords": [ | |
14 … | + "WebAssembly", | |
15 … | + "wasm" | |
16 … | + ], | |
17 … | + "author": "mjbecze <mjbecze@gmail.com>", | |
18 … | + "license": "MPL-2.0", | |
19 … | + "dependencies": { | |
20 … | + "buffer-pipe": "0.0.2", | |
21 … | + "leb128": "0.0.4", | |
22 … | + "wasm-json-toolkit": "^0.3.0" | |
23 … | + }, | |
24 … | + "devDependencies": { | |
25 … | + "coveralls": "^3.0.0", | |
26 … | + "documentation": "^6.2.0", | |
27 … | + "nyc": "^11.6.0", | |
28 … | + "standard": "^11.0.1", | |
29 … | + "tape": "^4.9.0", | |
30 … | + "wabt": "^1.0.0" | |
31 … | + }, | |
32 … | + "repository": { | |
33 … | + "type": "git", | |
34 … | + "url": "git@github.com:dfinity/wasm-persist.git" | |
35 … | + }, | |
36 … | + "bugs": { | |
37 … | + "url": "https://github.com/dfinity/wasm-persist/issues" | |
38 … | + }, | |
39 … | + "homepage": "https://github.com/dfinity/wasm-persist" | |
40 … | +} |
tests/index.js | ||
---|---|---|
@@ -1,0 +1,214 @@ | ||
1 … | +const fs = require('fs') | |
2 … | +const tape = require('tape') | |
3 … | +const persit = require('../') | |
4 … | + | |
5 … | +tape('empty', async t => { | |
6 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/empty.wasm`) | |
7 … | + wasm = persit.prepare(wasm) | |
8 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
9 … | + const json = persit.hibernate(wasmInstance.instance) | |
10 … | + persit.resume(wasmInstance.instance, json) | |
11 … | + t.deepEquals(json, {globals: [], table: [], symbol: '_'}) | |
12 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 0) | |
13 … | + | |
14 … | + t.end() | |
15 … | +}) | |
16 … | + | |
17 … | +tape('custom', async t => { | |
18 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/customSections.wasm`) | |
19 … | + wasm = persit.prepare(wasm) | |
20 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
21 … | + const json = persit.hibernate(wasmInstance.instance) | |
22 … | + persit.resume(wasmInstance.instance, json) | |
23 … | + t.deepEquals(json, {globals: [], table: [], symbol: '_'}) | |
24 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 0) | |
25 … | + | |
26 … | + t.end() | |
27 … | +}) | |
28 … | + | |
29 … | +tape('single type section', async t => { | |
30 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleType.wasm`) | |
31 … | + wasm = persit.prepare(wasm) | |
32 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
33 … | + const json = persit.hibernate(wasmInstance.instance) | |
34 … | + t.deepEquals(json, {globals: [], table: [], symbol: '_'}) | |
35 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 0) | |
36 … | + | |
37 … | + t.end() | |
38 … | +}) | |
39 … | + | |
40 … | +tape('single import section', async t => { | |
41 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleImport.wasm`) | |
42 … | + wasm = persit.prepare(wasm) | |
43 … | + const wasmInstance = await WebAssembly.instantiate(wasm, {foo: {bar () {}}}) | |
44 … | + const json = persit.hibernate(wasmInstance.instance) | |
45 … | + t.deepEquals(json, {globals: [], table: [], symbol: '_'}) | |
46 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 0) | |
47 … | + | |
48 … | + t.end() | |
49 … | +}) | |
50 … | + | |
51 … | +tape('single function', async t => { | |
52 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleFunction.wasm`) | |
53 … | + wasm = persit.prepare(wasm) | |
54 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
55 … | + const json = persit.hibernate(wasmInstance.instance) | |
56 … | + t.deepEquals(json, {globals: [], table: [], symbol: '_'}) | |
57 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 2) | |
58 … | + | |
59 … | + t.end() | |
60 … | +}) | |
61 … | + | |
62 … | +tape('single table', async t => { | |
63 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleTable.wasm`) | |
64 … | + wasm = persit.prepare(wasm) | |
65 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
66 … | + const json = persit.hibernate(wasmInstance.instance) | |
67 … | + t.deepEquals(json, {globals: [], table: ['0'], symbol: '_'}) | |
68 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 3) | |
69 … | + | |
70 … | + t.end() | |
71 … | +}) | |
72 … | + | |
73 … | +tape('single table with foregn fuction', async t => { | |
74 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleTable.wasm`) | |
75 … | + wasm = persit.prepare(wasm) | |
76 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
77 … | + const wasmInstance2 = await WebAssembly.instantiate(wasm) | |
78 … | + wasmInstance.instance.exports._table.set(0, wasmInstance2.instance.exports.e) | |
79 … | + const json = persit.hibernate(wasmInstance.instance) | |
80 … | + t.deepEquals(json, {globals: [], table: [], symbol: '_'}) | |
81 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 3) | |
82 … | + | |
83 … | + t.end() | |
84 … | +}) | |
85 … | + | |
86 … | +tape('single table resume', async t => { | |
87 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleTable.wasm`) | |
88 … | + wasm = persit.prepare(wasm) | |
89 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
90 … | + const json = persit.hibernate(wasmInstance.instance) | |
91 … | + | |
92 … | + const wasmInstance2 = await WebAssembly.instantiate(wasm) | |
93 … | + persit.resume(wasmInstance2.instance, json) | |
94 … | + const json2 = persit.hibernate(wasmInstance2.instance) | |
95 … | + t.deepEquals(json, json2) | |
96 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 3) | |
97 … | + | |
98 … | + t.end() | |
99 … | +}) | |
100 … | + | |
101 … | +tape('single memory', async t => { | |
102 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleMemory.wasm`) | |
103 … | + wasm = persit.prepare(wasm) | |
104 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
105 … | + const json = persit.hibernate(wasmInstance.instance) | |
106 … | + t.equals(json.memory.length, 16384) | |
107 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 3) | |
108 … | + | |
109 … | + t.end() | |
110 … | +}) | |
111 … | + | |
112 … | +tape('skipping memory', async t => { | |
113 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleMemory.wasm`) | |
114 … | + wasm = persit.prepare(wasm, '_', {memory: false}) | |
115 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
116 … | + const json = persit.hibernate(wasmInstance.instance) | |
117 … | + t.equals(json.memory, undefined) | |
118 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 2) | |
119 … | + | |
120 … | + t.end() | |
121 … | +}) | |
122 … | + | |
123 … | +tape('resuming memory', async t => { | |
124 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleMemory.wasm`) | |
125 … | + wasm = persit.prepare(wasm) | |
126 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
127 … | + const json = persit.hibernate(wasmInstance.instance) | |
128 … | + | |
129 … | + const wasmInstance2 = await WebAssembly.instantiate(wasm) | |
130 … | + persit.resume(wasmInstance2.instance, json) | |
131 … | + const json2 = persit.hibernate(wasmInstance2.instance) | |
132 … | + t.deepEquals(json, json2) | |
133 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 3) | |
134 … | + | |
135 … | + t.end() | |
136 … | +}) | |
137 … | + | |
138 … | +tape('single i32 global', async t => { | |
139 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleI32Global.wasm`) | |
140 … | + wasm = persit.prepare(wasm) | |
141 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
142 … | + const json = persit.hibernate(wasmInstance.instance) | |
143 … | + t.deepEquals(json, {globals: [-2], table: [], symbol: '_'}) | |
144 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 4) | |
145 … | + | |
146 … | + t.end() | |
147 … | +}) | |
148 … | + | |
149 … | +tape('single i32 global', async t => { | |
150 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleI32Global.wasm`) | |
151 … | + wasm = persit.prepare(wasm) | |
152 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
153 … | + const json = persit.hibernate(wasmInstance.instance) | |
154 … | + t.deepEquals(json, {globals: [-2], table: [], symbol: '_'}) | |
155 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 4) | |
156 … | + | |
157 … | + json.globals[0] = 8 | |
158 … | + const wasmInstance2 = await WebAssembly.instantiate(wasm) | |
159 … | + persit.resume(wasmInstance2.instance, json) | |
160 … | + const json2 = persit.hibernate(wasmInstance2.instance) | |
161 … | + t.deepEquals(json2, {globals: [8], table: [], symbol: '_'}) | |
162 … | + | |
163 … | + t.end() | |
164 … | +}) | |
165 … | + | |
166 … | +tape('single i64 global', async t => { | |
167 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleI64Global.wasm`) | |
168 … | + wasm = persit.prepare(wasm) | |
169 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
170 … | + const json = persit.hibernate(wasmInstance.instance) | |
171 … | + t.deepEquals(json, {globals: [[-1, -2]], table: [], symbol: '_'}) | |
172 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 5) | |
173 … | + | |
174 … | + t.end() | |
175 … | +}) | |
176 … | + | |
177 … | +tape('resuming i64 global', async t => { | |
178 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/singleI64Global.wasm`) | |
179 … | + wasm = persit.prepare(wasm) | |
180 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
181 … | + const json = {globals: [[99, 97]], table: [], symbol: '_'} | |
182 … | + persit.resume(wasmInstance.instance, json) | |
183 … | + const json2 = persit.hibernate(wasmInstance.instance) | |
184 … | + t.deepEquals(json, json2) | |
185 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 5) | |
186 … | + | |
187 … | + t.end() | |
188 … | +}) | |
189 … | + | |
190 … | +tape('skipping some globals', async t => { | |
191 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/doubleGlobals.wasm`) | |
192 … | + wasm = persit.prepare(wasm, { | |
193 … | + globals: [true] | |
194 … | + }, '_@') | |
195 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
196 … | + const json = persit.hibernate(wasmInstance.instance, '_@') | |
197 … | + t.deepEquals(json, {globals: [-2], table: [], symbol: '_@'}) | |
198 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 4) | |
199 … | + | |
200 … | + t.end() | |
201 … | +}) | |
202 … | + | |
203 … | +tape('skipping some globals', async t => { | |
204 … | + let wasm = fs.readFileSync(`${__dirname}/wasm/doubleGlobals.wasm`) | |
205 … | + wasm = persit.prepare(wasm, { | |
206 … | + globals: [false, true] | |
207 … | + }, '_@') | |
208 … | + const wasmInstance = await WebAssembly.instantiate(wasm) | |
209 … | + const json = persit.hibernate(wasmInstance.instance, '_@') | |
210 … | + t.deepEquals(json, {globals: [[-1, -2]], table: [], symbol: '_@'}) | |
211 … | + t.equals(Object.keys(wasmInstance.instance.exports).length, 5) | |
212 … | + | |
213 … | + t.end() | |
214 … | +}) |
tests/wast/doubleGlobals.wast | ||
---|---|---|
@@ -1,0 +1,6 @@ | ||
1 … | +(module | |
2 … | + (global (mut i32) (i32.const -2)) | |
3 … | + (global (mut i64) (i64.const -2)) | |
4 … | + (func) | |
5 … | + (export "e" (func 0)) | |
6 … | +) |
tests/wast/singleI32Global.wast | ||
---|---|---|
@@ -1,0 +1,5 @@ | ||
1 … | +(module | |
2 … | + (global $a (mut i32) (i32.const -2)) | |
3 … | + (func) | |
4 … | + (export "e" (func 0)) | |
5 … | +) |
tests/wast/singleI64Global.wast | ||
---|---|---|
@@ -1,0 +1,5 @@ | ||
1 … | +(module | |
2 … | + (global $a (mut i64) (i64.const -2)) | |
3 … | + (func) | |
4 … | + (export "e" (func 0)) | |
5 … | +) |
tests/wast/singleImport.wast | ||
---|---|---|
@@ -1,0 +1,3 @@ | ||
1 … | +(module | |
2 … | + (import "foo" "bar" (func (param f32))) | |
3 … | + ) |
tests/wast/singleMemory.wast | ||
---|---|---|
@@ -1,0 +1,5 @@ | ||
1 … | +(module | |
2 … | + (memory (data "hi")) | |
3 … | + (func) | |
4 … | + (export "e" (func 0)) | |
5 … | +) |
tests/wast/singleTable.wast | ||
---|---|---|
@@ -1,0 +1,6 @@ | ||
1 … | +(module | |
2 … | + (table 1 1 anyfunc) | |
3 … | + (elem (i32.const 0) 0) | |
4 … | + (func) | |
5 … | + (export "e" (func 0)) | |
6 … | +) |
tests/wast/singleType.wast | ||
---|---|---|
@@ -1,0 +1,3 @@ | ||
1 … | +(module | |
2 … | + (type (func (param i32) (result i32))) | |
3 … | + ) |
tests/wast2wasm.js | ||
---|---|---|
@@ -1,0 +1,26 @@ | ||
1 … | +const wabt = require('wabt') | |
2 … | +const fs = require('fs') | |
3 … | + | |
4 … | +function filesWast2wasm () { | |
5 … | + const srcFiles = fs.readdirSync(`${__dirname}/wast`) | |
6 … | + const wastFiles = srcFiles.filter(name => name.split('.').pop() === 'wast') | |
7 … | + for (let file of wastFiles) { | |
8 … | + const wat = fs.readFileSync(`${__dirname}/wast/${file}`).toString() | |
9 … | + file = file.split('.')[0] | |
10 … | + | |
11 … | + try { | |
12 … | + const mod = wabt.parseWat('module.wast', wat) | |
13 … | + const r = mod.toBinary({log: true}) | |
14 … | + let binary = Buffer.from(r.buffer) | |
15 … | + if (!WebAssembly.validate(binary)) { | |
16 … | + throw new Error('invalid wasm binary') | |
17 … | + } | |
18 … | + fs.writeFileSync(`${__dirname}/wasm/${file}.wasm`, binary) | |
19 … | + } catch (e) { | |
20 … | + console.log(`failed at ${file}`) | |
21 … | + console.log(e) | |
22 … | + } | |
23 … | + } | |
24 … | +} | |
25 … | + | |
26 … | +filesWast2wasm() |
Built with git-ssb-web