wat4wasm 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/examples/01-text/module-output.wat +228 -0
  4. package/examples/01-text/module.wat +9 -0
  5. package/examples/02-include/module-output.wat +22 -0
  6. package/examples/02-include/module.wat +3 -0
  7. package/examples/02-include/used-folder/included-file.wat +4 -0
  8. package/examples/03-ref.extern/module-output.wat +1537 -0
  9. package/examples/03-ref.extern/module.wat +33 -0
  10. package/examples/04-ref.func/module-output.wat +25 -0
  11. package/examples/04-ref.func/module.wat +8 -0
  12. package/examples/05-global.get/module-output.wat +991 -0
  13. package/examples/05-global.get/module.wat +26 -0
  14. package/examples/06-async/module-output.wat +661 -0
  15. package/examples/06-async/module.wat +15 -0
  16. package/examples/07-data/module-output.wasm +0 -0
  17. package/examples/07-data/module.wat +29 -0
  18. package/examples/07-data/used-folder/clear-text.txt +1 -0
  19. package/examples/07-data/used-folder/compile-this.wat +8 -0
  20. package/examples/08-reflectors/how-to/README.md +0 -0
  21. package/examples/08-reflectors/how-to/output-01-command.sh +0 -0
  22. package/examples/08-reflectors/how-to/output-02-command.sh +0 -0
  23. package/examples/08-reflectors/how-to/output-03-command.sh +0 -0
  24. package/examples/08-reflectors/how-to/output-04-command.sh +0 -0
  25. package/examples/08-reflectors/how-to/wat4wasm-outputs/01-module.wat +3 -0
  26. package/examples/08-reflectors/how-to/wat4wasm-outputs/02-module.wasm +3 -0
  27. package/examples/08-reflectors/how-to/wat4wasm-outputs/03-module.js +0 -0
  28. package/examples/08-reflectors/how-to/wat4wasm-outputs/04-module.html +0 -0
  29. package/examples/08-reflectors/module-output.wat +995 -0
  30. package/examples/08-reflectors/module.wat +108 -0
  31. package/examples/09-replaceAll/module-output.wat +347 -0
  32. package/examples/09-replaceAll/module.wat +68 -0
  33. package/examples/99-complex/module.wat +8 -0
  34. package/examples/99-complex/output.html +1 -0
  35. package/examples/99-complex/sub/worker.wat +2 -0
  36. package/examples/shell-usages.sh +60 -0
  37. package/lib/build +33 -0
  38. package/lib/clean.js +91 -0
  39. package/lib/cli.js +273 -0
  40. package/lib/helpers.js +567 -0
  41. package/lib/index.js +95 -0
  42. package/lib/processors/async.js +53 -0
  43. package/lib/processors/data.js +188 -0
  44. package/lib/processors/import.js +178 -0
  45. package/lib/processors/include.js +17 -0
  46. package/lib/processors/new.js +21 -0
  47. package/lib/processors/ref_extern.js +64 -0
  48. package/lib/processors/ref_func.js +44 -0
  49. package/lib/processors/replace_all.js +56 -0
  50. package/lib/processors/start.js +42 -0
  51. package/lib/processors/string.js +57 -0
  52. package/lib/processors/text.js +115 -0
  53. package/lib/processors/wat4wasm.js +285 -0
  54. package/lib/wat4beauty.js +320 -0
  55. package/package.json +30 -0
  56. package/ss-console.png +0 -0
  57. package/ss-terminal.png +0 -0
  58. package/test/boot.wat +5 -0
  59. package/test/test-output.html +1 -0
  60. package/test/test-output.js +27 -0
  61. package/test/test-output.wasm +0 -0
  62. package/test/test-sub.wat +4 -0
  63. package/test/test.wat +73 -0
  64. package/test/test_worker.js +1 -0
  65. package/wat4wasm +1998 -0
@@ -0,0 +1,115 @@
1
+ import helpers from "../helpers.js"
2
+
3
+ export const TEXT_BLOCK_NAME = "text";
4
+
5
+ const TEXT_ONINIT_BLOCK = (offset, length, setter) => String(
6
+ `
7
+ (block $decodeText/${offset}:${length}
8
+
9
+ (local.set $viewAt (i32.const 0))
10
+ (local.set $offset (i32.const ${offset}))
11
+ (local.set $length (i32.const ${length}))
12
+
13
+ (local.set $arguments (call $self.Array<>ext))
14
+
15
+ (call $self.Reflect.set<ext.i32.i32>
16
+ (local.get $arguments) (i32.const 0) (local.get $length)
17
+ )
18
+
19
+ (local.set $arrayBufferView
20
+ (call $self.Reflect.construct<ext.ext>ext
21
+ (local.get $Uint8Array)
22
+ (local.get $arguments)
23
+ )
24
+ )
25
+
26
+ (loop $length--
27
+ (if (local.get $length)
28
+ (then
29
+ (memory.init $wat4wasm
30
+ (i32.const 0)
31
+ (local.get $offset)
32
+ (i32.const 1)
33
+ )
34
+
35
+ (call $self.Reflect.set<ext.i32.i32>
36
+ (local.get $arrayBufferView)
37
+ (local.get $viewAt)
38
+ (i32.load8_u (i32.const 0))
39
+ )
40
+
41
+ (local.set $viewAt (i32.add (local.get $viewAt) (i32.const 1)))
42
+ (local.set $offset (i32.add (local.get $offset) (i32.const 1)))
43
+ (local.set $length (i32.sub (local.get $length) (i32.const 1)))
44
+
45
+ (br $length--)
46
+ )
47
+ )
48
+ )
49
+
50
+ (local.set $arguments (call $self.Array<>ext))
51
+
52
+ (call $self.Reflect.set<ext.i32.ext>
53
+ (local.get $arguments)
54
+ (i32.const 0)
55
+ (local.get $arrayBufferView)
56
+ )
57
+
58
+ ${setter}
59
+ )
60
+ `).trim();
61
+
62
+ export default function (wat, WAT4WASM) {
63
+
64
+ const maskSet = new helpers.MaskSet(wat);
65
+ const textBlocks = new Array();
66
+
67
+ while (maskSet.hasBlock(TEXT_BLOCK_NAME)) {
68
+ let block = maskSet.lastBlockOf(TEXT_BLOCK_NAME);
69
+ maskSet.mask(block);
70
+ textBlocks.push(block);
71
+ }
72
+
73
+ wat = maskSet.restore();
74
+
75
+ textBlocks.forEach(block => {
76
+ const text = helpers.findQuotedText(block);
77
+ const view = helpers.encodeText(text);
78
+
79
+ const dataRequest = WAT4WASM_ALLOC_DATA_BUFFER(wat, view.buffer);
80
+
81
+ block.dataOffset = dataRequest.offset;
82
+ block.viewLength = view.length;
83
+ block.strPreview = helpers.abstract(text);
84
+
85
+ wat = dataRequest.modifiedRaw;
86
+ });
87
+
88
+ textBlocks.forEach(block => {
89
+ const growRequest = WAT4WASM_GROW_EXTERN_TABLE(wat);
90
+ block.tableGetter = growRequest.getter.concat(`;; ${block.strPreview} \n`);
91
+ block.tableSetter = growRequest.generateSetter(`
92
+ (call $self.Reflect.apply<ext.ext.ext>ext
93
+ (local.get $textDecoder.decode)
94
+ (local.get $textDecoder)
95
+ (local.get $arguments) ;; ${block.strPreview}
96
+ )`).trim();
97
+
98
+ wat = growRequest.modifiedRaw;
99
+ });
100
+
101
+ textBlocks.forEach(block => {
102
+ wat = wat.replaceAll(block.toString(), block.tableGetter)
103
+ });
104
+
105
+ const oninit = textBlocks.map(block =>
106
+ TEXT_ONINIT_BLOCK(
107
+ block.dataOffset,
108
+ block.viewLength, block.tableSetter
109
+ )
110
+ ).join("\n");
111
+
112
+ wat = APPEND_ON_INIT(wat, oninit);
113
+
114
+ return wat;
115
+ }
@@ -0,0 +1,285 @@
1
+ import helpers from "../helpers.js"
2
+
3
+ export let WAT4WASM_$NAME = `$wat4wasm`;
4
+
5
+ export let WAT4WASM_FUNC = String(`
6
+ (func $wat4wasm
7
+ (local $textDecoder externref)
8
+ (local $textDecoder.decode externref)
9
+ (local $Uint8Array externref)
10
+ (local $arguments externref)
11
+ (local $arrayBufferView externref)
12
+
13
+ (local $viewAt i32)
14
+ (local $offset i32)
15
+ (local $length i32)
16
+
17
+ (block $prepare
18
+ (local.set $textDecoder
19
+ (call $self.Reflect.construct<ext.ext>ext
20
+ (call $self.Reflect.get<ext.ext>ext
21
+ (self)
22
+ (string "TextDecoder")
23
+ )
24
+ (self)
25
+ )
26
+ )
27
+
28
+ (local.set $textDecoder.decode
29
+ (call $self.Reflect.get<ext.ext>ext
30
+ (local.get $textDecoder)
31
+ (string "decode")
32
+ )
33
+ )
34
+
35
+ (local.set $Uint8Array
36
+ (call $self.Reflect.get<ext.ext>ext
37
+ (self)
38
+ (string "Uint8Array")
39
+ )
40
+ )
41
+ )
42
+
43
+ ;;secure zero heap for memory.init
44
+ (i32.const 0)
45
+ (i32.load (i32.const 0))
46
+ ;; offset and value stacked now
47
+
48
+ (block $oninit)
49
+ (block $ontextready)
50
+ (block $onexternready)
51
+
52
+ ;; restore zero heap value
53
+ (i32.store (; stack stack ;))
54
+ (nop)
55
+ )
56
+ `);
57
+
58
+ export let WAT4WASM_GLOBAL = String(
59
+ `(global $wat4wasm (mut externref) (ref.null extern))`
60
+ );
61
+
62
+ export let WAT4WASM_TABLE = (size = 1) => String(
63
+ `(table $wat4wasm ${size} externref)`
64
+ );
65
+
66
+ export let WAT4WASM_DATA = (buff = "0000") => String(
67
+ `(data $wat4wasm "${Buffer.from(buff).toString("hex").replaceAll(/(..)/g, `\\$1`)}")`
68
+ );
69
+
70
+ export let WAT4WASM_ELEM = String(
71
+ `(elem $wat4wasm declare func)`
72
+ );
73
+
74
+ export let WAT4WASM_MEMORY = String(
75
+ `(memory $wat4wasm 1)`
76
+ );
77
+
78
+ export let WAT4WASM_START = String(
79
+ `(start $wat4wasm)`
80
+ );
81
+
82
+ export const WAT4WASM_BLOCKS = {
83
+ global: WAT4WASM_GLOBAL,
84
+ table: WAT4WASM_TABLE(1),
85
+ elem: WAT4WASM_ELEM,
86
+ func: WAT4WASM_FUNC,
87
+ data: WAT4WASM_DATA(),
88
+ };
89
+
90
+ export function FUNC_WAT4WASM(wat) {
91
+ return helpers.lastBlockOf(wat, "func", { $name: WAT4WASM_$NAME });
92
+ }
93
+
94
+ export function ELEM_WAT4WASM(wat) {
95
+ const block = helpers.lastBlockOf(wat, "elem", { $name: WAT4WASM_$NAME });
96
+ return block && Object.assign(block, {
97
+ isInitial: helpers.generateId(block) === helpers.generateId(WAT4WASM_ELEM)
98
+ });
99
+ }
100
+
101
+ export function MEMORY_WAT4WASM(wat) {
102
+ return helpers.lastBlockOf(wat, "memory", { $name: WAT4WASM_$NAME });
103
+ }
104
+
105
+ export function GLOBAL_WAT4WASM(wat) {
106
+ return helpers.lastBlockOf(wat, "global", { $name: WAT4WASM_$NAME });
107
+ }
108
+
109
+ export function START_WAT4WASM(wat) {
110
+ return helpers.lastBlockOf(wat, "start", { $name: WAT4WASM_$NAME });
111
+ }
112
+
113
+ export function FUNC_WAT4WASM_NOBLOCKS(wat) {
114
+ const maskSet = new helpers.MaskSet(FUNC_WAT4WASM(wat));
115
+
116
+ maskSet.remove(maskSet.lastBlockOf("block", { name: "onexternready" }));
117
+ maskSet.remove(maskSet.lastBlockOf("block", { name: "ontextready" }));
118
+ maskSet.remove(maskSet.lastBlockOf("block", { name: "oninit" }));
119
+ maskSet.remove(maskSet.lastBlockOf("block", { name: "prepare" }));
120
+
121
+ return maskSet.restore();
122
+ }
123
+
124
+
125
+ export function FUNC_WAT4WASM_BLOCK_ONINIT(wat) {
126
+ const wat4func = FUNC_WAT4WASM(wat);
127
+ const blockoninit = helpers.lastBlockOf(wat4func, "block", { name: "oninit" });
128
+ const $blockoninit = helpers.parseBlockAt(wat, wat4func.begin + blockoninit.begin);
129
+
130
+ return $blockoninit;
131
+ }
132
+
133
+ export function FUNC_WAT4WASM_BLOCK_ONTEXTREADY(wat) {
134
+ const wat4func = FUNC_WAT4WASM(wat);
135
+ const ontextready = helpers.lastBlockOf(wat4func, "block", { name: "ontextready" });
136
+ const $ontextready = helpers.parseBlockAt(wat, wat4func.begin + ontextready.begin);
137
+
138
+ return $ontextready;
139
+ }
140
+
141
+ export function FUNC_WAT4WASM_BLOCK_ONEXTERNREADY(wat) {
142
+ const wat4func = FUNC_WAT4WASM(wat);
143
+ const onexternready = helpers.lastBlockOf(wat4func, "block", { name: "onexternready" });
144
+ const $onexternready = helpers.parseBlockAt(wat, wat4func.begin + onexternready.begin);
145
+
146
+ return $onexternready;
147
+ }
148
+
149
+ export function APPEND_ON_INIT(wat, block) {
150
+ const oninitblock = FUNC_WAT4WASM_BLOCK_ONINIT(wat);
151
+
152
+ if (oninitblock.includes(block.toString())) {
153
+ return wat;
154
+ }
155
+
156
+ wat = oninitblock.replacedRaw(
157
+ helpers.append(oninitblock, block)
158
+ );
159
+
160
+ return wat;
161
+ }
162
+
163
+ export function APPEND_ON_TEXT_READY(wat, block) {
164
+ const ontextready = FUNC_WAT4WASM_BLOCK_ONTEXTREADY(wat);
165
+
166
+ if (ontextready.hasBlock("block",
167
+ { $name: helpers.firstBlockOf(block, "block")?.$name }
168
+ ) === false && !ontextready.includes(block.trim())) {
169
+ return ontextready.replacedRaw(
170
+ helpers.append(ontextready, block)
171
+ );
172
+ }
173
+
174
+ return wat;
175
+ }
176
+
177
+ export function APPEND_ON_EXTERN_READY(wat, block) {
178
+ const onexternready = FUNC_WAT4WASM_BLOCK_ONEXTERNREADY(wat);
179
+
180
+ if (onexternready.includes(block.toString())) {
181
+ return wat;
182
+ }
183
+
184
+ wat = onexternready.replacedRaw(
185
+ helpers.append(onexternready, block)
186
+ );
187
+
188
+ return wat;
189
+ }
190
+
191
+
192
+ export function TABLE_WAT4WASM(wat) {
193
+ const wat4table = helpers.lastBlockOf(wat, "table", { $name: WAT4WASM_$NAME });
194
+ const lastIndex = parseInt(wat4table.toString().match(/\s(\d+)/).pop());
195
+
196
+ return wat4table && Object.assign(wat4table, {
197
+ lastIndex, isInitial: lastIndex === 1
198
+ })
199
+ }
200
+
201
+ export function WAT4WASM_GROW_EXTERN_TABLE(wat) {
202
+ const wat4table = TABLE_WAT4WASM(wat);
203
+ const lastIndex = wat4table.lastIndex;
204
+
205
+ return {
206
+ index: lastIndex,
207
+ getter: `(table.get ${WAT4WASM_$NAME} (i32.const ${lastIndex}))`,
208
+ generateSetter: value => `(table.set ${WAT4WASM_$NAME} (i32.const ${lastIndex}) ${value.toString()})`,
209
+ modifiedRaw: wat4table.replacedRaw(WAT4WASM_TABLE(lastIndex + 1))
210
+ };
211
+ }
212
+
213
+
214
+ export function WAT4WASM_REFERENCE_FUNC_ELEMENT(wat, $name) {
215
+ const $wat4elem = ELEM_WAT4WASM(wat);
216
+ const _wat4elem = $wat4elem.toString();
217
+
218
+ if (_wat4elem.includes($name) === false) {
219
+ wat = $wat4elem.replacedRaw(_wat4elem
220
+ .substring(0, _wat4elem.lastIndexOf(")"))
221
+ .concat(` ${$name}`)
222
+ .concat(")")
223
+ );
224
+ }
225
+
226
+ return wat;
227
+ }
228
+
229
+
230
+ export function DATA_WAT4WASM(wat) {
231
+ const block = helpers.lastBlockOf(wat, "data", { $name: WAT4WASM_$NAME });
232
+ const strhex = helpers.findQuotedText(block);
233
+ const buffer = Buffer.from(strhex.replaceAll(/[^a-f0-9A-F]/g, ""), "hex");
234
+
235
+ return Object.assign(block, {
236
+ buffer: buffer,
237
+ offset: buffer.byteLength,
238
+ isInitial: buffer.byteLength === 4
239
+ });
240
+ }
241
+
242
+ export function WAT4WASM_ALLOC_DATA_BUFFER(wat, buffer) {
243
+ const new_data = Buffer.from(buffer);
244
+ const all_data = DATA_WAT4WASM(wat);
245
+
246
+ let offset = all_data.buffer.indexOf(new_data);
247
+ let modifiedRaw = wat;
248
+
249
+ if (offset < 1) {
250
+ offset = all_data.offset;
251
+ all_data.buffer.writeUint32LE(offset + new_data.byteLength);
252
+ modifiedRaw = all_data.replacedRaw(WAT4WASM_DATA(Buffer.concat([all_data.buffer, new_data])));
253
+ }
254
+
255
+ return {
256
+ offset,
257
+ modifiedRaw,
258
+ isRawModified: modifiedRaw.toString() !== wat.toString()
259
+ };
260
+ }
261
+
262
+
263
+ export default function (wat) {
264
+ let i = 31, raw;
265
+
266
+ if (helpers.hasBlock(wat, "memory") === false) {
267
+ WAT4WASM_BLOCKS.memory = WAT4WASM_MEMORY;
268
+ }
269
+
270
+ for (const BLOCK_NAME in WAT4WASM_BLOCKS) {
271
+
272
+ if (wat.includes(`(${BLOCK_NAME} ${WAT4WASM_$NAME}`)) {
273
+ continue;
274
+ }
275
+
276
+ if (i === 31) console.log("")
277
+ console.log(`🦋 appending element --> \x1b[${i++}m(${BLOCK_NAME} ${WAT4WASM_$NAME}) ...)\x1b[0m`);
278
+
279
+ raw = WAT4WASM_BLOCKS[BLOCK_NAME].replaceAll("$wat4wasm", WAT4WASM_$NAME);
280
+ wat = helpers.append(wat, raw);
281
+ }
282
+ if (i !== 31) console.log("")
283
+
284
+ return wat;
285
+ }