@meshcore-cz/meshpkt 0.1.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 +25 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +83 -0
- package/dist/meshpkt.wasm +0 -0
- package/dist/wasm.gen.d.ts +176 -0
- package/dist/wasm.gen.js +52 -0
- package/dist/wasm_exec.js +559 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @meshcore-cz/meshpkt
|
|
2
|
+
|
|
3
|
+
MeshCore radio packet codec for JavaScript and TypeScript, powered by WebAssembly.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @meshcore-cz/meshpkt
|
|
9
|
+
````
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { load } from "@meshcore-cz/meshpkt";
|
|
15
|
+
|
|
16
|
+
const meshpkt = await load();
|
|
17
|
+
|
|
18
|
+
const envelope = meshpkt.decodeEnvelope(
|
|
19
|
+
"your-hex-encoded-meshcore-packet"
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
console.log(envelope);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The package includes the TinyGo WebAssembly module and generated TypeScript types.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export * from "./wasm.gen.js";
|
|
2
|
+
import { meshcoreOpNames } from "./wasm.gen.js";
|
|
3
|
+
const globals = globalThis;
|
|
4
|
+
let runtimeReady;
|
|
5
|
+
let apiReady;
|
|
6
|
+
function urlString(url) {
|
|
7
|
+
return typeof url === "string" ? url : url.href;
|
|
8
|
+
}
|
|
9
|
+
async function loadTinyGoRuntime(url) {
|
|
10
|
+
if (globals.Go)
|
|
11
|
+
return;
|
|
12
|
+
runtimeReady ??= new Promise((resolve, reject) => {
|
|
13
|
+
if (typeof document === "undefined") {
|
|
14
|
+
reject(new Error("@meshcore-cz/meshpkt currently requires a browser environment"));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const script = document.createElement("script");
|
|
18
|
+
script.src = urlString(url);
|
|
19
|
+
script.async = true;
|
|
20
|
+
script.onload = () => {
|
|
21
|
+
if (!globals.Go) {
|
|
22
|
+
reject(new Error("TinyGo runtime loaded but globalThis.Go was not registered"));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
resolve();
|
|
26
|
+
};
|
|
27
|
+
script.onerror = () => {
|
|
28
|
+
reject(new Error(`Failed to load TinyGo runtime: ${script.src}`));
|
|
29
|
+
};
|
|
30
|
+
document.head.appendChild(script);
|
|
31
|
+
});
|
|
32
|
+
return runtimeReady;
|
|
33
|
+
}
|
|
34
|
+
async function instantiate(url, imports) {
|
|
35
|
+
const response = await fetch(urlString(url));
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error(`Failed to fetch WASM module: ${response.status} ${response.statusText}`);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const result = await WebAssembly.instantiateStreaming(response.clone(), imports);
|
|
41
|
+
return result.instance;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
const bytes = await response.arrayBuffer();
|
|
45
|
+
const result = await WebAssembly.instantiate(bytes, imports);
|
|
46
|
+
return result.instance;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function waitForCall() {
|
|
50
|
+
const deadline = Date.now() + 10_000;
|
|
51
|
+
while (Date.now() < deadline) {
|
|
52
|
+
if (globals.meshpktCall)
|
|
53
|
+
return globals.meshpktCall;
|
|
54
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
55
|
+
}
|
|
56
|
+
throw new Error("meshpktCall was not registered by the WASM module");
|
|
57
|
+
}
|
|
58
|
+
function buildAPI(call) {
|
|
59
|
+
const api = {};
|
|
60
|
+
for (const name of meshcoreOpNames) {
|
|
61
|
+
api[name] = (...args) => call(name, JSON.stringify(args));
|
|
62
|
+
}
|
|
63
|
+
return api;
|
|
64
|
+
}
|
|
65
|
+
export function load(options = {}) {
|
|
66
|
+
if (apiReady)
|
|
67
|
+
return apiReady;
|
|
68
|
+
apiReady = (async () => {
|
|
69
|
+
const wasmURL = options.wasmURL ?? new URL("./meshpkt.wasm", import.meta.url);
|
|
70
|
+
const wasmExecURL = options.wasmExecURL ?? new URL("./wasm_exec.js", import.meta.url);
|
|
71
|
+
await loadTinyGoRuntime(wasmExecURL);
|
|
72
|
+
const Go = globals.Go;
|
|
73
|
+
if (!Go) {
|
|
74
|
+
throw new Error("TinyGo runtime is unavailable");
|
|
75
|
+
}
|
|
76
|
+
const go = new Go();
|
|
77
|
+
const instance = await instantiate(wasmURL, go.importObject);
|
|
78
|
+
void go.run(instance);
|
|
79
|
+
const call = await waitForCall();
|
|
80
|
+
return buildAPI(call);
|
|
81
|
+
})();
|
|
82
|
+
return apiReady;
|
|
83
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
export interface ErrResult {
|
|
2
|
+
error: string;
|
|
3
|
+
}
|
|
4
|
+
export interface HexResult {
|
|
5
|
+
hex: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Envelope {
|
|
8
|
+
route: string;
|
|
9
|
+
routeCode: number;
|
|
10
|
+
type: string;
|
|
11
|
+
typeCode: number;
|
|
12
|
+
version: number;
|
|
13
|
+
pathHashSize: number;
|
|
14
|
+
hopCount: number;
|
|
15
|
+
hops: string[];
|
|
16
|
+
payloadHex: string;
|
|
17
|
+
isTransport: boolean;
|
|
18
|
+
transportCodes?: [number, number];
|
|
19
|
+
}
|
|
20
|
+
export interface GroupTextPayload {
|
|
21
|
+
sender: string;
|
|
22
|
+
text: string;
|
|
23
|
+
timestamp: number;
|
|
24
|
+
txtType: number;
|
|
25
|
+
attempt: number;
|
|
26
|
+
channelHash: string;
|
|
27
|
+
}
|
|
28
|
+
export interface DirectTextPayload {
|
|
29
|
+
destHash: string;
|
|
30
|
+
srcHash: string;
|
|
31
|
+
text: string;
|
|
32
|
+
timestamp: number;
|
|
33
|
+
txtType: number;
|
|
34
|
+
attempt: number;
|
|
35
|
+
}
|
|
36
|
+
export interface AdvertPayload {
|
|
37
|
+
publicKey: string;
|
|
38
|
+
timestamp: number;
|
|
39
|
+
name: string;
|
|
40
|
+
nodeType: number;
|
|
41
|
+
hasGPS: boolean;
|
|
42
|
+
lat?: number;
|
|
43
|
+
lon?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface AckPayload {
|
|
46
|
+
crc: number;
|
|
47
|
+
crcHex: string;
|
|
48
|
+
}
|
|
49
|
+
export interface GrpDataPayload {
|
|
50
|
+
channelHash: string;
|
|
51
|
+
dataType: number;
|
|
52
|
+
dataHex: string;
|
|
53
|
+
}
|
|
54
|
+
export interface ReqPayload {
|
|
55
|
+
destHash: string;
|
|
56
|
+
srcHash: string;
|
|
57
|
+
timestamp: number;
|
|
58
|
+
reqType: number;
|
|
59
|
+
dataHex: string;
|
|
60
|
+
}
|
|
61
|
+
export interface ResponsePayload {
|
|
62
|
+
destHash: string;
|
|
63
|
+
srcHash: string;
|
|
64
|
+
dataHex: string;
|
|
65
|
+
}
|
|
66
|
+
export interface PathPayload {
|
|
67
|
+
destHash: string;
|
|
68
|
+
srcHash: string;
|
|
69
|
+
path: string[];
|
|
70
|
+
extraType: number;
|
|
71
|
+
extraHex: string;
|
|
72
|
+
}
|
|
73
|
+
export interface AnonReqPayload {
|
|
74
|
+
destHash: string;
|
|
75
|
+
senderPubKey: string;
|
|
76
|
+
timestamp: number;
|
|
77
|
+
dataHex: string;
|
|
78
|
+
}
|
|
79
|
+
export interface ControlPayload {
|
|
80
|
+
subType: number;
|
|
81
|
+
flags: number;
|
|
82
|
+
dataHex: string;
|
|
83
|
+
discoverTag?: number;
|
|
84
|
+
discoverTypeFilter?: number;
|
|
85
|
+
discoverSince?: number;
|
|
86
|
+
discoverNodeType?: number;
|
|
87
|
+
discoverSNR?: number;
|
|
88
|
+
discoverPubKey?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface KeypairResult {
|
|
91
|
+
publicKey: string;
|
|
92
|
+
privateKey: string;
|
|
93
|
+
}
|
|
94
|
+
export interface MeshcoreWasm {
|
|
95
|
+
encodeGroupText(channelName: string, sender: string, text: string): HexResult | ErrResult;
|
|
96
|
+
encodeGroupTextSecret(secret: string, sender: string, text: string): HexResult | ErrResult;
|
|
97
|
+
encodeGrpData(channelName: string, dataType: number, data: string): HexResult | ErrResult;
|
|
98
|
+
encodeGrpDataSecret(secret: string, dataType: number, data: string): HexResult | ErrResult;
|
|
99
|
+
encodeDirectText(privKey: string, peerPubKey: string, text: string): HexResult | ErrResult;
|
|
100
|
+
encodeAdvert(pubKey: string, signature: string, name: string, hasGPS: number, lat: unknown, lon: unknown): HexResult | ErrResult;
|
|
101
|
+
encodeAck(crc: number): HexResult | ErrResult;
|
|
102
|
+
encodeReq(privKey: string, peerPubKey: string, reqType: number, data: string): HexResult | ErrResult;
|
|
103
|
+
encodeAnonReq(destPubKey: string, myPrivKey: string, data: string): HexResult | ErrResult;
|
|
104
|
+
encodeDiscoverReq(typeFilter: number, tag: number, since: number, prefixOnly: number): HexResult | ErrResult;
|
|
105
|
+
encodeRaw(route: number, payloadType: number, version: number, pathHashSize: number, payload: string): HexResult | ErrResult;
|
|
106
|
+
decodeEnvelope(packet: string): Envelope | ErrResult;
|
|
107
|
+
decodeGroupText(payload: string, channelName: string): GroupTextPayload | ErrResult;
|
|
108
|
+
decodeGroupTextSecret(payload: string, secret: string): GroupTextPayload | ErrResult;
|
|
109
|
+
decodeDirectText(payload: string, privKey: string, peerPubKey: string): DirectTextPayload | ErrResult;
|
|
110
|
+
decodeAdvert(payload: string): AdvertPayload | ErrResult;
|
|
111
|
+
decodeAck(payload: string): AckPayload | ErrResult;
|
|
112
|
+
decodeGrpData(payload: string, channelName: string): GrpDataPayload | ErrResult;
|
|
113
|
+
decodeGrpDataSecret(payload: string, secret: string): GrpDataPayload | ErrResult;
|
|
114
|
+
decodeReq(payload: string, privKey: string, peerPubKey: string): ReqPayload | ErrResult;
|
|
115
|
+
decodeResponse(payload: string, privKey: string, peerPubKey: string): ResponsePayload | ErrResult;
|
|
116
|
+
decodePath(payload: string, privKey: string, peerPubKey: string): PathPayload | ErrResult;
|
|
117
|
+
decodeAnonReq(payload: string, myPrivKey: string): AnonReqPayload | ErrResult;
|
|
118
|
+
decodeControl(payload: string): ControlPayload | ErrResult;
|
|
119
|
+
generateKeypair(): KeypairResult | ErrResult;
|
|
120
|
+
deriveChannelSecret(channelName: string): HexResult | ErrResult;
|
|
121
|
+
sharedSecret(privKey: string, peerPubKey: string): HexResult | ErrResult;
|
|
122
|
+
}
|
|
123
|
+
export declare const meshcoreOpNames: readonly ["encodeGroupText", "encodeGroupTextSecret", "encodeGrpData", "encodeGrpDataSecret", "encodeDirectText", "encodeAdvert", "encodeAck", "encodeReq", "encodeAnonReq", "encodeDiscoverReq", "encodeRaw", "decodeEnvelope", "decodeGroupText", "decodeGroupTextSecret", "decodeDirectText", "decodeAdvert", "decodeAck", "decodeGrpData", "decodeGrpDataSecret", "decodeReq", "decodeResponse", "decodePath", "decodeAnonReq", "decodeControl", "generateKeypair", "deriveChannelSecret", "sharedSecret"];
|
|
124
|
+
export declare const RouteTypes: readonly [{
|
|
125
|
+
readonly code: 0;
|
|
126
|
+
readonly label: "TRANSPORT_FLOOD";
|
|
127
|
+
}, {
|
|
128
|
+
readonly code: 1;
|
|
129
|
+
readonly label: "FLOOD";
|
|
130
|
+
}, {
|
|
131
|
+
readonly code: 2;
|
|
132
|
+
readonly label: "DIRECT";
|
|
133
|
+
}, {
|
|
134
|
+
readonly code: 3;
|
|
135
|
+
readonly label: "TRANSPORT_DIRECT";
|
|
136
|
+
}];
|
|
137
|
+
export declare const PayloadTypes: readonly [{
|
|
138
|
+
readonly code: 0;
|
|
139
|
+
readonly label: "REQ";
|
|
140
|
+
}, {
|
|
141
|
+
readonly code: 1;
|
|
142
|
+
readonly label: "RESPONSE";
|
|
143
|
+
}, {
|
|
144
|
+
readonly code: 2;
|
|
145
|
+
readonly label: "TXT_MSG";
|
|
146
|
+
}, {
|
|
147
|
+
readonly code: 3;
|
|
148
|
+
readonly label: "ACK";
|
|
149
|
+
}, {
|
|
150
|
+
readonly code: 4;
|
|
151
|
+
readonly label: "ADVERT";
|
|
152
|
+
}, {
|
|
153
|
+
readonly code: 5;
|
|
154
|
+
readonly label: "GRP_TXT";
|
|
155
|
+
}, {
|
|
156
|
+
readonly code: 6;
|
|
157
|
+
readonly label: "GRP_DATA";
|
|
158
|
+
}, {
|
|
159
|
+
readonly code: 7;
|
|
160
|
+
readonly label: "ANON_REQ";
|
|
161
|
+
}, {
|
|
162
|
+
readonly code: 8;
|
|
163
|
+
readonly label: "PATH";
|
|
164
|
+
}, {
|
|
165
|
+
readonly code: 9;
|
|
166
|
+
readonly label: "TRACE";
|
|
167
|
+
}, {
|
|
168
|
+
readonly code: 10;
|
|
169
|
+
readonly label: "MULTIPART";
|
|
170
|
+
}, {
|
|
171
|
+
readonly code: 11;
|
|
172
|
+
readonly label: "CONTROL";
|
|
173
|
+
}, {
|
|
174
|
+
readonly code: 15;
|
|
175
|
+
readonly label: "RAW_CUSTOM";
|
|
176
|
+
}];
|
package/dist/wasm.gen.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Code generated by "go run ./cmd/gen-ts"; DO NOT EDIT.
|
|
2
|
+
// Source: github.com/meshcore-cz/meshpkt
|
|
3
|
+
export const meshcoreOpNames = [
|
|
4
|
+
"encodeGroupText",
|
|
5
|
+
"encodeGroupTextSecret",
|
|
6
|
+
"encodeGrpData",
|
|
7
|
+
"encodeGrpDataSecret",
|
|
8
|
+
"encodeDirectText",
|
|
9
|
+
"encodeAdvert",
|
|
10
|
+
"encodeAck",
|
|
11
|
+
"encodeReq",
|
|
12
|
+
"encodeAnonReq",
|
|
13
|
+
"encodeDiscoverReq",
|
|
14
|
+
"encodeRaw",
|
|
15
|
+
"decodeEnvelope",
|
|
16
|
+
"decodeGroupText",
|
|
17
|
+
"decodeGroupTextSecret",
|
|
18
|
+
"decodeDirectText",
|
|
19
|
+
"decodeAdvert",
|
|
20
|
+
"decodeAck",
|
|
21
|
+
"decodeGrpData",
|
|
22
|
+
"decodeGrpDataSecret",
|
|
23
|
+
"decodeReq",
|
|
24
|
+
"decodeResponse",
|
|
25
|
+
"decodePath",
|
|
26
|
+
"decodeAnonReq",
|
|
27
|
+
"decodeControl",
|
|
28
|
+
"generateKeypair",
|
|
29
|
+
"deriveChannelSecret",
|
|
30
|
+
"sharedSecret",
|
|
31
|
+
];
|
|
32
|
+
export const RouteTypes = [
|
|
33
|
+
{ code: 0, label: "TRANSPORT_FLOOD" },
|
|
34
|
+
{ code: 1, label: "FLOOD" },
|
|
35
|
+
{ code: 2, label: "DIRECT" },
|
|
36
|
+
{ code: 3, label: "TRANSPORT_DIRECT" },
|
|
37
|
+
];
|
|
38
|
+
export const PayloadTypes = [
|
|
39
|
+
{ code: 0x00, label: "REQ" },
|
|
40
|
+
{ code: 0x01, label: "RESPONSE" },
|
|
41
|
+
{ code: 0x02, label: "TXT_MSG" },
|
|
42
|
+
{ code: 0x03, label: "ACK" },
|
|
43
|
+
{ code: 0x04, label: "ADVERT" },
|
|
44
|
+
{ code: 0x05, label: "GRP_TXT" },
|
|
45
|
+
{ code: 0x06, label: "GRP_DATA" },
|
|
46
|
+
{ code: 0x07, label: "ANON_REQ" },
|
|
47
|
+
{ code: 0x08, label: "PATH" },
|
|
48
|
+
{ code: 0x09, label: "TRACE" },
|
|
49
|
+
{ code: 0x0a, label: "MULTIPART" },
|
|
50
|
+
{ code: 0x0b, label: "CONTROL" },
|
|
51
|
+
{ code: 0x0f, label: "RAW_CUSTOM" },
|
|
52
|
+
];
|
|
@@ -0,0 +1,559 @@
|
|
|
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
|
+
// This file has been modified for use by the TinyGo compiler.
|
|
6
|
+
|
|
7
|
+
(() => {
|
|
8
|
+
// Map multiple JavaScript environments to a single common API,
|
|
9
|
+
// preferring web standards over Node.js API.
|
|
10
|
+
//
|
|
11
|
+
// Environments considered:
|
|
12
|
+
// - Browsers
|
|
13
|
+
// - Node.js
|
|
14
|
+
// - Electron
|
|
15
|
+
// - Parcel
|
|
16
|
+
|
|
17
|
+
if (typeof global !== "undefined") {
|
|
18
|
+
// global already exists
|
|
19
|
+
} else if (typeof window !== "undefined") {
|
|
20
|
+
window.global = window;
|
|
21
|
+
} else if (typeof self !== "undefined") {
|
|
22
|
+
self.global = self;
|
|
23
|
+
} else {
|
|
24
|
+
throw new Error("cannot export Go (neither global, window nor self is defined)");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!global.require && typeof require !== "undefined") {
|
|
28
|
+
global.require = require;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!global.fs && global.require) {
|
|
32
|
+
global.fs = require("node:fs");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const enosys = () => {
|
|
36
|
+
const err = new Error("not implemented");
|
|
37
|
+
err.code = "ENOSYS";
|
|
38
|
+
return err;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
if (!global.fs) {
|
|
42
|
+
let outputBuf = "";
|
|
43
|
+
global.fs = {
|
|
44
|
+
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
|
|
45
|
+
writeSync(fd, buf) {
|
|
46
|
+
outputBuf += decoder.decode(buf);
|
|
47
|
+
const nl = outputBuf.lastIndexOf("\n");
|
|
48
|
+
if (nl != -1) {
|
|
49
|
+
console.log(outputBuf.substr(0, nl));
|
|
50
|
+
outputBuf = outputBuf.substr(nl + 1);
|
|
51
|
+
}
|
|
52
|
+
return buf.length;
|
|
53
|
+
},
|
|
54
|
+
write(fd, buf, offset, length, position, callback) {
|
|
55
|
+
if (offset !== 0 || length !== buf.length || position !== null) {
|
|
56
|
+
callback(enosys());
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const n = this.writeSync(fd, buf);
|
|
60
|
+
callback(null, n);
|
|
61
|
+
},
|
|
62
|
+
chmod(path, mode, callback) { callback(enosys()); },
|
|
63
|
+
chown(path, uid, gid, callback) { callback(enosys()); },
|
|
64
|
+
close(fd, callback) { callback(enosys()); },
|
|
65
|
+
fchmod(fd, mode, callback) { callback(enosys()); },
|
|
66
|
+
fchown(fd, uid, gid, callback) { callback(enosys()); },
|
|
67
|
+
fstat(fd, callback) { callback(enosys()); },
|
|
68
|
+
fsync(fd, callback) { callback(null); },
|
|
69
|
+
ftruncate(fd, length, callback) { callback(enosys()); },
|
|
70
|
+
lchown(path, uid, gid, callback) { callback(enosys()); },
|
|
71
|
+
link(path, link, callback) { callback(enosys()); },
|
|
72
|
+
lstat(path, callback) { callback(enosys()); },
|
|
73
|
+
mkdir(path, perm, callback) { callback(enosys()); },
|
|
74
|
+
open(path, flags, mode, callback) { callback(enosys()); },
|
|
75
|
+
read(fd, buffer, offset, length, position, callback) { callback(enosys()); },
|
|
76
|
+
readdir(path, callback) { callback(enosys()); },
|
|
77
|
+
readlink(path, callback) { callback(enosys()); },
|
|
78
|
+
rename(from, to, callback) { callback(enosys()); },
|
|
79
|
+
rmdir(path, callback) { callback(enosys()); },
|
|
80
|
+
stat(path, callback) { callback(enosys()); },
|
|
81
|
+
symlink(path, link, callback) { callback(enosys()); },
|
|
82
|
+
truncate(path, length, callback) { callback(enosys()); },
|
|
83
|
+
unlink(path, callback) { callback(enosys()); },
|
|
84
|
+
utimes(path, atime, mtime, callback) { callback(enosys()); },
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!global.process) {
|
|
89
|
+
global.process = {
|
|
90
|
+
getuid() { return -1; },
|
|
91
|
+
getgid() { return -1; },
|
|
92
|
+
geteuid() { return -1; },
|
|
93
|
+
getegid() { return -1; },
|
|
94
|
+
getgroups() { throw enosys(); },
|
|
95
|
+
pid: -1,
|
|
96
|
+
ppid: -1,
|
|
97
|
+
umask() { throw enosys(); },
|
|
98
|
+
cwd() { throw enosys(); },
|
|
99
|
+
chdir() { throw enosys(); },
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!global.crypto) {
|
|
104
|
+
const nodeCrypto = require("node:crypto");
|
|
105
|
+
global.crypto = {
|
|
106
|
+
getRandomValues(b) {
|
|
107
|
+
nodeCrypto.randomFillSync(b);
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!global.performance) {
|
|
113
|
+
global.performance = {
|
|
114
|
+
now() {
|
|
115
|
+
const [sec, nsec] = process.hrtime();
|
|
116
|
+
return sec * 1000 + nsec / 1000000;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!global.TextEncoder) {
|
|
122
|
+
global.TextEncoder = require("node:util").TextEncoder;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!global.TextDecoder) {
|
|
126
|
+
global.TextDecoder = require("node:util").TextDecoder;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// End of polyfills for common API.
|
|
130
|
+
|
|
131
|
+
const encoder = new TextEncoder("utf-8");
|
|
132
|
+
const decoder = new TextDecoder("utf-8");
|
|
133
|
+
let reinterpretBuf = new DataView(new ArrayBuffer(8));
|
|
134
|
+
var logLine = [];
|
|
135
|
+
const wasmExit = {}; // thrown to exit via proc_exit (not an error)
|
|
136
|
+
|
|
137
|
+
global.Go = class {
|
|
138
|
+
constructor() {
|
|
139
|
+
this._callbackTimeouts = new Map();
|
|
140
|
+
this._nextCallbackTimeoutID = 1;
|
|
141
|
+
|
|
142
|
+
const mem = () => {
|
|
143
|
+
// The buffer may change when requesting more memory.
|
|
144
|
+
return new DataView(this._inst.exports.memory.buffer);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const unboxValue = (v_ref) => {
|
|
148
|
+
reinterpretBuf.setBigInt64(0, v_ref, true);
|
|
149
|
+
const f = reinterpretBuf.getFloat64(0, true);
|
|
150
|
+
if (f === 0) {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
if (!isNaN(f)) {
|
|
154
|
+
return f;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const id = v_ref & 0xffffffffn;
|
|
158
|
+
return this._values[id];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
const loadValue = (addr) => {
|
|
163
|
+
let v_ref = mem().getBigUint64(addr, true);
|
|
164
|
+
return unboxValue(v_ref);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const boxValue = (v) => {
|
|
168
|
+
const nanHead = 0x7FF80000n;
|
|
169
|
+
|
|
170
|
+
if (typeof v === "number") {
|
|
171
|
+
if (isNaN(v)) {
|
|
172
|
+
return nanHead << 32n;
|
|
173
|
+
}
|
|
174
|
+
if (v === 0) {
|
|
175
|
+
return (nanHead << 32n) | 1n;
|
|
176
|
+
}
|
|
177
|
+
reinterpretBuf.setFloat64(0, v, true);
|
|
178
|
+
return reinterpretBuf.getBigInt64(0, true);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
switch (v) {
|
|
182
|
+
case undefined:
|
|
183
|
+
return 0n;
|
|
184
|
+
case null:
|
|
185
|
+
return (nanHead << 32n) | 2n;
|
|
186
|
+
case true:
|
|
187
|
+
return (nanHead << 32n) | 3n;
|
|
188
|
+
case false:
|
|
189
|
+
return (nanHead << 32n) | 4n;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let id = this._ids.get(v);
|
|
193
|
+
if (id === undefined) {
|
|
194
|
+
id = this._idPool.pop();
|
|
195
|
+
if (id === undefined) {
|
|
196
|
+
id = BigInt(this._values.length);
|
|
197
|
+
}
|
|
198
|
+
this._values[id] = v;
|
|
199
|
+
this._goRefCounts[id] = 0;
|
|
200
|
+
this._ids.set(v, id);
|
|
201
|
+
}
|
|
202
|
+
this._goRefCounts[id]++;
|
|
203
|
+
let typeFlag = 1n;
|
|
204
|
+
switch (typeof v) {
|
|
205
|
+
case "string":
|
|
206
|
+
typeFlag = 2n;
|
|
207
|
+
break;
|
|
208
|
+
case "symbol":
|
|
209
|
+
typeFlag = 3n;
|
|
210
|
+
break;
|
|
211
|
+
case "function":
|
|
212
|
+
typeFlag = 4n;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
return id | ((nanHead | typeFlag) << 32n);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const storeValue = (addr, v) => {
|
|
219
|
+
let v_ref = boxValue(v);
|
|
220
|
+
mem().setBigUint64(addr, v_ref, true);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const loadSlice = (array, len, cap) => {
|
|
224
|
+
return new Uint8Array(this._inst.exports.memory.buffer, array, len);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const loadSliceOfValues = (array, len, cap) => {
|
|
228
|
+
const a = new Array(len);
|
|
229
|
+
for (let i = 0; i < len; i++) {
|
|
230
|
+
a[i] = loadValue(array + i * 8);
|
|
231
|
+
}
|
|
232
|
+
return a;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const loadString = (ptr, len) => {
|
|
236
|
+
return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const timeOrigin = Date.now() - performance.now();
|
|
240
|
+
const wasi_EBADF = 8;
|
|
241
|
+
const wasi_ENOSYS = 52;
|
|
242
|
+
this.importObject = {
|
|
243
|
+
wasi_snapshot_preview1: {
|
|
244
|
+
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md
|
|
245
|
+
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
|
246
|
+
let nwritten = 0;
|
|
247
|
+
if (fd == 1) {
|
|
248
|
+
for (let iovs_i=0; iovs_i<iovs_len;iovs_i++) {
|
|
249
|
+
let iov_ptr = iovs_ptr+iovs_i*8; // assuming wasm32
|
|
250
|
+
let ptr = mem().getUint32(iov_ptr + 0, true);
|
|
251
|
+
let len = mem().getUint32(iov_ptr + 4, true);
|
|
252
|
+
nwritten += len;
|
|
253
|
+
for (let i=0; i<len; i++) {
|
|
254
|
+
let c = mem().getUint8(ptr+i);
|
|
255
|
+
if (c == 13) { // CR
|
|
256
|
+
// ignore
|
|
257
|
+
} else if (c == 10) { // LF
|
|
258
|
+
// write line
|
|
259
|
+
let line = decoder.decode(new Uint8Array(logLine));
|
|
260
|
+
logLine = [];
|
|
261
|
+
console.log(line);
|
|
262
|
+
} else {
|
|
263
|
+
logLine.push(c);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
console.error('invalid file descriptor:', fd);
|
|
269
|
+
}
|
|
270
|
+
mem().setUint32(nwritten_ptr, nwritten, true);
|
|
271
|
+
return 0;
|
|
272
|
+
},
|
|
273
|
+
fd_read: () => wasi_ENOSYS,
|
|
274
|
+
fd_close: () => wasi_ENOSYS,
|
|
275
|
+
fd_fdstat_get: () => wasi_ENOSYS,
|
|
276
|
+
fd_prestat_get: () => wasi_EBADF, // wasi-libc relies on this errno value
|
|
277
|
+
fd_prestat_dir_name: () => wasi_ENOSYS,
|
|
278
|
+
fd_seek: () => wasi_ENOSYS,
|
|
279
|
+
path_open: () => wasi_ENOSYS,
|
|
280
|
+
proc_exit: (code) => {
|
|
281
|
+
this.exited = true;
|
|
282
|
+
this.exitCode = code;
|
|
283
|
+
this._resolveExitPromise();
|
|
284
|
+
throw wasmExit;
|
|
285
|
+
},
|
|
286
|
+
random_get: (bufPtr, bufLen) => {
|
|
287
|
+
crypto.getRandomValues(loadSlice(bufPtr, bufLen));
|
|
288
|
+
return 0;
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
gojs: {
|
|
292
|
+
// func ticks() int64
|
|
293
|
+
"runtime.ticks": () => {
|
|
294
|
+
return BigInt((timeOrigin + performance.now()) * 1e6);
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
// func sleepTicks(timeout int64)
|
|
298
|
+
"runtime.sleepTicks": (timeout) => {
|
|
299
|
+
// Do not sleep, only reactivate scheduler after the given timeout.
|
|
300
|
+
setTimeout(() => {
|
|
301
|
+
if (this.exited) return;
|
|
302
|
+
try {
|
|
303
|
+
this._inst.exports.go_scheduler();
|
|
304
|
+
} catch (e) {
|
|
305
|
+
if (e !== wasmExit) throw e;
|
|
306
|
+
}
|
|
307
|
+
}, Number(timeout)/1e6);
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
// func finalizeRef(v ref)
|
|
311
|
+
"syscall/js.finalizeRef": (v_ref) => {
|
|
312
|
+
// Note: TinyGo does not support finalizers so this is only called
|
|
313
|
+
// for one specific case, by js.go:jsString. and can/might leak memory.
|
|
314
|
+
const id = v_ref & 0xffffffffn;
|
|
315
|
+
if (this._goRefCounts?.[id] !== undefined) {
|
|
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
|
+
} else {
|
|
324
|
+
console.error("syscall/js.finalizeRef: unknown id", id);
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
|
|
328
|
+
// func stringVal(value string) ref
|
|
329
|
+
"syscall/js.stringVal": (value_ptr, value_len) => {
|
|
330
|
+
value_ptr >>>= 0;
|
|
331
|
+
const s = loadString(value_ptr, value_len);
|
|
332
|
+
return boxValue(s);
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
// func valueGet(v ref, p string) ref
|
|
336
|
+
"syscall/js.valueGet": (v_ref, p_ptr, p_len) => {
|
|
337
|
+
let prop = loadString(p_ptr, p_len);
|
|
338
|
+
let v = unboxValue(v_ref);
|
|
339
|
+
let result = Reflect.get(v, prop);
|
|
340
|
+
return boxValue(result);
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
// func valueSet(v ref, p string, x ref)
|
|
344
|
+
"syscall/js.valueSet": (v_ref, p_ptr, p_len, x_ref) => {
|
|
345
|
+
const v = unboxValue(v_ref);
|
|
346
|
+
const p = loadString(p_ptr, p_len);
|
|
347
|
+
const x = unboxValue(x_ref);
|
|
348
|
+
Reflect.set(v, p, x);
|
|
349
|
+
},
|
|
350
|
+
|
|
351
|
+
// func valueDelete(v ref, p string)
|
|
352
|
+
"syscall/js.valueDelete": (v_ref, p_ptr, p_len) => {
|
|
353
|
+
const v = unboxValue(v_ref);
|
|
354
|
+
const p = loadString(p_ptr, p_len);
|
|
355
|
+
Reflect.deleteProperty(v, p);
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
// func valueIndex(v ref, i int) ref
|
|
359
|
+
"syscall/js.valueIndex": (v_ref, i) => {
|
|
360
|
+
return boxValue(Reflect.get(unboxValue(v_ref), i));
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
// valueSetIndex(v ref, i int, x ref)
|
|
364
|
+
"syscall/js.valueSetIndex": (v_ref, i, x_ref) => {
|
|
365
|
+
Reflect.set(unboxValue(v_ref), i, unboxValue(x_ref));
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
|
369
|
+
"syscall/js.valueCall": (ret_addr, v_ref, m_ptr, m_len, args_ptr, args_len, args_cap) => {
|
|
370
|
+
const v = unboxValue(v_ref);
|
|
371
|
+
const name = loadString(m_ptr, m_len);
|
|
372
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
373
|
+
try {
|
|
374
|
+
const m = Reflect.get(v, name);
|
|
375
|
+
storeValue(ret_addr, Reflect.apply(m, v, args));
|
|
376
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
377
|
+
} catch (err) {
|
|
378
|
+
storeValue(ret_addr, err);
|
|
379
|
+
mem().setUint8(ret_addr + 8, 0);
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
|
|
383
|
+
// func valueInvoke(v ref, args []ref) (ref, bool)
|
|
384
|
+
"syscall/js.valueInvoke": (ret_addr, v_ref, args_ptr, args_len, args_cap) => {
|
|
385
|
+
try {
|
|
386
|
+
const v = unboxValue(v_ref);
|
|
387
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
388
|
+
storeValue(ret_addr, Reflect.apply(v, undefined, args));
|
|
389
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
390
|
+
} catch (err) {
|
|
391
|
+
storeValue(ret_addr, err);
|
|
392
|
+
mem().setUint8(ret_addr + 8, 0);
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
|
|
396
|
+
// func valueNew(v ref, args []ref) (ref, bool)
|
|
397
|
+
"syscall/js.valueNew": (ret_addr, v_ref, args_ptr, args_len, args_cap) => {
|
|
398
|
+
const v = unboxValue(v_ref);
|
|
399
|
+
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
|
400
|
+
try {
|
|
401
|
+
storeValue(ret_addr, Reflect.construct(v, args));
|
|
402
|
+
mem().setUint8(ret_addr + 8, 1);
|
|
403
|
+
} catch (err) {
|
|
404
|
+
storeValue(ret_addr, err);
|
|
405
|
+
mem().setUint8(ret_addr+ 8, 0);
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
|
|
409
|
+
// func valueLength(v ref) int
|
|
410
|
+
"syscall/js.valueLength": (v_ref) => {
|
|
411
|
+
return unboxValue(v_ref).length;
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
// valuePrepareString(v ref) (ref, int)
|
|
415
|
+
"syscall/js.valuePrepareString": (ret_addr, v_ref) => {
|
|
416
|
+
const s = String(unboxValue(v_ref));
|
|
417
|
+
const str = encoder.encode(s);
|
|
418
|
+
storeValue(ret_addr, str);
|
|
419
|
+
mem().setInt32(ret_addr + 8, str.length, true);
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
// valueLoadString(v ref, b []byte)
|
|
423
|
+
"syscall/js.valueLoadString": (v_ref, slice_ptr, slice_len, slice_cap) => {
|
|
424
|
+
const str = unboxValue(v_ref);
|
|
425
|
+
loadSlice(slice_ptr, slice_len, slice_cap).set(str);
|
|
426
|
+
},
|
|
427
|
+
|
|
428
|
+
// func valueInstanceOf(v ref, t ref) bool
|
|
429
|
+
"syscall/js.valueInstanceOf": (v_ref, t_ref) => {
|
|
430
|
+
return unboxValue(v_ref) instanceof unboxValue(t_ref);
|
|
431
|
+
},
|
|
432
|
+
|
|
433
|
+
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
|
434
|
+
"syscall/js.copyBytesToGo": (ret_addr, dest_addr, dest_len, dest_cap, src_ref) => {
|
|
435
|
+
let num_bytes_copied_addr = ret_addr;
|
|
436
|
+
let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable
|
|
437
|
+
|
|
438
|
+
const dst = loadSlice(dest_addr, dest_len);
|
|
439
|
+
const src = unboxValue(src_ref);
|
|
440
|
+
if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
|
|
441
|
+
mem().setUint8(returned_status_addr, 0); // Return "not ok" status
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
const toCopy = src.subarray(0, dst.length);
|
|
445
|
+
dst.set(toCopy);
|
|
446
|
+
mem().setUint32(num_bytes_copied_addr, toCopy.length, true);
|
|
447
|
+
mem().setUint8(returned_status_addr, 1); // Return "ok" status
|
|
448
|
+
},
|
|
449
|
+
|
|
450
|
+
// copyBytesToJS(dst ref, src []byte) (int, bool)
|
|
451
|
+
// Originally copied from upstream Go project, then modified:
|
|
452
|
+
// https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416
|
|
453
|
+
"syscall/js.copyBytesToJS": (ret_addr, dst_ref, src_addr, src_len, src_cap) => {
|
|
454
|
+
let num_bytes_copied_addr = ret_addr;
|
|
455
|
+
let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable
|
|
456
|
+
|
|
457
|
+
const dst = unboxValue(dst_ref);
|
|
458
|
+
const src = loadSlice(src_addr, src_len);
|
|
459
|
+
if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
|
|
460
|
+
mem().setUint8(returned_status_addr, 0); // Return "not ok" status
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const toCopy = src.subarray(0, dst.length);
|
|
464
|
+
dst.set(toCopy);
|
|
465
|
+
mem().setUint32(num_bytes_copied_addr, toCopy.length, true);
|
|
466
|
+
mem().setUint8(returned_status_addr, 1); // Return "ok" status
|
|
467
|
+
},
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
// Go 1.20 uses 'env'. Go 1.21 uses 'gojs'.
|
|
472
|
+
// For compatibility, we use both as long as Go 1.20 is supported.
|
|
473
|
+
this.importObject.env = this.importObject.gojs;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
async run(instance) {
|
|
477
|
+
this._inst = instance;
|
|
478
|
+
this._values = [ // JS values that Go currently has references to, indexed by reference id
|
|
479
|
+
NaN,
|
|
480
|
+
0,
|
|
481
|
+
null,
|
|
482
|
+
true,
|
|
483
|
+
false,
|
|
484
|
+
global,
|
|
485
|
+
this,
|
|
486
|
+
];
|
|
487
|
+
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
|
|
488
|
+
this._ids = new Map(); // mapping from JS values to reference ids
|
|
489
|
+
this._idPool = []; // unused ids that have been garbage collected
|
|
490
|
+
this.exited = false; // whether the Go program has exited
|
|
491
|
+
this.exitCode = 0;
|
|
492
|
+
|
|
493
|
+
if (this._inst.exports._start) {
|
|
494
|
+
let exitPromise = new Promise((resolve, reject) => {
|
|
495
|
+
this._resolveExitPromise = resolve;
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// Run program, but catch the wasmExit exception that's thrown
|
|
499
|
+
// to return back here.
|
|
500
|
+
try {
|
|
501
|
+
this._inst.exports._start();
|
|
502
|
+
} catch (e) {
|
|
503
|
+
if (e !== wasmExit) throw e;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
await exitPromise;
|
|
507
|
+
return this.exitCode;
|
|
508
|
+
} else {
|
|
509
|
+
this._inst.exports._initialize();
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
_resume() {
|
|
514
|
+
if (this.exited) {
|
|
515
|
+
throw new Error("Go program has already exited");
|
|
516
|
+
}
|
|
517
|
+
try {
|
|
518
|
+
this._inst.exports.resume();
|
|
519
|
+
} catch (e) {
|
|
520
|
+
if (e !== wasmExit) throw e;
|
|
521
|
+
}
|
|
522
|
+
if (this.exited) {
|
|
523
|
+
this._resolveExitPromise();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
_makeFuncWrapper(id) {
|
|
528
|
+
const go = this;
|
|
529
|
+
return function () {
|
|
530
|
+
const event = { id: id, this: this, args: arguments };
|
|
531
|
+
go._pendingEvent = event;
|
|
532
|
+
go._resume();
|
|
533
|
+
return event.result;
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (
|
|
539
|
+
global.require &&
|
|
540
|
+
global.require.main === module &&
|
|
541
|
+
global.process &&
|
|
542
|
+
global.process.versions &&
|
|
543
|
+
!global.process.versions.electron
|
|
544
|
+
) {
|
|
545
|
+
if (process.argv.length != 3) {
|
|
546
|
+
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
|
|
547
|
+
process.exit(1);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const go = new Go();
|
|
551
|
+
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then(async (result) => {
|
|
552
|
+
let exitCode = await go.run(result.instance);
|
|
553
|
+
process.exit(exitCode);
|
|
554
|
+
}).catch((err) => {
|
|
555
|
+
console.error(err);
|
|
556
|
+
process.exit(1);
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
})();
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meshcore-cz/meshpkt",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MeshCore radio packet codec for JavaScript and TypeScript, powered by WebAssembly",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/meshcore-cz/meshpkt.git",
|
|
10
|
+
"directory": "js"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/meshcore-cz/meshpkt",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/meshcore-cz/meshpkt/issues"
|
|
15
|
+
},
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./meshpkt.wasm": "./dist/meshpkt.wasm",
|
|
22
|
+
"./wasm_exec.js": "./dist/wasm_exec.js"
|
|
23
|
+
},
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build:ts": "tsc -p tsconfig.json",
|
|
31
|
+
"pack:check": "npm pack --dry-run"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"typescript": "^6.0.3"
|
|
38
|
+
}
|
|
39
|
+
}
|