@wasm-fmt/gofmt 0.4.9 → 0.5.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.
- package/README.md +13 -8
- package/gofmt.js +179 -99
- package/gofmt.wasm +0 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# Install
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@wasm-fmt/gofmt)
|
|
5
|
+
[](https://www.npmjs.com/package/@wasm-fmt/gofmt)
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @wasm-fmt/gofmt
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
[](https://jsr.io/@fmt/gofmt)
|
|
11
|
+
[](https://jsr.io/@fmt/gofmt)
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
npx jsr add @fmt/gofmt
|
|
@@ -41,14 +41,19 @@ import init, { format } from "@wasm-fmt/gofmt/vite";
|
|
|
41
41
|
# Build from source
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
# 1.
|
|
45
|
-
git clone https://github.com/wasm-fmt/gofmt.git
|
|
44
|
+
# 1. install Go https://go.dev/doc/install
|
|
46
45
|
|
|
47
46
|
# 2. install TinyGo https://tinygo.org/getting-started/install/
|
|
48
47
|
|
|
49
|
-
# 3.
|
|
50
|
-
|
|
48
|
+
# 3. clone this repo
|
|
49
|
+
git clone https://github.com/wasm-fmt/gofmt.git
|
|
50
|
+
|
|
51
|
+
# 4. install dependencies inside the repo
|
|
52
|
+
npm install
|
|
53
|
+
|
|
54
|
+
# 5. build
|
|
55
|
+
npm run build
|
|
51
56
|
|
|
52
|
-
#
|
|
53
|
-
|
|
57
|
+
# 6. test
|
|
58
|
+
npm run /^test:/
|
|
54
59
|
```
|
package/gofmt.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
/* @ts-self-types="./gofmt.d.ts" */
|
|
1
2
|
// Copyright 2018 The Go Authors. All rights reserved.
|
|
2
3
|
// Use of this source code is governed by a BSD-style
|
|
3
4
|
// license that can be found in the LICENSE file.
|
|
4
5
|
//
|
|
5
6
|
// This file has been modified for use by the TinyGo compiler.
|
|
6
7
|
|
|
8
|
+
// End of polyfills for common API.
|
|
9
|
+
|
|
7
10
|
const encoder = new TextEncoder("utf-8");
|
|
8
11
|
const decoder = new TextDecoder("utf-8");
|
|
9
12
|
let reinterpretBuf = new DataView(new ArrayBuffer(8));
|
|
10
13
|
var logLine = [];
|
|
14
|
+
const wasmExit = {}; // thrown to exit via proc_exit (not an error)
|
|
11
15
|
|
|
12
16
|
class Go {
|
|
13
17
|
constructor() {
|
|
@@ -115,33 +119,78 @@
|
|
|
115
119
|
this.importObject = {
|
|
116
120
|
wasi_snapshot_preview1: {
|
|
117
121
|
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
|
|
118
|
-
fd_write: (
|
|
122
|
+
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
|
123
|
+
let nwritten = 0;
|
|
124
|
+
if (fd == 1) {
|
|
125
|
+
for (let iovs_i=0; iovs_i<iovs_len;iovs_i++) {
|
|
126
|
+
let iov_ptr = iovs_ptr+iovs_i*8; // assuming wasm32
|
|
127
|
+
let ptr = mem().getUint32(iov_ptr + 0, true);
|
|
128
|
+
let len = mem().getUint32(iov_ptr + 4, true);
|
|
129
|
+
nwritten += len;
|
|
130
|
+
for (let i=0; i<len; i++) {
|
|
131
|
+
let c = mem().getUint8(ptr+i);
|
|
132
|
+
if (c == 13) { // CR
|
|
133
|
+
// ignore
|
|
134
|
+
} else if (c == 10) { // LF
|
|
135
|
+
// write line
|
|
136
|
+
let line = decoder.decode(new Uint8Array(logLine));
|
|
137
|
+
logLine = [];
|
|
138
|
+
console.log(line);
|
|
139
|
+
} else {
|
|
140
|
+
logLine.push(c);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
console.error('invalid file descriptor:', fd);
|
|
146
|
+
}
|
|
147
|
+
mem().setUint32(nwritten_ptr, nwritten, true);
|
|
148
|
+
return 0;
|
|
149
|
+
},
|
|
150
|
+
/* removed fd_close */ // dummy
|
|
151
|
+
/* removed fd_fdstat_get */ // dummy
|
|
152
|
+
/* removed fd_seek */ // dummy
|
|
153
|
+
proc_exit: (code) => {
|
|
154
|
+
this.exited = true;
|
|
155
|
+
this.exitCode = code;
|
|
156
|
+
this._resolveExitPromise();
|
|
157
|
+
throw wasmExit;
|
|
158
|
+
},
|
|
159
|
+
random_get: (bufPtr, bufLen) => {
|
|
160
|
+
crypto.getRandomValues(loadSlice(bufPtr, bufLen));
|
|
161
|
+
return 0;
|
|
162
|
+
},
|
|
119
163
|
},
|
|
120
164
|
gojs: {
|
|
121
|
-
// func ticks()
|
|
165
|
+
// func ticks() int64
|
|
122
166
|
"runtime.ticks": () => {
|
|
123
|
-
return timeOrigin + performance.now();
|
|
167
|
+
return BigInt((timeOrigin + performance.now()) * 1e6);
|
|
124
168
|
},
|
|
125
169
|
|
|
170
|
+
// func sleepTicks(timeout int64)
|
|
171
|
+
/* removed runtime.sleepTicks */
|
|
172
|
+
|
|
126
173
|
// func finalizeRef(v ref)
|
|
127
174
|
"syscall/js.finalizeRef": (v_ref) => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (f === 0 || !isNaN(f)) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
175
|
+
// Note: TinyGo does not support finalizers so this is only called
|
|
176
|
+
// for one specific case, by js.go:jsString. and can/might leak memory.
|
|
133
177
|
const id = v_ref & 0xffffffffn;
|
|
134
|
-
this._goRefCounts[id]
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
178
|
+
if (this._goRefCounts?.[id] !== undefined) {
|
|
179
|
+
this._goRefCounts[id]--;
|
|
180
|
+
if (this._goRefCounts[id] === 0) {
|
|
181
|
+
const v = this._values[id];
|
|
182
|
+
this._values[id] = null;
|
|
183
|
+
this._ids.delete(v);
|
|
184
|
+
this._idPool.push(id);
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
console.error("syscall/js.finalizeRef: unknown id", id);
|
|
140
188
|
}
|
|
141
189
|
},
|
|
142
190
|
|
|
143
191
|
// func stringVal(value string) ref
|
|
144
192
|
"syscall/js.stringVal": (value_ptr, value_len) => {
|
|
193
|
+
value_ptr >>>= 0;
|
|
145
194
|
const s = loadString(value_ptr, value_len);
|
|
146
195
|
return boxValue(s);
|
|
147
196
|
},
|
|
@@ -162,6 +211,9 @@
|
|
|
162
211
|
Reflect.set(v, p, x);
|
|
163
212
|
},
|
|
164
213
|
|
|
214
|
+
// func valueDelete(v ref, p string)
|
|
215
|
+
/* removed syscall/js.valueDelete */
|
|
216
|
+
|
|
165
217
|
// func valueIndex(v ref, i int) ref
|
|
166
218
|
"syscall/js.valueIndex": (v_ref, i) => {
|
|
167
219
|
return boxValue(Reflect.get(unboxValue(v_ref), i));
|
|
@@ -187,6 +239,9 @@
|
|
|
187
239
|
}
|
|
188
240
|
},
|
|
189
241
|
|
|
242
|
+
// func valueInvoke(v ref, args []ref) (ref, bool)
|
|
243
|
+
/* removed syscall/js.valueInvoke */
|
|
244
|
+
|
|
190
245
|
// func valueNew(v ref, args []ref) (ref, bool)
|
|
191
246
|
"syscall/js.valueNew": (ret_addr, v_ref, args_ptr, args_len, args_cap) => {
|
|
192
247
|
const v = unboxValue(v_ref);
|
|
@@ -218,6 +273,17 @@
|
|
|
218
273
|
const str = unboxValue(v_ref);
|
|
219
274
|
loadSlice(slice_ptr, slice_len, slice_cap).set(str);
|
|
220
275
|
},
|
|
276
|
+
|
|
277
|
+
// func valueInstanceOf(v ref, t ref) bool
|
|
278
|
+
/* removed syscall/js.valueInstanceOf */
|
|
279
|
+
|
|
280
|
+
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
|
281
|
+
/* removed syscall/js.copyBytesToGo */
|
|
282
|
+
|
|
283
|
+
// copyBytesToJS(dst ref, src []byte) (int, bool)
|
|
284
|
+
// Originally copied from upstream Go project, then modified:
|
|
285
|
+
// https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416
|
|
286
|
+
/* removed syscall/js.copyBytesToJS */
|
|
221
287
|
}
|
|
222
288
|
};
|
|
223
289
|
|
|
@@ -234,33 +300,32 @@
|
|
|
234
300
|
null,
|
|
235
301
|
true,
|
|
236
302
|
false,
|
|
237
|
-
|
|
238
|
-
{
|
|
239
|
-
set format(fn){ instance.format = fn; },
|
|
240
|
-
Array,
|
|
241
|
-
Object,
|
|
242
|
-
},
|
|
303
|
+
/* fake global */ { set format(fn) { instance.format = fn }, Array, Object},
|
|
243
304
|
this,
|
|
244
305
|
];
|
|
245
306
|
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
|
|
246
307
|
this._ids = new Map(); // mapping from JS values to reference ids
|
|
247
308
|
this._idPool = []; // unused ids that have been garbage collected
|
|
248
309
|
this.exited = false; // whether the Go program has exited
|
|
310
|
+
this.exitCode = 0;
|
|
249
311
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
this.
|
|
253
|
-
if (this.exited) {
|
|
254
|
-
throw new Error("bad callback: Go program has already exited");
|
|
255
|
-
}
|
|
256
|
-
setTimeout(resolve, 0); // make sure it is asynchronous
|
|
257
|
-
};
|
|
312
|
+
if (this._inst.exports._start) {
|
|
313
|
+
let exitPromise = new Promise((resolve, reject) => {
|
|
314
|
+
this._resolveExitPromise = resolve;
|
|
258
315
|
});
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
316
|
+
|
|
317
|
+
// Run program, but catch the wasmExit exception that's thrown
|
|
318
|
+
// to return back here.
|
|
319
|
+
try {
|
|
320
|
+
this._inst.exports._start();
|
|
321
|
+
} catch (e) {
|
|
322
|
+
if (e !== wasmExit) throw e;
|
|
262
323
|
}
|
|
263
|
-
|
|
324
|
+
|
|
325
|
+
await exitPromise;
|
|
326
|
+
return this.exitCode;
|
|
327
|
+
} else {
|
|
328
|
+
this._inst.exports._initialize();
|
|
264
329
|
}
|
|
265
330
|
}
|
|
266
331
|
|
|
@@ -268,7 +333,11 @@
|
|
|
268
333
|
if (this.exited) {
|
|
269
334
|
throw new Error("Go program has already exited");
|
|
270
335
|
}
|
|
271
|
-
|
|
336
|
+
try {
|
|
337
|
+
this._inst.exports.resume();
|
|
338
|
+
} catch (e) {
|
|
339
|
+
if (e !== wasmExit) throw e;
|
|
340
|
+
}
|
|
272
341
|
if (this.exited) {
|
|
273
342
|
this._resolveExitPromise();
|
|
274
343
|
}
|
|
@@ -284,72 +353,83 @@
|
|
|
284
353
|
};
|
|
285
354
|
}
|
|
286
355
|
}
|
|
287
|
-
|
|
288
356
|
/**
|
|
289
357
|
* ================== End of wasm_exec.js ==================
|
|
290
358
|
*/
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
359
|
+
let wasm;
|
|
360
|
+
async function __load(module, imports) {
|
|
361
|
+
if (typeof Response === "function" && module instanceof Response) {
|
|
362
|
+
if (typeof WebAssembly.instantiateStreaming === "function") {
|
|
363
|
+
try {
|
|
364
|
+
return await WebAssembly.instantiateStreaming(module, imports);
|
|
365
|
+
} catch (e) {
|
|
366
|
+
if (module.headers.get("Content-Type") != "application/wasm") {
|
|
367
|
+
console.warn(
|
|
368
|
+
"`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",
|
|
369
|
+
e,
|
|
370
|
+
);
|
|
371
|
+
} else {
|
|
372
|
+
throw e;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const bytes = await module.arrayBuffer();
|
|
377
|
+
return await WebAssembly.instantiate(bytes, imports);
|
|
378
|
+
} else {
|
|
379
|
+
const instance = await WebAssembly.instantiate(module, imports);
|
|
380
|
+
if (instance instanceof WebAssembly.Instance)
|
|
381
|
+
return { instance, module };
|
|
382
|
+
else return instance;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
function __finalize_init(instance) {
|
|
386
|
+
return (wasm = instance);
|
|
387
|
+
}
|
|
388
|
+
function __init_memory(imports, maybe_memory) {}
|
|
389
|
+
export function initSync(module) {
|
|
390
|
+
if (wasm !== undefined) return wasm;
|
|
391
|
+
|
|
392
|
+
const go = new Go();
|
|
393
|
+
const imports = go.importObject;
|
|
394
|
+
|
|
395
|
+
__init_memory(imports);
|
|
396
|
+
|
|
397
|
+
if (!(module instanceof WebAssembly.Module))
|
|
398
|
+
module = new WebAssembly.Module(module);
|
|
399
|
+
|
|
400
|
+
const instance = new WebAssembly.Instance(module, imports);
|
|
401
|
+
|
|
402
|
+
go.run(instance);
|
|
403
|
+
return __finalize_init(instance, module);
|
|
404
|
+
}
|
|
405
|
+
export default async function initAsync(input) {
|
|
406
|
+
if (wasm !== undefined) return wasm;
|
|
407
|
+
|
|
408
|
+
if (typeof input === "undefined")
|
|
409
|
+
input = new URL("gofmt.wasm", import.meta.url);
|
|
410
|
+
|
|
411
|
+
const go = new Go();
|
|
412
|
+
const imports = go.importObject;
|
|
413
|
+
|
|
414
|
+
if (
|
|
415
|
+
typeof input === "string" ||
|
|
416
|
+
(typeof Request === "function" && input instanceof Request) ||
|
|
417
|
+
(typeof URL === "function" && input instanceof URL)
|
|
418
|
+
) {
|
|
419
|
+
input = fetch(input);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
__init_memory(imports);
|
|
423
|
+
|
|
424
|
+
const { instance, module } = await __load(await input, imports);
|
|
425
|
+
|
|
426
|
+
go.run(instance);
|
|
427
|
+
return __finalize_init(instance, module);
|
|
428
|
+
}
|
|
429
|
+
export function format(input) {
|
|
430
|
+
const [err, result] = wasm.format(input);
|
|
431
|
+
if (err) {
|
|
432
|
+
throw new Error(result);
|
|
433
|
+
}
|
|
434
|
+
return result;
|
|
435
|
+
}
|
package/gofmt.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@wasm-fmt/gofmt",
|
|
3
3
|
"description": "A wasm based golang formatter",
|
|
4
4
|
"author": "magic-akari <akari.ccino@gamil.com>",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.5.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"wasm",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "./scripts/build.sh",
|
|
39
|
-
"test:node": "node --test test_node",
|
|
39
|
+
"test:node": "node --test test_node/node.test.js",
|
|
40
40
|
"test:deno": "deno test test_deno --allow-read",
|
|
41
41
|
"test:bun": "bun test test_bun"
|
|
42
42
|
},
|
|
@@ -45,5 +45,8 @@
|
|
|
45
45
|
},
|
|
46
46
|
"publishConfig": {
|
|
47
47
|
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@ast-grep/napi": "0.40.0"
|
|
48
51
|
}
|
|
49
52
|
}
|