xbintsc 0.1.10 → 0.1.11
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/dist/src/codegen/generator/module.js +1 -0
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +14 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +18 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/compiler.js +1 -0
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/extensions/node/buffer/index.d.ts +10 -0
- package/dist/src/extensions/node/buffer/index.js +15 -0
- package/dist/src/extensions/node/buffer/index.js.map +1 -0
- package/dist/src/extensions/node/dgram/index.d.ts +8 -0
- package/dist/src/extensions/node/dgram/index.js +13 -0
- package/dist/src/extensions/node/dgram/index.js.map +1 -0
- package/dist/src/extensions/node/fs-promises/index.d.ts +10 -0
- package/dist/src/extensions/node/fs-promises/index.js +37 -0
- package/dist/src/extensions/node/fs-promises/index.js.map +1 -0
- package/dist/src/extensions/node/http/index.d.ts +10 -0
- package/dist/src/extensions/node/http/index.js +18 -0
- package/dist/src/extensions/node/http/index.js.map +1 -0
- package/dist/src/extensions/node/index.d.ts +2 -1
- package/dist/src/extensions/node/index.js +24 -4
- package/dist/src/extensions/node/index.js.map +1 -1
- package/dist/src/extensions/node/net/index.d.ts +9 -0
- package/dist/src/extensions/node/net/index.js +14 -0
- package/dist/src/extensions/node/net/index.js.map +1 -0
- package/dist/src/extensions/node/stream/index.d.ts +10 -0
- package/dist/src/extensions/node/stream/index.js +15 -0
- package/dist/src/extensions/node/stream/index.js.map +1 -0
- package/dist/tests/e2e/node-modules.test.d.ts +9 -0
- package/dist/tests/e2e/node-modules.test.js +179 -0
- package/dist/tests/e2e/node-modules.test.js.map +1 -0
- package/package.json +1 -1
- package/runtime/ext_node/buffer/buffer.c +569 -0
- package/runtime/ext_node/dgram/dgram.c +337 -0
- package/runtime/ext_node/fs/promises.c +60 -0
- package/runtime/ext_node/http/http.c +760 -0
- package/runtime/ext_node/net/net.c +546 -0
- package/runtime/ext_node/node_common.h +305 -0
- package/runtime/ext_node/stream/stream.c +348 -0
- package/runtime/rt.h +13 -0
- package/runtime/xt_containers.c +2 -0
- package/runtime/xt_loop.c +117 -0
- package/scripts/build-runtime.mjs +9 -0
- package/src/codegen/generator/module.ts +1 -0
- package/src/codegen/generator/state.ts +14 -0
- package/src/codegen/generator/tables.ts +18 -0
- package/src/driver/compiler.ts +1 -0
- package/src/extensions/node/buffer/index.ts +17 -0
- package/src/extensions/node/dgram/index.ts +15 -0
- package/src/extensions/node/fs-promises/index.ts +41 -0
- package/src/extensions/node/http/index.ts +20 -0
- package/src/extensions/node/index.ts +24 -4
- package/src/extensions/node/net/index.ts +16 -0
- package/src/extensions/node/stream/index.ts +17 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end tests for the Node compatibility modules that need real host I/O:
|
|
3
|
+
* `buffer`, `fs/promises`, `stream`, `net`, `dgram` and `http`.
|
|
4
|
+
*
|
|
5
|
+
* Every program is compiled to a native binary and executed. The event-loop
|
|
6
|
+
* based modules open servers on an ephemeral port (`listen(0)` / `bind(0)`) so
|
|
7
|
+
* the tests stay hermetic. Skipped when no clang-compatible compiler is found.
|
|
8
|
+
*/
|
|
9
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { spawnSync } from "node:child_process";
|
|
13
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
14
|
+
import { build } from "../../src/driver/compiler.js";
|
|
15
|
+
import { createDefaultRegistry } from "../../src/extensions/registry.js";
|
|
16
|
+
import { nodeExtension } from "../../src/extensions/node/index.js";
|
|
17
|
+
import { hasClang } from "../helpers.js";
|
|
18
|
+
const describeWithClang = hasClang() ? describe : describe.skip;
|
|
19
|
+
describeWithClang("node compatibility modules", () => {
|
|
20
|
+
let workdir;
|
|
21
|
+
let cacheDir;
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
workdir = mkdtempSync(join(tmpdir(), "xbintsc-node-mods-"));
|
|
24
|
+
cacheDir = join(workdir, ".cache");
|
|
25
|
+
});
|
|
26
|
+
afterAll(() => {
|
|
27
|
+
rmSync(workdir, { recursive: true, force: true });
|
|
28
|
+
});
|
|
29
|
+
function run(source) {
|
|
30
|
+
const entry = join(workdir, `program_${Math.random().toString(36).slice(2)}.ts`);
|
|
31
|
+
writeFileSync(entry, source);
|
|
32
|
+
const extensions = createDefaultRegistry().register(nodeExtension);
|
|
33
|
+
// `force` keeps the runtime objects honest: the whole-program cache does
|
|
34
|
+
// not key on the C sources, only the generated object files do.
|
|
35
|
+
const result = build(entry, { emit: "exe", outDir: join(workdir, "out"), cacheDir, extensions, force: true });
|
|
36
|
+
expect(result.diagnostics.filter((d) => d.category === "error")).toEqual([]);
|
|
37
|
+
const executed = spawnSync(result.outputPath, [], { encoding: "utf8", timeout: 20000 });
|
|
38
|
+
return { stdout: executed.stdout ?? "", stderr: executed.stderr ?? "", status: executed.status };
|
|
39
|
+
}
|
|
40
|
+
it("implements Buffer construction and instance methods", () => {
|
|
41
|
+
const source = `
|
|
42
|
+
const buf = Buffer.from("hello");
|
|
43
|
+
console.log(buf.toString(), buf.length, Buffer.isBuffer(buf));
|
|
44
|
+
console.log(Buffer.alloc(4, 65).toString());
|
|
45
|
+
console.log(Buffer.from("deadbeef", "hex").toString("hex"));
|
|
46
|
+
console.log(Buffer.concat([Buffer.from("foo"), Buffer.from("bar")]).toString());
|
|
47
|
+
const wide = Buffer.alloc(4);
|
|
48
|
+
wide.writeUInt32BE(305419896, 0);
|
|
49
|
+
console.log(wide.readUInt32BE(0), wide.toString("hex"));
|
|
50
|
+
`;
|
|
51
|
+
const { status, stdout } = run(source);
|
|
52
|
+
expect(status).toBe(0);
|
|
53
|
+
expect(stdout.trim()).toBe(["hello 5 true", "AAAA", "deadbeef", "foobar", "305419896 12345678"].join("\n"));
|
|
54
|
+
});
|
|
55
|
+
it("wraps fs operations in promises", () => {
|
|
56
|
+
const target = join(workdir, `promise_${Math.random().toString(36).slice(2)}.txt`);
|
|
57
|
+
const source = `
|
|
58
|
+
async function main(): Promise<void> {
|
|
59
|
+
await writeFile(${JSON.stringify(target)}, "hello promises");
|
|
60
|
+
const data = await readFile(${JSON.stringify(target)});
|
|
61
|
+
const info = await stat(${JSON.stringify(target)});
|
|
62
|
+
console.log(data, info.size, info.isFile());
|
|
63
|
+
await rm(${JSON.stringify(target)});
|
|
64
|
+
}
|
|
65
|
+
main();
|
|
66
|
+
`;
|
|
67
|
+
const { status, stdout } = run(source);
|
|
68
|
+
expect(status).toBe(0);
|
|
69
|
+
expect(stdout.trim()).toBe("hello promises 14 true");
|
|
70
|
+
});
|
|
71
|
+
it("streams data through Readable, Transform and pipe", () => {
|
|
72
|
+
const source = `
|
|
73
|
+
const readable = new Readable();
|
|
74
|
+
readable.on("data", (chunk: string) => console.log("data", chunk));
|
|
75
|
+
readable.on("end", () => console.log("end"));
|
|
76
|
+
readable.push("hello");
|
|
77
|
+
readable.push(null);
|
|
78
|
+
|
|
79
|
+
const transform = new Transform({ transform(chunk: string, enc: string, cb: (err: unknown, out: string) => void) {
|
|
80
|
+
cb(null, chunk.toUpperCase());
|
|
81
|
+
} });
|
|
82
|
+
transform.on("data", (chunk: string) => console.log("upper", chunk));
|
|
83
|
+
transform.write("abc");
|
|
84
|
+
|
|
85
|
+
const source = new Readable();
|
|
86
|
+
const sink = new Writable();
|
|
87
|
+
sink.on("finish", () => console.log("piped"));
|
|
88
|
+
source.pipe(sink);
|
|
89
|
+
source.push("payload");
|
|
90
|
+
source.push(null);
|
|
91
|
+
`;
|
|
92
|
+
const { status, stdout } = run(source);
|
|
93
|
+
expect(status).toBe(0);
|
|
94
|
+
expect(stdout.trim().split("\n")).toEqual(["data hello", "end", "upper ABC", "piped"]);
|
|
95
|
+
});
|
|
96
|
+
it("exchanges data over a TCP server and client", () => {
|
|
97
|
+
const source = `
|
|
98
|
+
const server = net.createServer((socket: any) => {
|
|
99
|
+
socket.on("data", (data: string) => {
|
|
100
|
+
socket.write("echo:" + data);
|
|
101
|
+
socket.end();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
server.listen(0, () => {
|
|
105
|
+
const client = net.connect(server.address().port, "127.0.0.1");
|
|
106
|
+
client.on("data", (data: string) => console.log("client", data));
|
|
107
|
+
client.on("end", () => {
|
|
108
|
+
console.log("end");
|
|
109
|
+
server.close();
|
|
110
|
+
});
|
|
111
|
+
client.write("ping");
|
|
112
|
+
});
|
|
113
|
+
`;
|
|
114
|
+
const { status, stdout } = run(source);
|
|
115
|
+
expect(status).toBe(0);
|
|
116
|
+
expect(stdout.trim().split("\n")).toEqual(["client echo:ping", "end"]);
|
|
117
|
+
});
|
|
118
|
+
it("exchanges a datagram over UDP", () => {
|
|
119
|
+
const source = `
|
|
120
|
+
const server = dgram.createSocket("udp4");
|
|
121
|
+
server.on("message", (msg: string, rinfo: any) => {
|
|
122
|
+
server.send("pong:" + msg, rinfo.port, rinfo.address);
|
|
123
|
+
});
|
|
124
|
+
server.bind(0, () => {
|
|
125
|
+
const client = dgram.createSocket("udp4");
|
|
126
|
+
client.on("message", (msg: string) => {
|
|
127
|
+
console.log(msg);
|
|
128
|
+
client.close();
|
|
129
|
+
server.close();
|
|
130
|
+
});
|
|
131
|
+
client.send("ping", server.address().port, "127.0.0.1");
|
|
132
|
+
});
|
|
133
|
+
`;
|
|
134
|
+
const { status, stdout } = run(source);
|
|
135
|
+
expect(status).toBe(0);
|
|
136
|
+
expect(stdout.trim()).toBe("pong:ping");
|
|
137
|
+
});
|
|
138
|
+
it("serves HTTP requests and reads responses", () => {
|
|
139
|
+
const source = `
|
|
140
|
+
const server = http.createServer((req: any, res: any) => {
|
|
141
|
+
let body = "";
|
|
142
|
+
req.on("data", (chunk: string) => { body += chunk; });
|
|
143
|
+
req.on("end", () => {
|
|
144
|
+
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
145
|
+
res.end("hello " + req.url + " " + body);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
server.listen(0, () => {
|
|
149
|
+
const port = server.address().port;
|
|
150
|
+
http.get("http://127.0.0.1:" + port + "/world", (res: any) => {
|
|
151
|
+
let body = "";
|
|
152
|
+
console.log("status", res.statusCode);
|
|
153
|
+
res.on("data", (chunk: string) => { body += chunk; });
|
|
154
|
+
res.on("end", () => {
|
|
155
|
+
console.log("get", body);
|
|
156
|
+
const req = http.request({ host: "127.0.0.1", port, path: "/submit", method: "POST" }, (res2: any) => {
|
|
157
|
+
let reply = "";
|
|
158
|
+
res2.on("data", (chunk: string) => { reply += chunk; });
|
|
159
|
+
res2.on("end", () => {
|
|
160
|
+
console.log("post", reply);
|
|
161
|
+
server.close();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
req.write("payload");
|
|
165
|
+
req.end();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
`;
|
|
170
|
+
const { status, stdout } = run(source);
|
|
171
|
+
expect(status).toBe(0);
|
|
172
|
+
expect(stdout.trim().split("\n")).toEqual([
|
|
173
|
+
"status 200",
|
|
174
|
+
"get hello /world ",
|
|
175
|
+
"post hello /submit payload",
|
|
176
|
+
]);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
//# sourceMappingURL=node-modules.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-modules.test.js","sourceRoot":"","sources":["../../../tests/e2e/node-modules.test.ts"],"names":[],"mappings":"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"}
|