@wasm-fmt/gofmt 0.5.0 → 0.6.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/CHANGELOG.md +11 -0
- package/README.md +37 -8
- package/gofmt.d.wasm.ts +11 -0
- package/gofmt.js +36 -422
- package/gofmt.wasm +0 -0
- package/gofmt_bundle.js +16 -0
- package/gofmt_entry.d.ts +11 -0
- package/gofmt_esm.js +23 -0
- package/gofmt_node.js +24 -7
- package/gofmt_vite.js +34 -5
- package/gofmt_web.d.ts +20 -0
- package/gofmt_web.js +90 -0
- package/package.json +24 -10
- package/gofmt.d.ts +0 -10
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.6.0]
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
- **Entry point change:** The default entry point has been restructured. If you are upgrading from a version below 0.6.0 and want the previous behavior, import from `@wasm-fmt/gofmt/web` instead of the default entry point.
|
package/README.md
CHANGED
|
@@ -16,8 +16,28 @@ npx jsr add @fmt/gofmt
|
|
|
16
16
|
|
|
17
17
|
# Usage
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
## Node.js / Deno / Bun / Bundler
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
import { format } from "@wasm-fmt/gofmt";
|
|
23
|
+
|
|
24
|
+
const source = `
|
|
25
|
+
package main
|
|
26
|
+
import "fmt"
|
|
27
|
+
func main(){fmt.Println("Hello, 世界")
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const formatted = format(source);
|
|
32
|
+
console.log(formatted);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Web
|
|
36
|
+
|
|
37
|
+
For web environments, you need to initialize WASM module manually:
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
import init, { format } from "@wasm-fmt/gofmt/web";
|
|
21
41
|
|
|
22
42
|
await init();
|
|
23
43
|
|
|
@@ -32,12 +52,24 @@ const formatted = format(source);
|
|
|
32
52
|
console.log(formatted);
|
|
33
53
|
```
|
|
34
54
|
|
|
35
|
-
Vite
|
|
55
|
+
### Vite
|
|
36
56
|
|
|
37
57
|
```JavaScript
|
|
38
58
|
import init, { format } from "@wasm-fmt/gofmt/vite";
|
|
59
|
+
|
|
60
|
+
await init();
|
|
61
|
+
// ...
|
|
39
62
|
```
|
|
40
63
|
|
|
64
|
+
## Entry Points
|
|
65
|
+
|
|
66
|
+
- `.` - Auto-detects environment (Node.js uses node, Webpack uses bundler, default is ESM)
|
|
67
|
+
- `./node` - Node.js environment (no init required)
|
|
68
|
+
- `./esm` - ESM environments like Deno (no init required)
|
|
69
|
+
- `./bundler` - Bundlers like Webpack (no init required)
|
|
70
|
+
- `./web` - Web browsers (requires manual init)
|
|
71
|
+
- `./vite` - Vite bundler (requires manual init)
|
|
72
|
+
|
|
41
73
|
# Build from source
|
|
42
74
|
|
|
43
75
|
```bash
|
|
@@ -48,12 +80,9 @@ import init, { format } from "@wasm-fmt/gofmt/vite";
|
|
|
48
80
|
# 3. clone this repo
|
|
49
81
|
git clone https://github.com/wasm-fmt/gofmt.git
|
|
50
82
|
|
|
51
|
-
# 4.
|
|
52
|
-
npm install
|
|
53
|
-
|
|
54
|
-
# 5. build
|
|
83
|
+
# 4. build
|
|
55
84
|
npm run build
|
|
56
85
|
|
|
57
86
|
# 6. test
|
|
58
|
-
npm run
|
|
87
|
+
npm run test:node
|
|
59
88
|
```
|
package/gofmt.d.wasm.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebAssembly module for gofmt.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
export declare const memory: WebAssembly.Memory;
|
|
6
|
+
export declare function _initialize(): void;
|
|
7
|
+
export declare function alloc(size: number): number;
|
|
8
|
+
export declare function dispose(): void;
|
|
9
|
+
export declare function format(): 0 | 1 | 2;
|
|
10
|
+
export declare function output_ptr(): number;
|
|
11
|
+
export declare function output_len(): number;
|
package/gofmt.js
CHANGED
|
@@ -1,435 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// license that can be found in the LICENSE file.
|
|
5
|
-
//
|
|
6
|
-
// This file has been modified for use by the TinyGo compiler.
|
|
7
|
-
|
|
8
|
-
// End of polyfills for common API.
|
|
9
|
-
|
|
10
|
-
const encoder = new TextEncoder("utf-8");
|
|
11
|
-
const decoder = new TextDecoder("utf-8");
|
|
12
|
-
let reinterpretBuf = new DataView(new ArrayBuffer(8));
|
|
13
|
-
var logLine = [];
|
|
14
|
-
const wasmExit = {}; // thrown to exit via proc_exit (not an error)
|
|
15
|
-
|
|
16
|
-
class Go {
|
|
17
|
-
constructor() {
|
|
18
|
-
this._callbackTimeouts = new Map();
|
|
19
|
-
this._nextCallbackTimeoutID = 1;
|
|
20
|
-
|
|
21
|
-
const mem = () => {
|
|
22
|
-
// The buffer may change when requesting more memory.
|
|
23
|
-
return new DataView(this._inst.exports.memory.buffer);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const unboxValue = (v_ref) => {
|
|
27
|
-
reinterpretBuf.setBigInt64(0, v_ref, true);
|
|
28
|
-
const f = reinterpretBuf.getFloat64(0, true);
|
|
29
|
-
if (f === 0) {
|
|
30
|
-
return undefined;
|
|
31
|
-
}
|
|
32
|
-
if (!isNaN(f)) {
|
|
33
|
-
return f;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const id = v_ref & 0xffffffffn;
|
|
37
|
-
return this._values[id];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const loadValue = (addr) => {
|
|
42
|
-
let v_ref = mem().getBigUint64(addr, true);
|
|
43
|
-
return unboxValue(v_ref);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const boxValue = (v) => {
|
|
47
|
-
const nanHead = 0x7FF80000n;
|
|
48
|
-
|
|
49
|
-
if (typeof v === "number") {
|
|
50
|
-
if (isNaN(v)) {
|
|
51
|
-
return nanHead << 32n;
|
|
52
|
-
}
|
|
53
|
-
if (v === 0) {
|
|
54
|
-
return (nanHead << 32n) | 1n;
|
|
55
|
-
}
|
|
56
|
-
reinterpretBuf.setFloat64(0, v, true);
|
|
57
|
-
return reinterpretBuf.getBigInt64(0, true);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
switch (v) {
|
|
61
|
-
case undefined:
|
|
62
|
-
return 0n;
|
|
63
|
-
case null:
|
|
64
|
-
return (nanHead << 32n) | 2n;
|
|
65
|
-
case true:
|
|
66
|
-
return (nanHead << 32n) | 3n;
|
|
67
|
-
case false:
|
|
68
|
-
return (nanHead << 32n) | 4n;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let id = this._ids.get(v);
|
|
72
|
-
if (id === undefined) {
|
|
73
|
-
id = this._idPool.pop();
|
|
74
|
-
if (id === undefined) {
|
|
75
|
-
id = BigInt(this._values.length);
|
|
76
|
-
}
|
|
77
|
-
this._values[id] = v;
|
|
78
|
-
this._goRefCounts[id] = 0;
|
|
79
|
-
this._ids.set(v, id);
|
|
80
|
-
}
|
|
81
|
-
this._goRefCounts[id]++;
|
|
82
|
-
let typeFlag = 1n;
|
|
83
|
-
switch (typeof v) {
|
|
84
|
-
case "string":
|
|
85
|
-
typeFlag = 2n;
|
|
86
|
-
break;
|
|
87
|
-
case "symbol":
|
|
88
|
-
typeFlag = 3n;
|
|
89
|
-
break;
|
|
90
|
-
case "function":
|
|
91
|
-
typeFlag = 4n;
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
return id | ((nanHead | typeFlag) << 32n);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const storeValue = (addr, v) => {
|
|
98
|
-
let v_ref = boxValue(v);
|
|
99
|
-
mem().setBigUint64(addr, v_ref, true);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const loadSlice = (array, len, cap) => {
|
|
103
|
-
return new Uint8Array(this._inst.exports.memory.buffer, array, len);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const loadSliceOfValues = (array, len, cap) => {
|
|
107
|
-
const a = new Array(len);
|
|
108
|
-
for (let i = 0; i < len; i++) {
|
|
109
|
-
a[i] = loadValue(array + i * 8);
|
|
110
|
-
}
|
|
111
|
-
return a;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const loadString = (ptr, len) => {
|
|
115
|
-
return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const timeOrigin = Date.now() - performance.now();
|
|
119
|
-
this.importObject = {
|
|
120
|
-
wasi_snapshot_preview1: {
|
|
121
|
-
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#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
|
-
},
|
|
163
|
-
},
|
|
164
|
-
gojs: {
|
|
165
|
-
// func ticks() int64
|
|
166
|
-
"runtime.ticks": () => {
|
|
167
|
-
return BigInt((timeOrigin + performance.now()) * 1e6);
|
|
168
|
-
},
|
|
169
|
-
|
|
170
|
-
// func sleepTicks(timeout int64)
|
|
171
|
-
/* removed runtime.sleepTicks */
|
|
172
|
-
|
|
173
|
-
// func finalizeRef(v ref)
|
|
174
|
-
"syscall/js.finalizeRef": (v_ref) => {
|
|
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.
|
|
177
|
-
const id = v_ref & 0xffffffffn;
|
|
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);
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
// func stringVal(value string) ref
|
|
192
|
-
"syscall/js.stringVal": (value_ptr, value_len) => {
|
|
193
|
-
value_ptr >>>= 0;
|
|
194
|
-
const s = loadString(value_ptr, value_len);
|
|
195
|
-
return boxValue(s);
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
// func valueGet(v ref, p string) ref
|
|
199
|
-
"syscall/js.valueGet": (v_ref, p_ptr, p_len) => {
|
|
200
|
-
let prop = loadString(p_ptr, p_len);
|
|
201
|
-
let v = unboxValue(v_ref);
|
|
202
|
-
let result = Reflect.get(v, prop);
|
|
203
|
-
return boxValue(result);
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
// func valueSet(v ref, p string, x ref)
|
|
207
|
-
"syscall/js.valueSet": (v_ref, p_ptr, p_len, x_ref) => {
|
|
208
|
-
const v = unboxValue(v_ref);
|
|
209
|
-
const p = loadString(p_ptr, p_len);
|
|
210
|
-
const x = unboxValue(x_ref);
|
|
211
|
-
Reflect.set(v, p, x);
|
|
212
|
-
},
|
|
213
|
-
|
|
214
|
-
// func valueDelete(v ref, p string)
|
|
215
|
-
/* removed syscall/js.valueDelete */
|
|
216
|
-
|
|
217
|
-
// func valueIndex(v ref, i int) ref
|
|
218
|
-
"syscall/js.valueIndex": (v_ref, i) => {
|
|
219
|
-
return boxValue(Reflect.get(unboxValue(v_ref), i));
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
// valueSetIndex(v ref, i int, x ref)
|
|
223
|
-
"syscall/js.valueSetIndex": (v_ref, i, x_ref) => {
|
|
224
|
-
Reflect.set(unboxValue(v_ref), i, unboxValue(x_ref));
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
|
228
|
-
"syscall/js.valueCall": (ret_addr, v_ref, m_ptr, m_len, args_ptr, args_len, args_cap) => {
|
|
229
|
-
const v = unboxValue(v_ref);
|
|
230
|
-
const name = loadString(m_ptr, m_len);
|
|
231
|
-
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
232
|
-
try {
|
|
233
|
-
const m = Reflect.get(v, name);
|
|
234
|
-
storeValue(ret_addr, Reflect.apply(m, v, args));
|
|
235
|
-
mem().setUint8(ret_addr + 8, 1);
|
|
236
|
-
} catch (err) {
|
|
237
|
-
storeValue(ret_addr, err);
|
|
238
|
-
mem().setUint8(ret_addr + 8, 0);
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
|
-
|
|
242
|
-
// func valueInvoke(v ref, args []ref) (ref, bool)
|
|
243
|
-
/* removed syscall/js.valueInvoke */
|
|
244
|
-
|
|
245
|
-
// func valueNew(v ref, args []ref) (ref, bool)
|
|
246
|
-
"syscall/js.valueNew": (ret_addr, v_ref, args_ptr, args_len, args_cap) => {
|
|
247
|
-
const v = unboxValue(v_ref);
|
|
248
|
-
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
249
|
-
try {
|
|
250
|
-
storeValue(ret_addr, Reflect.construct(v, args));
|
|
251
|
-
mem().setUint8(ret_addr + 8, 1);
|
|
252
|
-
} catch (err) {
|
|
253
|
-
storeValue(ret_addr, err);
|
|
254
|
-
mem().setUint8(ret_addr+ 8, 0);
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
|
|
258
|
-
// func valueLength(v ref) int
|
|
259
|
-
"syscall/js.valueLength": (v_ref) => {
|
|
260
|
-
return unboxValue(v_ref).length;
|
|
261
|
-
},
|
|
262
|
-
|
|
263
|
-
// valuePrepareString(v ref) (ref, int)
|
|
264
|
-
"syscall/js.valuePrepareString": (ret_addr, v_ref) => {
|
|
265
|
-
const s = String(unboxValue(v_ref));
|
|
266
|
-
const str = encoder.encode(s);
|
|
267
|
-
storeValue(ret_addr, str);
|
|
268
|
-
mem().setInt32(ret_addr + 8, str.length, true);
|
|
269
|
-
},
|
|
270
|
-
|
|
271
|
-
// valueLoadString(v ref, b []byte)
|
|
272
|
-
"syscall/js.valueLoadString": (v_ref, slice_ptr, slice_len, slice_cap) => {
|
|
273
|
-
const str = unboxValue(v_ref);
|
|
274
|
-
loadSlice(slice_ptr, slice_len, slice_cap).set(str);
|
|
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 */
|
|
287
|
-
}
|
|
288
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* @import * as WASM from "./gofmt.wasm"
|
|
3
|
+
*/
|
|
289
4
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
5
|
+
/**
|
|
6
|
+
* @param {WASM} wasm
|
|
7
|
+
* @param {string} source
|
|
8
|
+
* @return {string}
|
|
9
|
+
*/
|
|
10
|
+
export function format(wasm, source) {
|
|
11
|
+
try {
|
|
12
|
+
writeStringToWasmMemory(wasm, source);
|
|
13
|
+
const result = wasm.format();
|
|
14
|
+
if (result === 0) {
|
|
15
|
+
return source;
|
|
293
16
|
}
|
|
294
17
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
NaN,
|
|
299
|
-
0,
|
|
300
|
-
null,
|
|
301
|
-
true,
|
|
302
|
-
false,
|
|
303
|
-
/* fake global */ { set format(fn) { instance.format = fn }, Array, Object},
|
|
304
|
-
this,
|
|
305
|
-
];
|
|
306
|
-
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
|
|
307
|
-
this._ids = new Map(); // mapping from JS values to reference ids
|
|
308
|
-
this._idPool = []; // unused ids that have been garbage collected
|
|
309
|
-
this.exited = false; // whether the Go program has exited
|
|
310
|
-
this.exitCode = 0;
|
|
311
|
-
|
|
312
|
-
if (this._inst.exports._start) {
|
|
313
|
-
let exitPromise = new Promise((resolve, reject) => {
|
|
314
|
-
this._resolveExitPromise = resolve;
|
|
315
|
-
});
|
|
18
|
+
const ptr = wasm.output_ptr();
|
|
19
|
+
const length = wasm.output_len();
|
|
20
|
+
const text = readStringFromWasmMemory(wasm, ptr, length);
|
|
316
21
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
try {
|
|
320
|
-
this._inst.exports._start();
|
|
321
|
-
} catch (e) {
|
|
322
|
-
if (e !== wasmExit) throw e;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
await exitPromise;
|
|
326
|
-
return this.exitCode;
|
|
327
|
-
} else {
|
|
328
|
-
this._inst.exports._initialize();
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
_resume() {
|
|
333
|
-
if (this.exited) {
|
|
334
|
-
throw new Error("Go program has already exited");
|
|
335
|
-
}
|
|
336
|
-
try {
|
|
337
|
-
this._inst.exports.resume();
|
|
338
|
-
} catch (e) {
|
|
339
|
-
if (e !== wasmExit) throw e;
|
|
340
|
-
}
|
|
341
|
-
if (this.exited) {
|
|
342
|
-
this._resolveExitPromise();
|
|
343
|
-
}
|
|
22
|
+
if (result === 1) {
|
|
23
|
+
return text;
|
|
344
24
|
}
|
|
345
25
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const event = { id: id, this: this, args: arguments };
|
|
350
|
-
go._pendingEvent = event;
|
|
351
|
-
go._resume();
|
|
352
|
-
return event.result;
|
|
353
|
-
};
|
|
354
|
-
}
|
|
26
|
+
throw new Error(text);
|
|
27
|
+
} finally {
|
|
28
|
+
wasm.dispose();
|
|
355
29
|
}
|
|
30
|
+
}
|
|
31
|
+
|
|
356
32
|
/**
|
|
357
|
-
*
|
|
33
|
+
* @param {WASM} wasm
|
|
34
|
+
* @param {string} str
|
|
358
35
|
*/
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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);
|
|
36
|
+
function writeStringToWasmMemory(wasm, str) {
|
|
37
|
+
const bytes = encoder.encode(str);
|
|
38
|
+
const ptr = wasm.alloc(bytes.length);
|
|
39
|
+
const memory = new Uint8Array(wasm.memory.buffer, ptr, bytes.length);
|
|
40
|
+
memory.set(bytes);
|
|
387
41
|
}
|
|
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
42
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
const instance = new WebAssembly.Instance(module, imports);
|
|
401
|
-
|
|
402
|
-
go.run(instance);
|
|
403
|
-
return __finalize_init(instance, module);
|
|
43
|
+
function readStringFromWasmMemory(wasm, ptr, length) {
|
|
44
|
+
const memory = new Uint8Array(wasm.memory.buffer, ptr, length);
|
|
45
|
+
return decoder.decode(memory);
|
|
404
46
|
}
|
|
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
47
|
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
}
|
|
48
|
+
const encoder = new TextEncoder();
|
|
49
|
+
const decoder = new TextDecoder();
|
package/gofmt.wasm
CHANGED
|
Binary file
|
package/gofmt_bundle.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import wasm from "./gofmt.wasm";
|
|
2
|
+
import { format as _format } from "./gofmt.js";
|
|
3
|
+
|
|
4
|
+
wasm._initialize();
|
|
5
|
+
|
|
6
|
+
export function initSync() {
|
|
7
|
+
return wasm;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default async function initAsync() {
|
|
11
|
+
return wasm;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function format(source) {
|
|
15
|
+
return _format(wasm, source);
|
|
16
|
+
}
|
package/gofmt_entry.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gofmt default entry for formatting Go source code.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Formats a Go source code.
|
|
8
|
+
* @param input - The Go source code to format
|
|
9
|
+
* @returns The formatted Go source code
|
|
10
|
+
*/
|
|
11
|
+
export declare function format(input: string): string;
|
package/gofmt_esm.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* @ts-self-types="./gofmt_entry.d.ts" */
|
|
2
|
+
/**
|
|
3
|
+
* Loads the Wasm module via source phase import.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
// prettier-ignore
|
|
7
|
+
import source wasmModule from "./gofmt.wasm";
|
|
8
|
+
import { format as _format } from "./gofmt.js";
|
|
9
|
+
/**
|
|
10
|
+
* @import * as WASM from "./gofmt.wasm"
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const instance = new WebAssembly.Instance(wasmModule);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @type {WASM}
|
|
17
|
+
*/
|
|
18
|
+
const wasm = instance.exports;
|
|
19
|
+
wasm._initialize();
|
|
20
|
+
|
|
21
|
+
export function format(source) {
|
|
22
|
+
return _format(wasm, source);
|
|
23
|
+
}
|
package/gofmt_node.js
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* @ts-self-types="./gofmt_entry.d.ts" */
|
|
2
|
+
/**
|
|
3
|
+
* Loads the Wasm module using Node's fs API.
|
|
4
|
+
* Consider using `./esm` entry if your environment supports source phase import.
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { format as _format } from "./gofmt.js";
|
|
3
9
|
|
|
4
|
-
const
|
|
10
|
+
const wasmUrl = new URL("gofmt.wasm", import.meta.url);
|
|
11
|
+
const wasmBytes = readFileSync(wasmUrl);
|
|
12
|
+
const wasmModule = new WebAssembly.Module(wasmBytes);
|
|
5
13
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @import * as WASM from "./gofmt.wasm"
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const instance = new WebAssembly.Instance(wasmModule);
|
|
19
|
+
/**
|
|
20
|
+
* @type {WASM}
|
|
21
|
+
*/
|
|
22
|
+
const wasm = instance.exports;
|
|
23
|
+
wasm._initialize();
|
|
9
24
|
|
|
10
|
-
export
|
|
25
|
+
export function format(source) {
|
|
26
|
+
return _format(wasm, source);
|
|
27
|
+
}
|
package/gofmt_vite.js
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* @ts-self-types="./gofmt_web.d.ts" */
|
|
2
|
+
/**
|
|
3
|
+
* Loads the Wasm module for Vite and bundlers supporting `?init` imports.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import init from "./gofmt.wasm?init";
|
|
7
|
+
import initAsync from "./gofmt_web.js";
|
|
8
|
+
import { format as _format } from "./gofmt.js";
|
|
3
9
|
|
|
4
|
-
|
|
5
|
-
|
|
10
|
+
let wasm, wasmModule;
|
|
11
|
+
|
|
12
|
+
function finalize_init(instance, module) {
|
|
13
|
+
wasm = instance.exports;
|
|
14
|
+
wasmModule = module;
|
|
15
|
+
wasm._initialize();
|
|
16
|
+
return wasm;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default async function initAsync() {
|
|
20
|
+
if (wasm !== void 0) return wasm;
|
|
21
|
+
const instance = await init();
|
|
22
|
+
return finalize_init(instance);
|
|
6
23
|
}
|
|
7
24
|
|
|
8
|
-
export
|
|
25
|
+
export function initSync(module) {
|
|
26
|
+
if (wasm !== void 0) return wasm;
|
|
27
|
+
|
|
28
|
+
if (!(module instanceof WebAssembly.Module)) {
|
|
29
|
+
module = new WebAssembly.Module(module);
|
|
30
|
+
}
|
|
31
|
+
const instance = new WebAssembly.Instance(module);
|
|
32
|
+
return finalize_init(instance, module);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function format(source) {
|
|
36
|
+
return _format(wasm, source);
|
|
37
|
+
}
|
package/gofmt_web.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gofmt entry with initialization functions.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
6
|
+
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
|
7
|
+
import type * as InitOutput from "./gofmt.wasm";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Initializes the WASM module asynchronously.
|
|
11
|
+
* @param init_input - Optional URL/path to the WASM file, or any valid InitInput
|
|
12
|
+
*/
|
|
13
|
+
export default function initAsync(init_input?: InitInput): Promise<InitOutput>;
|
|
14
|
+
/**
|
|
15
|
+
* Initializes the WASM module synchronously.
|
|
16
|
+
* @param buffer_or_module - The WASM module or buffer source
|
|
17
|
+
*/
|
|
18
|
+
export declare function initSync(buffer_or_module: BufferSource | WebAssembly.Module): InitOutput;
|
|
19
|
+
|
|
20
|
+
export * from "gofmt_entry.d.ts";
|
package/gofmt_web.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* @ts-self-types="./gofmt_web.d.ts" */
|
|
2
|
+
/**
|
|
3
|
+
* Loads the Wasm module via Web Fetch API (browsers).
|
|
4
|
+
* Requires calling init().
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { format as _format } from "./gofmt.js";
|
|
8
|
+
let wasm, wasmModule;
|
|
9
|
+
|
|
10
|
+
async function load(module, imports) {
|
|
11
|
+
if (typeof Response === "function" && module instanceof Response) {
|
|
12
|
+
if (typeof WebAssembly.instantiateStreaming === "function") {
|
|
13
|
+
try {
|
|
14
|
+
return await WebAssembly.instantiateStreaming(module, imports);
|
|
15
|
+
} catch (e) {
|
|
16
|
+
const validResponse = module.ok && expectedResponseType(module.type);
|
|
17
|
+
|
|
18
|
+
if (validResponse && module.headers.get("Content-Type") !== "application/wasm") {
|
|
19
|
+
console.warn(
|
|
20
|
+
"`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",
|
|
21
|
+
e,
|
|
22
|
+
);
|
|
23
|
+
} else {
|
|
24
|
+
throw e;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const bytes = await module.arrayBuffer();
|
|
30
|
+
return await WebAssembly.instantiate(bytes, imports);
|
|
31
|
+
} else {
|
|
32
|
+
const instance = await WebAssembly.instantiate(module, imports);
|
|
33
|
+
|
|
34
|
+
if (instance instanceof WebAssembly.Instance) {
|
|
35
|
+
return { instance, module };
|
|
36
|
+
} else {
|
|
37
|
+
return instance;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function expectedResponseType(type) {
|
|
42
|
+
switch (type) {
|
|
43
|
+
case "basic":
|
|
44
|
+
case "cors":
|
|
45
|
+
case "default":
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function finalize_init(instance, module) {
|
|
53
|
+
((wasm = instance.exports), (wasmModule = module));
|
|
54
|
+
wasm._initialize();
|
|
55
|
+
return wasm;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function initSync(module) {
|
|
59
|
+
if (wasm !== void 0) return wasm;
|
|
60
|
+
|
|
61
|
+
if (!(module instanceof WebAssembly.Module)) {
|
|
62
|
+
module = new WebAssembly.Module(module);
|
|
63
|
+
}
|
|
64
|
+
const instance = new WebAssembly.Instance(module);
|
|
65
|
+
return finalize_init(instance, module);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default async function initAsync(module_or_path) {
|
|
69
|
+
if (wasm !== void 0) return wasm;
|
|
70
|
+
|
|
71
|
+
if (module_or_path === void 0) {
|
|
72
|
+
module_or_path = new URL("gofmt.wasm", import.meta.url);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (
|
|
76
|
+
typeof module_or_path === "string" ||
|
|
77
|
+
(typeof Request === "function" && module_or_path instanceof Request) ||
|
|
78
|
+
(typeof URL === "function" && module_or_path instanceof URL)
|
|
79
|
+
) {
|
|
80
|
+
module_or_path = fetch(module_or_path);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const { instance, module } = await load(await module_or_path);
|
|
84
|
+
|
|
85
|
+
return finalize_init(instance, module);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function format(source) {
|
|
89
|
+
return _format(wasm, source);
|
|
90
|
+
}
|
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.6.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"wasm",
|
|
@@ -18,24 +18,41 @@
|
|
|
18
18
|
"url": "https://github.com/wasm-fmt/gofmt/issues"
|
|
19
19
|
},
|
|
20
20
|
"type": "module",
|
|
21
|
-
"main": "gofmt.js",
|
|
22
|
-
"module": "gofmt.js",
|
|
23
|
-
"types": "gofmt.d.ts",
|
|
24
21
|
"exports": {
|
|
25
22
|
".": {
|
|
26
|
-
"types": "./
|
|
23
|
+
"types": "./gofmt_entry.d.ts",
|
|
24
|
+
"webpack": "./gofmt_bundle.js",
|
|
27
25
|
"node": "./gofmt_node.js",
|
|
28
|
-
"default": "./
|
|
26
|
+
"default": "./gofmt_esm.js"
|
|
27
|
+
},
|
|
28
|
+
"./esm": {
|
|
29
|
+
"types": "./gofmt_entry.d.ts",
|
|
30
|
+
"default": "./gofmt_esm.js"
|
|
31
|
+
},
|
|
32
|
+
"./node": {
|
|
33
|
+
"types": "./gofmt_entry.d.ts",
|
|
34
|
+
"default": "./gofmt_node.js"
|
|
35
|
+
},
|
|
36
|
+
"./bundler": {
|
|
37
|
+
"types": "./gofmt_entry.d.ts",
|
|
38
|
+
"default": "./gofmt_bundle.js"
|
|
39
|
+
},
|
|
40
|
+
"./web": {
|
|
41
|
+
"types": "./gofmt_web.d.ts",
|
|
42
|
+
"default": "./gofmt_web.js"
|
|
29
43
|
},
|
|
30
44
|
"./vite": {
|
|
31
|
-
"types": "./
|
|
45
|
+
"types": "./gofmt_web.d.ts",
|
|
32
46
|
"default": "./gofmt_vite.js"
|
|
33
47
|
},
|
|
48
|
+
"./wasm": "./gofmt.wasm",
|
|
34
49
|
"./package.json": "./package.json",
|
|
35
50
|
"./*": "./*"
|
|
36
51
|
},
|
|
37
52
|
"scripts": {
|
|
38
53
|
"build": "./scripts/build.sh",
|
|
54
|
+
"fmt": "dprint fmt",
|
|
55
|
+
"test:go": "go test ./src -v",
|
|
39
56
|
"test:node": "node --test test_node/node.test.js",
|
|
40
57
|
"test:deno": "deno test test_deno --allow-read",
|
|
41
58
|
"test:bun": "bun test test_bun"
|
|
@@ -45,8 +62,5 @@
|
|
|
45
62
|
},
|
|
46
63
|
"publishConfig": {
|
|
47
64
|
"access": "public"
|
|
48
|
-
},
|
|
49
|
-
"devDependencies": {
|
|
50
|
-
"@ast-grep/napi": "0.40.0"
|
|
51
65
|
}
|
|
52
66
|
}
|
package/gofmt.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export type InitInput =
|
|
2
|
-
| RequestInfo
|
|
3
|
-
| URL
|
|
4
|
-
| Response
|
|
5
|
-
| BufferSource
|
|
6
|
-
| WebAssembly.Module;
|
|
7
|
-
|
|
8
|
-
export default function initAsync(wasm_url?: InitInput): Promise<void>;
|
|
9
|
-
export declare function initSync(module: BufferSource | WebAssembly.Module): void;
|
|
10
|
-
export declare function format(input: string): string;
|