-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnm_componentize_qjs.js
More file actions
89 lines (80 loc) · 2.33 KB
/
Copy pathnm_componentize_qjs.js
File metadata and controls
89 lines (80 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! componentize-qjs Native Messaging host
//! guest271314, andreiltd (https://github.com/andreiltd), 6-13-2026
//! https://github.com/andreiltd/issues/1
//! Based on https://github.com/guest271314/native-messaging-webassembly/nm_javy.js
import stdin from "wasi:cli/stdin@0.2.6";
import stdout from "wasi:cli/stdout@0.2.6";
const MAX_IN = 64 * 1024 * 1024;
const WRITE_CHUNK = 4096;
const FRAME = 1024 * 1024;
const COMMA = 0x2c, OPEN = 0x5b, CLOSE = 0x5d;
function readExact(input, n) {
const out = new Uint8Array(n);
let off = 0;
while (off < n) {
let chunk;
try {
chunk = input.blockingRead(n - off);
} catch (e) {
if (e && e.payload && e.payload.tag === "closed" && off === 0) {
return null;
}
throw e;
}
if (chunk.length === 0) {
if (off === 0) return null;
throw new Error(`stdin closed after ${off} of ${n} bytes`);
}
out.set(chunk, off);
off += chunk.length;
}
return out;
}
function readMessage(input) {
const header = readExact(input, 4);
if (header === null) return null;
const len = new DataView(header.buffer).getUint32(0, true);
if (len > MAX_IN) throw new Error(`message of ${len} bytes exceeds 64 MiB`);
return len === 0 ? new Uint8Array(0) : readExact(input, len);
}
function writeAll(output, data) {
for (let off = 0; off < data.length; off += WRITE_CHUNK) {
output.blockingWriteAndFlush(data.subarray(off, off + WRITE_CHUNK));
}
}
function writeFrame(output, body) {
const frame = new Uint8Array(4 + body.length);
new DataView(frame.buffer).setUint32(0, body.length, true);
frame.set(body, 4);
writeAll(output, frame);
}
function sendMessage(output, msg) {
if (msg.length <= FRAME) {
writeFrame(output, msg);
return;
}
for (let i = 1, end = msg.length - 1; i < end;) {
let j = i + FRAME - 16;
if (j >= end) j = end;
else {
const c = msg.indexOf(COMMA, j);
j = c === -1 ? end : c;
}
const body = new Uint8Array(2 + (j - i));
body[0] = OPEN;
body.set(msg.subarray(i, j), 1);
body[body.length - 1] = CLOSE;
writeFrame(output, body);
i = j + 1;
}
}
export const run = {
run() {
const input = stdin.getStdin();
const output = stdout.getStdout();
for (let msg; (msg = readMessage(input)) !== null;) {
sendMessage(output, msg);
}
return { tag: "ok" };
},
};