jonasknobloch commited on
Commit
d8d7490
·
verified ·
1 Parent(s): 559d077

Upload 3 files

Browse files
Files changed (3) hide show
  1. index.html +207 -19
  2. main.wasm +3 -0
  3. wasm_exec.js +575 -0
index.html CHANGED
@@ -1,19 +1,207 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>mbpe-dyn</title>
7
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
8
+ <script src="wasm_exec.js"></script>
9
+ <script>
10
+ const go = new Go();
11
+
12
+ WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then(result => {
13
+ go.run(result.instance);
14
+ });
15
+
16
+ async function tokenizeText() {
17
+ const input = document.getElementById("textInput").value.trim();
18
+ const modelChoice = document.getElementById("modelSelect").value;
19
+ const vocabSize = parseInt(document.getElementById("vocabSize").value, 10) || -1;
20
+
21
+ if (!input) {
22
+ alert("Please enter text to tokenize.");
23
+ return;
24
+ }
25
+
26
+ if (typeof tokenizeWeb !== "undefined") {
27
+ const resultJSON = tokenizeWeb(input, modelChoice, vocabSize);
28
+
29
+ try {
30
+ const result = JSON.parse(resultJSON);
31
+ console.log(result);
32
+
33
+ if (Array.isArray(result) && result.length > 0) {
34
+ displayTabs(result);
35
+ showResult(0); // Show first tab by default
36
+ } else {
37
+ document.getElementById("code").innerText = "No tokens found.";
38
+ document.getElementById("mermaidContainer").innerHTML = "";
39
+ }
40
+ } catch (e) {
41
+ console.error("Error parsing result:", e);
42
+ }
43
+ }
44
+ }
45
+
46
+ function displayTabs(results) {
47
+ const tabsContainer = document.getElementById("wordTabs");
48
+ tabsContainer.innerHTML = "";
49
+
50
+ results.forEach((entry, index) => {
51
+ const finalSegmentation = entry.Segmentations[entry.Segmentations.length - 1];
52
+ const label = finalSegmentation.map(t => t.Token).join("");
53
+
54
+ const tabButton = document.createElement("button");
55
+ tabButton.textContent = label;
56
+ tabButton.classList.add("word-tab");
57
+ tabButton.dataset.index = index;
58
+ tabButton.onclick = () => showResult(index);
59
+
60
+ tabsContainer.appendChild(tabButton);
61
+ });
62
+ }
63
+
64
+ function showResult(index) {
65
+ const results = JSON.parse(tokenizeWeb(
66
+ document.getElementById("textInput").value.trim(),
67
+ document.getElementById("modelSelect").value,
68
+ parseInt(document.getElementById("vocabSize").value, 10) || -1
69
+ ));
70
+
71
+ const selectedResult = results[index];
72
+
73
+ // Update Mermaid code
74
+ document.getElementById("code").innerText = selectedResult.Mermaid;
75
+ renderMermaid();
76
+
77
+ // Update active tab
78
+ document.querySelectorAll(".word-tab").forEach(tab => tab.classList.remove("active"));
79
+ document.querySelector(`.word-tab[data-index="${index}"]`).classList.add("active");
80
+ }
81
+
82
+ function renderMermaid() {
83
+ const diagramCode = document.getElementById("code").innerText.trim();
84
+ if (diagramCode) {
85
+ document.getElementById("mermaidContainer").innerHTML = `<div class="mermaid">${diagramCode}</div>`;
86
+ mermaid.init(undefined, document.querySelectorAll(".mermaid"));
87
+ }
88
+ }
89
+ </script>
90
+ <style>
91
+ /* General Styles */
92
+ body {
93
+ font-family: Arial, sans-serif;
94
+ background: #f8f9fa;
95
+ color: #333;
96
+ text-align: center;
97
+ padding: 20px;
98
+ }
99
+
100
+ h1 {
101
+ color: #007bff;
102
+ }
103
+
104
+ /* Input and Select */
105
+ .input-group {
106
+ display: flex;
107
+ justify-content: center;
108
+ gap: 10px;
109
+ margin-bottom: 20px;
110
+ }
111
+
112
+ input, select, button {
113
+ padding: 10px;
114
+ border: 1px solid #ccc;
115
+ border-radius: 5px;
116
+ font-size: 16px;
117
+ }
118
+
119
+ input {
120
+ width: 300px;
121
+ }
122
+
123
+ select {
124
+ width: 150px;
125
+ background: white;
126
+ cursor: pointer;
127
+ }
128
+
129
+ button {
130
+ background: #007bff;
131
+ color: white;
132
+ font-weight: bold;
133
+ cursor: pointer;
134
+ transition: 0.3s;
135
+ border: none;
136
+ }
137
+
138
+ button:hover {
139
+ background: #0056b3;
140
+ }
141
+
142
+ #modelSelect {
143
+ width: 80px;
144
+ }
145
+
146
+ #vocabSize {
147
+ width: 110px;
148
+ }
149
+
150
+ /* Word Tabs */
151
+ .word-tabs {
152
+ display: flex;
153
+ justify-content: center;
154
+ gap: 10px;
155
+ margin-top: 20px;
156
+ margin-bottom: 20px;
157
+ flex-wrap: wrap;
158
+ }
159
+
160
+ .word-tab {
161
+ padding: 8px 15px;
162
+ background: #e1ecf4;
163
+ border: none;
164
+ border-radius: 20px;
165
+ cursor: pointer;
166
+ font-weight: bold;
167
+ transition: 0.3s;
168
+ }
169
+
170
+ .word-tab.active {
171
+ background: #007bff;
172
+ color: white;
173
+ }
174
+ </style>
175
+ </head>
176
+ <body>
177
+
178
+ <h1>mbpe-dyn</h1>
179
+
180
+ <div class="input-group">
181
+ <select id="modelSelect">
182
+ <option value="m000">m000</option>
183
+ <option value="m010">m010</option>
184
+ <option value="m020">m020</option>
185
+ <option value="m030">m030</option>
186
+ <option value="m040">m040</option>
187
+ <option value="m050">m050</option>
188
+ <option value="m060">m060</option>
189
+ <option value="m070">m070</option>
190
+ <option value="m080">m080</option>
191
+ <option value="m090">m090</option>
192
+ <option value="m100" selected>m100</option>
193
+ </select>
194
+ <select id="vocabSize">
195
+ <option value="16384">2¹⁴ (16K)</option>
196
+ <option value="32768">2¹⁵ (32K)</option>
197
+ <option value="65536">2¹⁶ (64K)</option>
198
+ <option value="131072" selected>2¹⁷ (128K)</option>
199
+ </select>
200
+ <input type="text" id="textInput" placeholder="Enter text here" value="airsickness">
201
+ <button onclick="tokenizeText()">Tokenize</button>
202
+ </div>
203
+ <div id="wordTabs" class="word-tabs"></div>
204
+ <code id="code" style="display: none;"></code>
205
+ <div id="mermaidContainer"></div>
206
+ </body>
207
+ </html>
main.wasm ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c8b0c692cf0fd88106ec4636e9fdfbc2ca6723efd104aeefb4c344780132a5c4
3
+ size 43684316
wasm_exec.js ADDED
@@ -0,0 +1,575 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2018 The Go Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style
3
+ // license that can be found in the LICENSE file.
4
+
5
+ "use strict";
6
+
7
+ (() => {
8
+ const enosys = () => {
9
+ const err = new Error("not implemented");
10
+ err.code = "ENOSYS";
11
+ return err;
12
+ };
13
+
14
+ if (!globalThis.fs) {
15
+ let outputBuf = "";
16
+ globalThis.fs = {
17
+ constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_DIRECTORY: -1 }, // unused
18
+ writeSync(fd, buf) {
19
+ outputBuf += decoder.decode(buf);
20
+ const nl = outputBuf.lastIndexOf("\n");
21
+ if (nl != -1) {
22
+ console.log(outputBuf.substring(0, nl));
23
+ outputBuf = outputBuf.substring(nl + 1);
24
+ }
25
+ return buf.length;
26
+ },
27
+ write(fd, buf, offset, length, position, callback) {
28
+ if (offset !== 0 || length !== buf.length || position !== null) {
29
+ callback(enosys());
30
+ return;
31
+ }
32
+ const n = this.writeSync(fd, buf);
33
+ callback(null, n);
34
+ },
35
+ chmod(path, mode, callback) { callback(enosys()); },
36
+ chown(path, uid, gid, callback) { callback(enosys()); },
37
+ close(fd, callback) { callback(enosys()); },
38
+ fchmod(fd, mode, callback) { callback(enosys()); },
39
+ fchown(fd, uid, gid, callback) { callback(enosys()); },
40
+ fstat(fd, callback) { callback(enosys()); },
41
+ fsync(fd, callback) { callback(null); },
42
+ ftruncate(fd, length, callback) { callback(enosys()); },
43
+ lchown(path, uid, gid, callback) { callback(enosys()); },
44
+ link(path, link, callback) { callback(enosys()); },
45
+ lstat(path, callback) { callback(enosys()); },
46
+ mkdir(path, perm, callback) { callback(enosys()); },
47
+ open(path, flags, mode, callback) { callback(enosys()); },
48
+ read(fd, buffer, offset, length, position, callback) { callback(enosys()); },
49
+ readdir(path, callback) { callback(enosys()); },
50
+ readlink(path, callback) { callback(enosys()); },
51
+ rename(from, to, callback) { callback(enosys()); },
52
+ rmdir(path, callback) { callback(enosys()); },
53
+ stat(path, callback) { callback(enosys()); },
54
+ symlink(path, link, callback) { callback(enosys()); },
55
+ truncate(path, length, callback) { callback(enosys()); },
56
+ unlink(path, callback) { callback(enosys()); },
57
+ utimes(path, atime, mtime, callback) { callback(enosys()); },
58
+ };
59
+ }
60
+
61
+ if (!globalThis.process) {
62
+ globalThis.process = {
63
+ getuid() { return -1; },
64
+ getgid() { return -1; },
65
+ geteuid() { return -1; },
66
+ getegid() { return -1; },
67
+ getgroups() { throw enosys(); },
68
+ pid: -1,
69
+ ppid: -1,
70
+ umask() { throw enosys(); },
71
+ cwd() { throw enosys(); },
72
+ chdir() { throw enosys(); },
73
+ }
74
+ }
75
+
76
+ if (!globalThis.path) {
77
+ globalThis.path = {
78
+ resolve(...pathSegments) {
79
+ return pathSegments.join("/");
80
+ }
81
+ }
82
+ }
83
+
84
+ if (!globalThis.crypto) {
85
+ throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)");
86
+ }
87
+
88
+ if (!globalThis.performance) {
89
+ throw new Error("globalThis.performance is not available, polyfill required (performance.now only)");
90
+ }
91
+
92
+ if (!globalThis.TextEncoder) {
93
+ throw new Error("globalThis.TextEncoder is not available, polyfill required");
94
+ }
95
+
96
+ if (!globalThis.TextDecoder) {
97
+ throw new Error("globalThis.TextDecoder is not available, polyfill required");
98
+ }
99
+
100
+ const encoder = new TextEncoder("utf-8");
101
+ const decoder = new TextDecoder("utf-8");
102
+
103
+ globalThis.Go = class {
104
+ constructor() {
105
+ this.argv = ["js"];
106
+ this.env = {};
107
+ this.exit = (code) => {
108
+ if (code !== 0) {
109
+ console.warn("exit code:", code);
110
+ }
111
+ };
112
+ this._exitPromise = new Promise((resolve) => {
113
+ this._resolveExitPromise = resolve;
114
+ });
115
+ this._pendingEvent = null;
116
+ this._scheduledTimeouts = new Map();
117
+ this._nextCallbackTimeoutID = 1;
118
+
119
+ const setInt64 = (addr, v) => {
120
+ this.mem.setUint32(addr + 0, v, true);
121
+ this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true);
122
+ }
123
+
124
+ const setInt32 = (addr, v) => {
125
+ this.mem.setUint32(addr + 0, v, true);
126
+ }
127
+
128
+ const getInt64 = (addr) => {
129
+ const low = this.mem.getUint32(addr + 0, true);
130
+ const high = this.mem.getInt32(addr + 4, true);
131
+ return low + high * 4294967296;
132
+ }
133
+
134
+ const loadValue = (addr) => {
135
+ const f = this.mem.getFloat64(addr, true);
136
+ if (f === 0) {
137
+ return undefined;
138
+ }
139
+ if (!isNaN(f)) {
140
+ return f;
141
+ }
142
+
143
+ const id = this.mem.getUint32(addr, true);
144
+ return this._values[id];
145
+ }
146
+
147
+ const storeValue = (addr, v) => {
148
+ const nanHead = 0x7FF80000;
149
+
150
+ if (typeof v === "number" && v !== 0) {
151
+ if (isNaN(v)) {
152
+ this.mem.setUint32(addr + 4, nanHead, true);
153
+ this.mem.setUint32(addr, 0, true);
154
+ return;
155
+ }
156
+ this.mem.setFloat64(addr, v, true);
157
+ return;
158
+ }
159
+
160
+ if (v === undefined) {
161
+ this.mem.setFloat64(addr, 0, true);
162
+ return;
163
+ }
164
+
165
+ let id = this._ids.get(v);
166
+ if (id === undefined) {
167
+ id = this._idPool.pop();
168
+ if (id === undefined) {
169
+ id = this._values.length;
170
+ }
171
+ this._values[id] = v;
172
+ this._goRefCounts[id] = 0;
173
+ this._ids.set(v, id);
174
+ }
175
+ this._goRefCounts[id]++;
176
+ let typeFlag = 0;
177
+ switch (typeof v) {
178
+ case "object":
179
+ if (v !== null) {
180
+ typeFlag = 1;
181
+ }
182
+ break;
183
+ case "string":
184
+ typeFlag = 2;
185
+ break;
186
+ case "symbol":
187
+ typeFlag = 3;
188
+ break;
189
+ case "function":
190
+ typeFlag = 4;
191
+ break;
192
+ }
193
+ this.mem.setUint32(addr + 4, nanHead | typeFlag, true);
194
+ this.mem.setUint32(addr, id, true);
195
+ }
196
+
197
+ const loadSlice = (addr) => {
198
+ const array = getInt64(addr + 0);
199
+ const len = getInt64(addr + 8);
200
+ return new Uint8Array(this._inst.exports.mem.buffer, array, len);
201
+ }
202
+
203
+ const loadSliceOfValues = (addr) => {
204
+ const array = getInt64(addr + 0);
205
+ const len = getInt64(addr + 8);
206
+ const a = new Array(len);
207
+ for (let i = 0; i < len; i++) {
208
+ a[i] = loadValue(array + i * 8);
209
+ }
210
+ return a;
211
+ }
212
+
213
+ const loadString = (addr) => {
214
+ const saddr = getInt64(addr + 0);
215
+ const len = getInt64(addr + 8);
216
+ return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
217
+ }
218
+
219
+ const testCallExport = (a, b) => {
220
+ this._inst.exports.testExport0();
221
+ return this._inst.exports.testExport(a, b);
222
+ }
223
+
224
+ const timeOrigin = Date.now() - performance.now();
225
+ this.importObject = {
226
+ _gotest: {
227
+ add: (a, b) => a + b,
228
+ callExport: testCallExport,
229
+ },
230
+ gojs: {
231
+ // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
232
+ // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
233
+ // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
234
+ // This changes the SP, thus we have to update the SP used by the imported function.
235
+
236
+ // func wasmExit(code int32)
237
+ "runtime.wasmExit": (sp) => {
238
+ sp >>>= 0;
239
+ const code = this.mem.getInt32(sp + 8, true);
240
+ this.exited = true;
241
+ delete this._inst;
242
+ delete this._values;
243
+ delete this._goRefCounts;
244
+ delete this._ids;
245
+ delete this._idPool;
246
+ this.exit(code);
247
+ },
248
+
249
+ // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
250
+ "runtime.wasmWrite": (sp) => {
251
+ sp >>>= 0;
252
+ const fd = getInt64(sp + 8);
253
+ const p = getInt64(sp + 16);
254
+ const n = this.mem.getInt32(sp + 24, true);
255
+ fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
256
+ },
257
+
258
+ // func resetMemoryDataView()
259
+ "runtime.resetMemoryDataView": (sp) => {
260
+ sp >>>= 0;
261
+ this.mem = new DataView(this._inst.exports.mem.buffer);
262
+ },
263
+
264
+ // func nanotime1() int64
265
+ "runtime.nanotime1": (sp) => {
266
+ sp >>>= 0;
267
+ setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
268
+ },
269
+
270
+ // func walltime() (sec int64, nsec int32)
271
+ "runtime.walltime": (sp) => {
272
+ sp >>>= 0;
273
+ const msec = (new Date).getTime();
274
+ setInt64(sp + 8, msec / 1000);
275
+ this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
276
+ },
277
+
278
+ // func scheduleTimeoutEvent(delay int64) int32
279
+ "runtime.scheduleTimeoutEvent": (sp) => {
280
+ sp >>>= 0;
281
+ const id = this._nextCallbackTimeoutID;
282
+ this._nextCallbackTimeoutID++;
283
+ this._scheduledTimeouts.set(id, setTimeout(
284
+ () => {
285
+ this._resume();
286
+ while (this._scheduledTimeouts.has(id)) {
287
+ // for some reason Go failed to register the timeout event, log and try again
288
+ // (temporary workaround for https://github.com/golang/go/issues/28975)
289
+ console.warn("scheduleTimeoutEvent: missed timeout event");
290
+ this._resume();
291
+ }
292
+ },
293
+ getInt64(sp + 8),
294
+ ));
295
+ this.mem.setInt32(sp + 16, id, true);
296
+ },
297
+
298
+ // func clearTimeoutEvent(id int32)
299
+ "runtime.clearTimeoutEvent": (sp) => {
300
+ sp >>>= 0;
301
+ const id = this.mem.getInt32(sp + 8, true);
302
+ clearTimeout(this._scheduledTimeouts.get(id));
303
+ this._scheduledTimeouts.delete(id);
304
+ },
305
+
306
+ // func getRandomData(r []byte)
307
+ "runtime.getRandomData": (sp) => {
308
+ sp >>>= 0;
309
+ crypto.getRandomValues(loadSlice(sp + 8));
310
+ },
311
+
312
+ // func finalizeRef(v ref)
313
+ "syscall/js.finalizeRef": (sp) => {
314
+ sp >>>= 0;
315
+ const id = this.mem.getUint32(sp + 8, true);
316
+ this._goRefCounts[id]--;
317
+ if (this._goRefCounts[id] === 0) {
318
+ const v = this._values[id];
319
+ this._values[id] = null;
320
+ this._ids.delete(v);
321
+ this._idPool.push(id);
322
+ }
323
+ },
324
+
325
+ // func stringVal(value string) ref
326
+ "syscall/js.stringVal": (sp) => {
327
+ sp >>>= 0;
328
+ storeValue(sp + 24, loadString(sp + 8));
329
+ },
330
+
331
+ // func valueGet(v ref, p string) ref
332
+ "syscall/js.valueGet": (sp) => {
333
+ sp >>>= 0;
334
+ const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
335
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
336
+ storeValue(sp + 32, result);
337
+ },
338
+
339
+ // func valueSet(v ref, p string, x ref)
340
+ "syscall/js.valueSet": (sp) => {
341
+ sp >>>= 0;
342
+ Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
343
+ },
344
+
345
+ // func valueDelete(v ref, p string)
346
+ "syscall/js.valueDelete": (sp) => {
347
+ sp >>>= 0;
348
+ Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
349
+ },
350
+
351
+ // func valueIndex(v ref, i int) ref
352
+ "syscall/js.valueIndex": (sp) => {
353
+ sp >>>= 0;
354
+ storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
355
+ },
356
+
357
+ // valueSetIndex(v ref, i int, x ref)
358
+ "syscall/js.valueSetIndex": (sp) => {
359
+ sp >>>= 0;
360
+ Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
361
+ },
362
+
363
+ // func valueCall(v ref, m string, args []ref) (ref, bool)
364
+ "syscall/js.valueCall": (sp) => {
365
+ sp >>>= 0;
366
+ try {
367
+ const v = loadValue(sp + 8);
368
+ const m = Reflect.get(v, loadString(sp + 16));
369
+ const args = loadSliceOfValues(sp + 32);
370
+ const result = Reflect.apply(m, v, args);
371
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
372
+ storeValue(sp + 56, result);
373
+ this.mem.setUint8(sp + 64, 1);
374
+ } catch (err) {
375
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
376
+ storeValue(sp + 56, err);
377
+ this.mem.setUint8(sp + 64, 0);
378
+ }
379
+ },
380
+
381
+ // func valueInvoke(v ref, args []ref) (ref, bool)
382
+ "syscall/js.valueInvoke": (sp) => {
383
+ sp >>>= 0;
384
+ try {
385
+ const v = loadValue(sp + 8);
386
+ const args = loadSliceOfValues(sp + 16);
387
+ const result = Reflect.apply(v, undefined, args);
388
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
389
+ storeValue(sp + 40, result);
390
+ this.mem.setUint8(sp + 48, 1);
391
+ } catch (err) {
392
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
393
+ storeValue(sp + 40, err);
394
+ this.mem.setUint8(sp + 48, 0);
395
+ }
396
+ },
397
+
398
+ // func valueNew(v ref, args []ref) (ref, bool)
399
+ "syscall/js.valueNew": (sp) => {
400
+ sp >>>= 0;
401
+ try {
402
+ const v = loadValue(sp + 8);
403
+ const args = loadSliceOfValues(sp + 16);
404
+ const result = Reflect.construct(v, args);
405
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
406
+ storeValue(sp + 40, result);
407
+ this.mem.setUint8(sp + 48, 1);
408
+ } catch (err) {
409
+ sp = this._inst.exports.getsp() >>> 0; // see comment above
410
+ storeValue(sp + 40, err);
411
+ this.mem.setUint8(sp + 48, 0);
412
+ }
413
+ },
414
+
415
+ // func valueLength(v ref) int
416
+ "syscall/js.valueLength": (sp) => {
417
+ sp >>>= 0;
418
+ setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
419
+ },
420
+
421
+ // valuePrepareString(v ref) (ref, int)
422
+ "syscall/js.valuePrepareString": (sp) => {
423
+ sp >>>= 0;
424
+ const str = encoder.encode(String(loadValue(sp + 8)));
425
+ storeValue(sp + 16, str);
426
+ setInt64(sp + 24, str.length);
427
+ },
428
+
429
+ // valueLoadString(v ref, b []byte)
430
+ "syscall/js.valueLoadString": (sp) => {
431
+ sp >>>= 0;
432
+ const str = loadValue(sp + 8);
433
+ loadSlice(sp + 16).set(str);
434
+ },
435
+
436
+ // func valueInstanceOf(v ref, t ref) bool
437
+ "syscall/js.valueInstanceOf": (sp) => {
438
+ sp >>>= 0;
439
+ this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0);
440
+ },
441
+
442
+ // func copyBytesToGo(dst []byte, src ref) (int, bool)
443
+ "syscall/js.copyBytesToGo": (sp) => {
444
+ sp >>>= 0;
445
+ const dst = loadSlice(sp + 8);
446
+ const src = loadValue(sp + 32);
447
+ if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
448
+ this.mem.setUint8(sp + 48, 0);
449
+ return;
450
+ }
451
+ const toCopy = src.subarray(0, dst.length);
452
+ dst.set(toCopy);
453
+ setInt64(sp + 40, toCopy.length);
454
+ this.mem.setUint8(sp + 48, 1);
455
+ },
456
+
457
+ // func copyBytesToJS(dst ref, src []byte) (int, bool)
458
+ "syscall/js.copyBytesToJS": (sp) => {
459
+ sp >>>= 0;
460
+ const dst = loadValue(sp + 8);
461
+ const src = loadSlice(sp + 16);
462
+ if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
463
+ this.mem.setUint8(sp + 48, 0);
464
+ return;
465
+ }
466
+ const toCopy = src.subarray(0, dst.length);
467
+ dst.set(toCopy);
468
+ setInt64(sp + 40, toCopy.length);
469
+ this.mem.setUint8(sp + 48, 1);
470
+ },
471
+
472
+ "debug": (value) => {
473
+ console.log(value);
474
+ },
475
+ }
476
+ };
477
+ }
478
+
479
+ async run(instance) {
480
+ if (!(instance instanceof WebAssembly.Instance)) {
481
+ throw new Error("Go.run: WebAssembly.Instance expected");
482
+ }
483
+ this._inst = instance;
484
+ this.mem = new DataView(this._inst.exports.mem.buffer);
485
+ this._values = [ // JS values that Go currently has references to, indexed by reference id
486
+ NaN,
487
+ 0,
488
+ null,
489
+ true,
490
+ false,
491
+ globalThis,
492
+ this,
493
+ ];
494
+ this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
495
+ this._ids = new Map([ // mapping from JS values to reference ids
496
+ [0, 1],
497
+ [null, 2],
498
+ [true, 3],
499
+ [false, 4],
500
+ [globalThis, 5],
501
+ [this, 6],
502
+ ]);
503
+ this._idPool = []; // unused ids that have been garbage collected
504
+ this.exited = false; // whether the Go program has exited
505
+
506
+ // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
507
+ let offset = 4096;
508
+
509
+ const strPtr = (str) => {
510
+ const ptr = offset;
511
+ const bytes = encoder.encode(str + "\0");
512
+ new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes);
513
+ offset += bytes.length;
514
+ if (offset % 8 !== 0) {
515
+ offset += 8 - (offset % 8);
516
+ }
517
+ return ptr;
518
+ };
519
+
520
+ const argc = this.argv.length;
521
+
522
+ const argvPtrs = [];
523
+ this.argv.forEach((arg) => {
524
+ argvPtrs.push(strPtr(arg));
525
+ });
526
+ argvPtrs.push(0);
527
+
528
+ const keys = Object.keys(this.env).sort();
529
+ keys.forEach((key) => {
530
+ argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
531
+ });
532
+ argvPtrs.push(0);
533
+
534
+ const argv = offset;
535
+ argvPtrs.forEach((ptr) => {
536
+ this.mem.setUint32(offset, ptr, true);
537
+ this.mem.setUint32(offset + 4, 0, true);
538
+ offset += 8;
539
+ });
540
+
541
+ // The linker guarantees global data starts from at least wasmMinDataAddr.
542
+ // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
543
+ const wasmMinDataAddr = 4096 + 8192;
544
+ if (offset >= wasmMinDataAddr) {
545
+ throw new Error("total length of command line and environment variables exceeds limit");
546
+ }
547
+
548
+ this._inst.exports.run(argc, argv);
549
+ if (this.exited) {
550
+ this._resolveExitPromise();
551
+ }
552
+ await this._exitPromise;
553
+ }
554
+
555
+ _resume() {
556
+ if (this.exited) {
557
+ throw new Error("Go program has already exited");
558
+ }
559
+ this._inst.exports.resume();
560
+ if (this.exited) {
561
+ this._resolveExitPromise();
562
+ }
563
+ }
564
+
565
+ _makeFuncWrapper(id) {
566
+ const go = this;
567
+ return function () {
568
+ const event = { id: id, this: this, args: arguments };
569
+ go._pendingEvent = event;
570
+ go._resume();
571
+ return event.result;
572
+ };
573
+ }
574
+ }
575
+ })();