@bytecodealliance/preview2-shim 0.20.2 → 0.22.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/dist/io/calls.d.ts +1 -0
- package/dist/io/calls.js +1 -0
- package/dist/io/worker-filesystem.d.ts +2 -0
- package/dist/io/worker-filesystem.js +7 -0
- package/dist/io/worker-socket-tcp.d.ts +5 -2
- package/dist/io/worker-socket-tcp.js +121 -95
- package/dist/io/worker-thread.bundle.js +120 -83
- package/dist/io/worker-thread.js +4 -2
- package/dist/nodejs/filesystem.d.ts +1 -1
- package/dist/nodejs/filesystem.js +12 -2
- package/package.json +4 -1
package/dist/io/calls.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export declare const OUTPUT_STREAM_DISPOSE: number;
|
|
|
31
31
|
export declare const OUTPUT_STREAM_GET_TOTAL_BYTES: number;
|
|
32
32
|
export declare const FILESYSTEM_DESCRIPTOR_OPEN: number;
|
|
33
33
|
export declare const FILESYSTEM_DESCRIPTOR_CLOSE: number;
|
|
34
|
+
export declare const FILESYSTEM_DESCRIPTOR_ADVISE: number;
|
|
34
35
|
export declare const FILESYSTEM_DESCRIPTOR_SYNC_DATA: number;
|
|
35
36
|
export declare const FILESYSTEM_DESCRIPTOR_GET_TYPE: number;
|
|
36
37
|
export declare const FILESYSTEM_DESCRIPTOR_SET_SIZE: number;
|
package/dist/io/calls.js
CHANGED
|
@@ -38,6 +38,7 @@ export const OUTPUT_STREAM_GET_TOTAL_BYTES = ++call_id << CALL_SHIFT;
|
|
|
38
38
|
// Filesystem descriptors
|
|
39
39
|
export const FILESYSTEM_DESCRIPTOR_OPEN = ++call_id << CALL_SHIFT;
|
|
40
40
|
export const FILESYSTEM_DESCRIPTOR_CLOSE = ++call_id << CALL_SHIFT;
|
|
41
|
+
export const FILESYSTEM_DESCRIPTOR_ADVISE = ++call_id << CALL_SHIFT;
|
|
41
42
|
export const FILESYSTEM_DESCRIPTOR_SYNC_DATA = ++call_id << CALL_SHIFT;
|
|
42
43
|
export const FILESYSTEM_DESCRIPTOR_GET_TYPE = ++call_id << CALL_SHIFT;
|
|
43
44
|
export const FILESYSTEM_DESCRIPTOR_SET_SIZE = ++call_id << CALL_SHIFT;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Advice } from "@bytecodealliance/jco-node-fs";
|
|
1
2
|
export declare function openFileResource(path: string, flags: number): Promise<{
|
|
2
3
|
id: number;
|
|
3
4
|
type: any;
|
|
@@ -5,6 +6,7 @@ export declare function openFileResource(path: string, flags: number): Promise<{
|
|
|
5
6
|
export declare function retainFileResource(id: number): number;
|
|
6
7
|
export declare function releaseFileResource(id: number): Promise<void>;
|
|
7
8
|
export declare function fileResourceFd(id: number): number;
|
|
9
|
+
export declare function adviseFileResource(id: number, offset: bigint, length: bigint, advice: Advice): void;
|
|
8
10
|
export declare function syncFileResourceData(id: number): Promise<void>;
|
|
9
11
|
export declare function getFileResourceType(id: number): Promise<"block-device" | "character-device" | "directory" | "fifo" | "regular-file" | "socket" | "symbolic-link" | "unknown">;
|
|
10
12
|
export declare function setFileResourceSize(id: number, size: number): Promise<void>;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import { promisify } from "node:util";
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
let nativeFadvise;
|
|
3
6
|
const closeAsync = promisify(fs.close);
|
|
4
7
|
const fdatasyncAsync = promisify(fs.fdatasync);
|
|
5
8
|
const fstatAsync = promisify(fs.fstat);
|
|
@@ -72,6 +75,10 @@ export async function releaseFileResource(id) {
|
|
|
72
75
|
export function fileResourceFd(id) {
|
|
73
76
|
return getFileResource(id).fd;
|
|
74
77
|
}
|
|
78
|
+
export function adviseFileResource(id, offset, length, advice) {
|
|
79
|
+
const fadvise = (nativeFadvise ??= require("@bytecodealliance/jco-node-fs").fadvise);
|
|
80
|
+
fadvise(fileResourceFd(id), offset, length, advice);
|
|
81
|
+
}
|
|
75
82
|
export async function syncFileResourceData(id) {
|
|
76
83
|
await fdatasyncAsync(fileResourceFd(id));
|
|
77
84
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PollState } from "./worker-thread.js";
|
|
2
|
-
import { Socket as TcpSocket } from "node:net";
|
|
2
|
+
import { Server, Socket as TcpSocket } from "node:net";
|
|
3
3
|
import { IpSocketAddress } from "../../types/interfaces/wasi-sockets-network.js";
|
|
4
4
|
interface PendingAccept {
|
|
5
5
|
tcpSocket: TcpSocket | null;
|
|
@@ -10,8 +10,11 @@ interface TcpSocketRecord {
|
|
|
10
10
|
state: number;
|
|
11
11
|
future: number | null;
|
|
12
12
|
tcpSocket: TcpSocket | null;
|
|
13
|
+
server: Server | null;
|
|
14
|
+
localAddress: IpSocketAddress | null;
|
|
13
15
|
listenBacklogSize: number;
|
|
14
|
-
|
|
16
|
+
keepAlive: boolean;
|
|
17
|
+
keepAliveIdleTime: number;
|
|
15
18
|
pendingAccepts: PendingAccept[];
|
|
16
19
|
pollState: PollState | null;
|
|
17
20
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { createFuture, createReadableStream, createReadableStreamPollState, createWritableStream, futureDispose, futureTakeValue, pollStateReady, verifyPollsDroppedForDrop, } from "./worker-thread.js";
|
|
2
2
|
import process from "node:process";
|
|
3
|
-
|
|
4
|
-
const { TCP, constants: TCPConstants } = process.binding("tcp_wrap");
|
|
5
|
-
import { convertSocketError, convertSocketErrorCode, ipSocketAddress, isIPv4MappedAddress, isMulticastIpAddress, isUnicastIpAddress, isWildcardAddress, noLookup, serializeIpAddress, SOCKET_STATE_BIND, SOCKET_STATE_BOUND, SOCKET_STATE_CLOSED, SOCKET_STATE_CONNECT, SOCKET_STATE_CONNECTION, SOCKET_STATE_INIT, SOCKET_STATE_LISTEN, SOCKET_STATE_LISTENER, } from "./worker-sockets.js";
|
|
3
|
+
import { convertSocketError, ipSocketAddress, isIPv4MappedAddress, isMulticastIpAddress, isUnicastIpAddress, isWildcardAddress, noLookup, serializeIpAddress, SOCKET_STATE_BIND, SOCKET_STATE_BOUND, SOCKET_STATE_CLOSED, SOCKET_STATE_CONNECT, SOCKET_STATE_CONNECTION, SOCKET_STATE_INIT, SOCKET_STATE_LISTEN, SOCKET_STATE_LISTENER, } from "./worker-sockets.js";
|
|
6
4
|
import { Server, Socket as TcpSocket } from "node:net";
|
|
7
5
|
const win = process.platform === "win32";
|
|
8
6
|
export const tcpSockets = new Map();
|
|
9
7
|
let tcpSocketCnt = 0;
|
|
10
8
|
export function createTcpSocket() {
|
|
11
|
-
const handle = new TCP(TCPConstants.SOCKET);
|
|
12
9
|
tcpSockets.set(++tcpSocketCnt, {
|
|
13
10
|
state: SOCKET_STATE_INIT,
|
|
14
11
|
future: null,
|
|
15
12
|
tcpSocket: null,
|
|
13
|
+
server: null,
|
|
14
|
+
localAddress: null,
|
|
16
15
|
listenBacklogSize: 128,
|
|
17
|
-
|
|
16
|
+
keepAlive: false,
|
|
17
|
+
keepAliveIdleTime: 0,
|
|
18
18
|
pendingAccepts: [],
|
|
19
19
|
pollState: {
|
|
20
20
|
ready: true,
|
|
@@ -44,7 +44,7 @@ export function socketTcpFinish(id, fromState, toState) {
|
|
|
44
44
|
socket.state = toState;
|
|
45
45
|
// for the listener, we must immediately transition back to unresolved
|
|
46
46
|
if (toState === SOCKET_STATE_LISTENER) {
|
|
47
|
-
socket.pollState.ready =
|
|
47
|
+
socket.pollState.ready = socket.pendingAccepts.length > 0;
|
|
48
48
|
}
|
|
49
49
|
return val;
|
|
50
50
|
}
|
|
@@ -60,26 +60,77 @@ export function socketTcpBindStart(id, localAddress, family) {
|
|
|
60
60
|
throw "invalid-argument";
|
|
61
61
|
}
|
|
62
62
|
socket.state = SOCKET_STATE_BIND;
|
|
63
|
-
|
|
64
|
-
socket.future = createFuture((async () => {
|
|
63
|
+
socket.future = createFuture(new Promise((resolve, reject) => {
|
|
65
64
|
const address = serializeIpAddress(localAddress);
|
|
66
65
|
const port = localAddress.val.port;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
// node:net has no public standalone TCP bind API. Keep a server open
|
|
67
|
+
// to reserve the endpoint, then reuse it for listen or close it for connect.
|
|
68
|
+
const server = (socket.server = createTcpServer(socket));
|
|
69
|
+
function handleErr(err) {
|
|
70
|
+
server.off("listening", handleListen);
|
|
71
|
+
reject(convertSocketError(err));
|
|
72
72
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
throw convertSocketErrorCode(-code);
|
|
73
|
+
function handleListen() {
|
|
74
|
+
server.off("error", handleErr);
|
|
75
|
+
const boundAddress = server.address();
|
|
76
|
+
if (!boundAddress || typeof boundAddress === "string") {
|
|
77
|
+
reject("invalid-state");
|
|
78
|
+
return;
|
|
80
79
|
}
|
|
80
|
+
socket.localAddress = ipSocketAddress(boundAddress.family.toLowerCase(), boundAddress.address, boundAddress.port);
|
|
81
|
+
resolve();
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
+
server.once("listening", handleListen);
|
|
84
|
+
server.once("error", handleErr);
|
|
85
|
+
server.listen({
|
|
86
|
+
host: address ?? undefined,
|
|
87
|
+
port,
|
|
88
|
+
backlog: socket.listenBacklogSize,
|
|
89
|
+
ipv6Only: family === "ipv6",
|
|
90
|
+
});
|
|
91
|
+
}), socket.pollState);
|
|
92
|
+
}
|
|
93
|
+
function createTcpServer(socket) {
|
|
94
|
+
const server = new Server({
|
|
95
|
+
pauseOnConnect: true,
|
|
96
|
+
allowHalfOpen: true,
|
|
97
|
+
});
|
|
98
|
+
server.on("connection", (tcpSocket) => {
|
|
99
|
+
// The reservation is already listening at the OS level, so reject any
|
|
100
|
+
// connections that arrive before the WASI socket enters its listen state.
|
|
101
|
+
if (socket.state !== SOCKET_STATE_LISTEN && socket.state !== SOCKET_STATE_LISTENER) {
|
|
102
|
+
tcpSocket.destroy();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
pollStateReady(socket.pollState);
|
|
106
|
+
const pollState = createReadableStreamPollState(tcpSocket);
|
|
107
|
+
socket.pendingAccepts.push({
|
|
108
|
+
tcpSocket,
|
|
109
|
+
err: null,
|
|
110
|
+
pollState,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
server.on("error", (err) => {
|
|
114
|
+
if (socket.state === SOCKET_STATE_LISTEN || socket.state === SOCKET_STATE_LISTENER) {
|
|
115
|
+
pollStateReady(socket.pollState);
|
|
116
|
+
socket.pendingAccepts.push({
|
|
117
|
+
tcpSocket: null,
|
|
118
|
+
err,
|
|
119
|
+
pollState: null,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return server;
|
|
124
|
+
}
|
|
125
|
+
function closeTcpServer(socket) {
|
|
126
|
+
const server = socket.server;
|
|
127
|
+
socket.server = null;
|
|
128
|
+
if (!server) {
|
|
129
|
+
return Promise.resolve();
|
|
130
|
+
}
|
|
131
|
+
return new Promise((resolve, reject) => {
|
|
132
|
+
server.close((err) => (err ? reject(err) : resolve()));
|
|
133
|
+
});
|
|
83
134
|
}
|
|
84
135
|
export function socketTcpConnectStart(id, remoteAddress, family) {
|
|
85
136
|
const socket = tcpSockets.get(id);
|
|
@@ -95,71 +146,44 @@ export function socketTcpConnectStart(id, remoteAddress, family) {
|
|
|
95
146
|
throw "invalid-argument";
|
|
96
147
|
}
|
|
97
148
|
socket.state = SOCKET_STATE_CONNECT;
|
|
98
|
-
socket.future = createFuture(
|
|
149
|
+
socket.future = createFuture((async () => {
|
|
150
|
+
const localAddress = socket.localAddress;
|
|
151
|
+
await closeTcpServer(socket);
|
|
99
152
|
const tcpSocket = (socket.tcpSocket = new TcpSocket({
|
|
100
|
-
// @ts-expect-error Not present in type definition
|
|
101
|
-
handle: socket.handle,
|
|
102
|
-
pauseOnCreate: true,
|
|
103
153
|
allowHalfOpen: true,
|
|
104
154
|
}));
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
155
|
+
tcpSocket.setKeepAlive(socket.keepAlive, socket.keepAliveIdleTime);
|
|
156
|
+
await new Promise((resolve, reject) => {
|
|
157
|
+
function handleErr(err) {
|
|
158
|
+
tcpSocket.off("connect", handleConnect);
|
|
159
|
+
reject(convertSocketError(err));
|
|
160
|
+
}
|
|
161
|
+
function handleConnect() {
|
|
162
|
+
tcpSocket.off("error", handleErr);
|
|
163
|
+
resolve();
|
|
164
|
+
}
|
|
165
|
+
tcpSocket.once("connect", handleConnect);
|
|
166
|
+
tcpSocket.once("error", handleErr);
|
|
167
|
+
tcpSocket.connect({
|
|
168
|
+
port: remoteAddress.val.port,
|
|
169
|
+
host: serializeIpAddress(remoteAddress) ?? undefined,
|
|
170
|
+
lookup: noLookup,
|
|
171
|
+
localAddress: localAddress
|
|
172
|
+
? (serializeIpAddress(localAddress) ?? undefined)
|
|
173
|
+
: undefined,
|
|
174
|
+
localPort: localAddress?.val.port,
|
|
175
|
+
});
|
|
119
176
|
});
|
|
120
|
-
|
|
177
|
+
return [createReadableStream(tcpSocket), createWritableStream(tcpSocket)];
|
|
178
|
+
})(), socket.pollState);
|
|
121
179
|
}
|
|
122
180
|
export function socketTcpListenStart(id) {
|
|
123
181
|
const socket = tcpSockets.get(id);
|
|
124
182
|
if (socket.state !== SOCKET_STATE_BOUND) {
|
|
125
183
|
throw "invalid-state";
|
|
126
184
|
}
|
|
127
|
-
const { handle } = socket;
|
|
128
185
|
socket.state = SOCKET_STATE_LISTEN;
|
|
129
|
-
socket.future = createFuture(
|
|
130
|
-
const server = new Server({
|
|
131
|
-
pauseOnConnect: true,
|
|
132
|
-
allowHalfOpen: true,
|
|
133
|
-
});
|
|
134
|
-
function handleErr(err) {
|
|
135
|
-
server.off("listening", handleListen);
|
|
136
|
-
reject(convertSocketError(err));
|
|
137
|
-
}
|
|
138
|
-
function handleListen() {
|
|
139
|
-
server.off("error", handleErr);
|
|
140
|
-
server.on("connection", (tcpSocket) => {
|
|
141
|
-
pollStateReady(socket.pollState);
|
|
142
|
-
const pollState = createReadableStreamPollState(tcpSocket);
|
|
143
|
-
socket.pendingAccepts.push({
|
|
144
|
-
tcpSocket,
|
|
145
|
-
err: null,
|
|
146
|
-
pollState,
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
server.on("error", (err) => {
|
|
150
|
-
pollStateReady(socket.pollState);
|
|
151
|
-
socket.pendingAccepts.push({
|
|
152
|
-
tcpSocket: null,
|
|
153
|
-
err,
|
|
154
|
-
pollState: null,
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
resolve();
|
|
158
|
-
}
|
|
159
|
-
server.once("listening", handleListen);
|
|
160
|
-
server.once("error", handleErr);
|
|
161
|
-
server.listen(handle, socket.listenBacklogSize);
|
|
162
|
-
}), socket.pollState);
|
|
186
|
+
socket.future = createFuture(Promise.resolve(), socket.pollState);
|
|
163
187
|
}
|
|
164
188
|
export function socketTcpAccept(id) {
|
|
165
189
|
const socket = tcpSockets.get(id);
|
|
@@ -181,9 +205,11 @@ export function socketTcpAccept(id) {
|
|
|
181
205
|
state: SOCKET_STATE_CONNECTION,
|
|
182
206
|
future: null,
|
|
183
207
|
tcpSocket: accept.tcpSocket,
|
|
208
|
+
server: null,
|
|
209
|
+
localAddress: null,
|
|
184
210
|
listenBacklogSize: 128,
|
|
185
|
-
|
|
186
|
-
|
|
211
|
+
keepAlive: false,
|
|
212
|
+
keepAliveIdleTime: 0,
|
|
187
213
|
pendingAccepts: [],
|
|
188
214
|
pollState: accept.pollState,
|
|
189
215
|
});
|
|
@@ -207,22 +233,22 @@ export function socketTcpSetListenBacklogSize(id, backlogSize) {
|
|
|
207
233
|
socket.listenBacklogSize = Number(backlogSize);
|
|
208
234
|
}
|
|
209
235
|
export function socketTcpGetLocalAddress(id) {
|
|
210
|
-
const
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
236
|
+
const socket = tcpSockets.get(id);
|
|
237
|
+
const address = socket.tcpSocket?.address();
|
|
238
|
+
if (address && typeof address !== "string" && "family" in address) {
|
|
239
|
+
return ipSocketAddress(address.family.toLowerCase(), address.address, address.port);
|
|
240
|
+
}
|
|
241
|
+
if (socket.localAddress) {
|
|
242
|
+
return socket.localAddress;
|
|
215
243
|
}
|
|
216
|
-
|
|
244
|
+
throw "invalid-state";
|
|
217
245
|
}
|
|
218
246
|
export function socketTcpGetRemoteAddress(id) {
|
|
219
|
-
const {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (code !== 0) {
|
|
223
|
-
throw convertSocketErrorCode(-code);
|
|
247
|
+
const { tcpSocket } = tcpSockets.get(id);
|
|
248
|
+
if (!tcpSocket?.remoteFamily || !tcpSocket.remoteAddress || !tcpSocket.remotePort) {
|
|
249
|
+
throw "invalid-state";
|
|
224
250
|
}
|
|
225
|
-
return ipSocketAddress(
|
|
251
|
+
return ipSocketAddress(tcpSocket.remoteFamily.toLowerCase(), tcpSocket.remoteAddress, tcpSocket.remotePort);
|
|
226
252
|
}
|
|
227
253
|
export function socketTcpShutdown(id, _shutdownType) {
|
|
228
254
|
const socket = tcpSockets.get(id);
|
|
@@ -237,15 +263,15 @@ export function socketTcpShutdown(id, _shutdownType) {
|
|
|
237
263
|
}
|
|
238
264
|
}
|
|
239
265
|
export function socketTcpSetKeepAlive(id, { keepAlive, keepAliveIdleTime }) {
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
266
|
+
const socket = tcpSockets.get(id);
|
|
267
|
+
socket.keepAlive = keepAlive;
|
|
268
|
+
socket.keepAliveIdleTime = Number(keepAliveIdleTime / 1000000000n);
|
|
269
|
+
socket.tcpSocket?.setKeepAlive(socket.keepAlive, socket.keepAliveIdleTime);
|
|
245
270
|
}
|
|
246
271
|
export function socketTcpDispose(id) {
|
|
247
272
|
const socket = tcpSockets.get(id);
|
|
248
273
|
verifyPollsDroppedForDrop(socket.pollState, "tcp socket");
|
|
249
|
-
socket.
|
|
274
|
+
socket.server?.close();
|
|
275
|
+
socket.tcpSocket?.destroy();
|
|
250
276
|
tcpSockets.delete(id);
|
|
251
277
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
1
2
|
import fs, { createReadStream, createWriteStream, read } from "node:fs";
|
|
2
3
|
import process, { hrtime, nextTick, stderr, stdout } from "node:process";
|
|
3
4
|
import { PassThrough, Readable } from "node:stream";
|
|
@@ -79,6 +80,7 @@ var calls_exports = /* @__PURE__ */ __exportAll({
|
|
|
79
80
|
CLOCKS_DURATION_SUBSCRIBE: () => CLOCKS_DURATION_SUBSCRIBE,
|
|
80
81
|
CLOCKS_INSTANT_SUBSCRIBE: () => CLOCKS_INSTANT_SUBSCRIBE,
|
|
81
82
|
FILE: () => FILE,
|
|
83
|
+
FILESYSTEM_DESCRIPTOR_ADVISE: () => FILESYSTEM_DESCRIPTOR_ADVISE,
|
|
82
84
|
FILESYSTEM_DESCRIPTOR_CLOSE: () => FILESYSTEM_DESCRIPTOR_CLOSE,
|
|
83
85
|
FILESYSTEM_DESCRIPTOR_GET_TYPE: () => FILESYSTEM_DESCRIPTOR_GET_TYPE,
|
|
84
86
|
FILESYSTEM_DESCRIPTOR_METADATA_HASH: () => FILESYSTEM_DESCRIPTOR_METADATA_HASH,
|
|
@@ -209,6 +211,7 @@ const OUTPUT_STREAM_DISPOSE = ++call_id << 24;
|
|
|
209
211
|
const OUTPUT_STREAM_GET_TOTAL_BYTES = ++call_id << 24;
|
|
210
212
|
const FILESYSTEM_DESCRIPTOR_OPEN = ++call_id << 24;
|
|
211
213
|
const FILESYSTEM_DESCRIPTOR_CLOSE = ++call_id << 24;
|
|
214
|
+
const FILESYSTEM_DESCRIPTOR_ADVISE = ++call_id << 24;
|
|
212
215
|
const FILESYSTEM_DESCRIPTOR_SYNC_DATA = ++call_id << 24;
|
|
213
216
|
const FILESYSTEM_DESCRIPTOR_GET_TYPE = ++call_id << 24;
|
|
214
217
|
const FILESYSTEM_DESCRIPTOR_SET_SIZE = ++call_id << 24;
|
|
@@ -427,6 +430,8 @@ function getFirstError(e) {
|
|
|
427
430
|
}
|
|
428
431
|
//#endregion
|
|
429
432
|
//#region dist/io/worker-filesystem.js
|
|
433
|
+
const require = createRequire(import.meta.url);
|
|
434
|
+
let nativeFadvise;
|
|
430
435
|
const closeAsync = promisify(fs.close);
|
|
431
436
|
const fdatasyncAsync = promisify(fs.fdatasync);
|
|
432
437
|
const fstatAsync = promisify(fs.fstat);
|
|
@@ -490,6 +495,9 @@ async function releaseFileResource(id) {
|
|
|
490
495
|
function fileResourceFd(id) {
|
|
491
496
|
return getFileResource(id).fd;
|
|
492
497
|
}
|
|
498
|
+
function adviseFileResource(id, offset, length, advice) {
|
|
499
|
+
(nativeFadvise ??= require("@bytecodealliance/jco-node-fs").fadvise)(fileResourceFd(id), offset, length, advice);
|
|
500
|
+
}
|
|
493
501
|
async function syncFileResourceData(id) {
|
|
494
502
|
await fdatasyncAsync(fileResourceFd(id));
|
|
495
503
|
}
|
|
@@ -719,18 +727,19 @@ async function getDefaultReceiveBufferSize() {
|
|
|
719
727
|
}
|
|
720
728
|
//#endregion
|
|
721
729
|
//#region dist/io/worker-socket-tcp.js
|
|
722
|
-
const { TCP, constants: TCPConstants } = process.binding("tcp_wrap");
|
|
723
730
|
const win = process.platform === "win32";
|
|
724
731
|
const tcpSockets = /* @__PURE__ */ new Map();
|
|
725
732
|
let tcpSocketCnt = 0;
|
|
726
733
|
function createTcpSocket() {
|
|
727
|
-
const handle = new TCP(TCPConstants.SOCKET);
|
|
728
734
|
tcpSockets.set(++tcpSocketCnt, {
|
|
729
735
|
state: SOCKET_STATE_INIT,
|
|
730
736
|
future: null,
|
|
731
737
|
tcpSocket: null,
|
|
738
|
+
server: null,
|
|
739
|
+
localAddress: null,
|
|
732
740
|
listenBacklogSize: 128,
|
|
733
|
-
|
|
741
|
+
keepAlive: false,
|
|
742
|
+
keepAliveIdleTime: 0,
|
|
734
743
|
pendingAccepts: [],
|
|
735
744
|
pollState: {
|
|
736
745
|
ready: true,
|
|
@@ -753,7 +762,7 @@ function socketTcpFinish(id, fromState, toState) {
|
|
|
753
762
|
throw val;
|
|
754
763
|
} else {
|
|
755
764
|
socket.state = toState;
|
|
756
|
-
if (toState === SOCKET_STATE_LISTENER) socket.pollState.ready =
|
|
765
|
+
if (toState === SOCKET_STATE_LISTENER) socket.pollState.ready = socket.pendingAccepts.length > 0;
|
|
757
766
|
return val;
|
|
758
767
|
}
|
|
759
768
|
}
|
|
@@ -762,85 +771,109 @@ function socketTcpBindStart(id, localAddress, family) {
|
|
|
762
771
|
if (socket.state !== SOCKET_STATE_INIT) throw "invalid-state";
|
|
763
772
|
if (family !== localAddress.tag || !isUnicastIpAddress(localAddress) || isIPv4MappedAddress(localAddress)) throw "invalid-argument";
|
|
764
773
|
socket.state = SOCKET_STATE_BIND;
|
|
765
|
-
|
|
766
|
-
socket.future = createFuture((async () => {
|
|
774
|
+
socket.future = createFuture(new Promise((resolve, reject) => {
|
|
767
775
|
const address = serializeIpAddress(localAddress);
|
|
768
776
|
const port = localAddress.val.port;
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
if (code !== 0) throw convertSocketErrorCode(-code);
|
|
777
|
+
const server = socket.server = createTcpServer(socket);
|
|
778
|
+
function handleErr(err) {
|
|
779
|
+
server.off("listening", handleListen);
|
|
780
|
+
reject(convertSocketError(err));
|
|
774
781
|
}
|
|
775
|
-
|
|
782
|
+
function handleListen() {
|
|
783
|
+
server.off("error", handleErr);
|
|
784
|
+
const boundAddress = server.address();
|
|
785
|
+
if (!boundAddress || typeof boundAddress === "string") {
|
|
786
|
+
reject("invalid-state");
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
socket.localAddress = ipSocketAddress(boundAddress.family.toLowerCase(), boundAddress.address, boundAddress.port);
|
|
790
|
+
resolve();
|
|
791
|
+
}
|
|
792
|
+
server.once("listening", handleListen);
|
|
793
|
+
server.once("error", handleErr);
|
|
794
|
+
server.listen({
|
|
795
|
+
host: address ?? void 0,
|
|
796
|
+
port,
|
|
797
|
+
backlog: socket.listenBacklogSize,
|
|
798
|
+
ipv6Only: family === "ipv6"
|
|
799
|
+
});
|
|
800
|
+
}), socket.pollState);
|
|
801
|
+
}
|
|
802
|
+
function createTcpServer(socket) {
|
|
803
|
+
const server = new Server({
|
|
804
|
+
pauseOnConnect: true,
|
|
805
|
+
allowHalfOpen: true
|
|
806
|
+
});
|
|
807
|
+
server.on("connection", (tcpSocket) => {
|
|
808
|
+
if (socket.state !== SOCKET_STATE_LISTEN && socket.state !== SOCKET_STATE_LISTENER) {
|
|
809
|
+
tcpSocket.destroy();
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
pollStateReady(socket.pollState);
|
|
813
|
+
const pollState = createReadableStreamPollState(tcpSocket);
|
|
814
|
+
socket.pendingAccepts.push({
|
|
815
|
+
tcpSocket,
|
|
816
|
+
err: null,
|
|
817
|
+
pollState
|
|
818
|
+
});
|
|
819
|
+
});
|
|
820
|
+
server.on("error", (err) => {
|
|
821
|
+
if (socket.state === SOCKET_STATE_LISTEN || socket.state === SOCKET_STATE_LISTENER) {
|
|
822
|
+
pollStateReady(socket.pollState);
|
|
823
|
+
socket.pendingAccepts.push({
|
|
824
|
+
tcpSocket: null,
|
|
825
|
+
err,
|
|
826
|
+
pollState: null
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
return server;
|
|
831
|
+
}
|
|
832
|
+
function closeTcpServer(socket) {
|
|
833
|
+
const server = socket.server;
|
|
834
|
+
socket.server = null;
|
|
835
|
+
if (!server) return Promise.resolve();
|
|
836
|
+
return new Promise((resolve, reject) => {
|
|
837
|
+
server.close((err) => err ? reject(err) : resolve());
|
|
838
|
+
});
|
|
776
839
|
}
|
|
777
840
|
function socketTcpConnectStart(id, remoteAddress, family) {
|
|
778
841
|
const socket = tcpSockets.get(id);
|
|
779
842
|
if (socket.state !== SOCKET_STATE_INIT && socket.state !== SOCKET_STATE_BOUND) throw "invalid-state";
|
|
780
843
|
if (isWildcardAddress(remoteAddress) || family !== remoteAddress.tag || !isUnicastIpAddress(remoteAddress) || isMulticastIpAddress(remoteAddress) || remoteAddress.val.port === 0 || isIPv4MappedAddress(remoteAddress)) throw "invalid-argument";
|
|
781
844
|
socket.state = SOCKET_STATE_CONNECT;
|
|
782
|
-
socket.future = createFuture(
|
|
783
|
-
const
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
845
|
+
socket.future = createFuture((async () => {
|
|
846
|
+
const localAddress = socket.localAddress;
|
|
847
|
+
await closeTcpServer(socket);
|
|
848
|
+
const tcpSocket = socket.tcpSocket = new Socket({ allowHalfOpen: true });
|
|
849
|
+
tcpSocket.setKeepAlive(socket.keepAlive, socket.keepAliveIdleTime);
|
|
850
|
+
await new Promise((resolve, reject) => {
|
|
851
|
+
function handleErr(err) {
|
|
852
|
+
tcpSocket.off("connect", handleConnect);
|
|
853
|
+
reject(convertSocketError(err));
|
|
854
|
+
}
|
|
855
|
+
function handleConnect() {
|
|
856
|
+
tcpSocket.off("error", handleErr);
|
|
857
|
+
resolve();
|
|
858
|
+
}
|
|
859
|
+
tcpSocket.once("connect", handleConnect);
|
|
860
|
+
tcpSocket.once("error", handleErr);
|
|
861
|
+
tcpSocket.connect({
|
|
862
|
+
port: remoteAddress.val.port,
|
|
863
|
+
host: serializeIpAddress(remoteAddress) ?? void 0,
|
|
864
|
+
lookup: noLookup,
|
|
865
|
+
localAddress: localAddress ? serializeIpAddress(localAddress) ?? void 0 : void 0,
|
|
866
|
+
localPort: localAddress?.val.port
|
|
867
|
+
});
|
|
802
868
|
});
|
|
803
|
-
|
|
869
|
+
return [createReadableStream(tcpSocket), createWritableStream(tcpSocket)];
|
|
870
|
+
})(), socket.pollState);
|
|
804
871
|
}
|
|
805
872
|
function socketTcpListenStart(id) {
|
|
806
873
|
const socket = tcpSockets.get(id);
|
|
807
874
|
if (socket.state !== SOCKET_STATE_BOUND) throw "invalid-state";
|
|
808
|
-
const { handle } = socket;
|
|
809
875
|
socket.state = SOCKET_STATE_LISTEN;
|
|
810
|
-
socket.future = createFuture(
|
|
811
|
-
const server = new Server({
|
|
812
|
-
pauseOnConnect: true,
|
|
813
|
-
allowHalfOpen: true
|
|
814
|
-
});
|
|
815
|
-
function handleErr(err) {
|
|
816
|
-
server.off("listening", handleListen);
|
|
817
|
-
reject(convertSocketError(err));
|
|
818
|
-
}
|
|
819
|
-
function handleListen() {
|
|
820
|
-
server.off("error", handleErr);
|
|
821
|
-
server.on("connection", (tcpSocket) => {
|
|
822
|
-
pollStateReady(socket.pollState);
|
|
823
|
-
const pollState = createReadableStreamPollState(tcpSocket);
|
|
824
|
-
socket.pendingAccepts.push({
|
|
825
|
-
tcpSocket,
|
|
826
|
-
err: null,
|
|
827
|
-
pollState
|
|
828
|
-
});
|
|
829
|
-
});
|
|
830
|
-
server.on("error", (err) => {
|
|
831
|
-
pollStateReady(socket.pollState);
|
|
832
|
-
socket.pendingAccepts.push({
|
|
833
|
-
tcpSocket: null,
|
|
834
|
-
err,
|
|
835
|
-
pollState: null
|
|
836
|
-
});
|
|
837
|
-
});
|
|
838
|
-
resolve();
|
|
839
|
-
}
|
|
840
|
-
server.once("listening", handleListen);
|
|
841
|
-
server.once("error", handleErr);
|
|
842
|
-
server.listen(handle, socket.listenBacklogSize);
|
|
843
|
-
}), socket.pollState);
|
|
876
|
+
socket.future = createFuture(Promise.resolve(), socket.pollState);
|
|
844
877
|
}
|
|
845
878
|
function socketTcpAccept(id) {
|
|
846
879
|
const socket = tcpSockets.get(id);
|
|
@@ -856,8 +889,11 @@ function socketTcpAccept(id) {
|
|
|
856
889
|
state: SOCKET_STATE_CONNECTION,
|
|
857
890
|
future: null,
|
|
858
891
|
tcpSocket: accept.tcpSocket,
|
|
892
|
+
server: null,
|
|
893
|
+
localAddress: null,
|
|
859
894
|
listenBacklogSize: 128,
|
|
860
|
-
|
|
895
|
+
keepAlive: false,
|
|
896
|
+
keepAliveIdleTime: 0,
|
|
861
897
|
pendingAccepts: [],
|
|
862
898
|
pollState: accept.pollState
|
|
863
899
|
});
|
|
@@ -874,18 +910,16 @@ function socketTcpSetListenBacklogSize(id, backlogSize) {
|
|
|
874
910
|
socket.listenBacklogSize = Number(backlogSize);
|
|
875
911
|
}
|
|
876
912
|
function socketTcpGetLocalAddress(id) {
|
|
877
|
-
const
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
if (
|
|
881
|
-
|
|
913
|
+
const socket = tcpSockets.get(id);
|
|
914
|
+
const address = socket.tcpSocket?.address();
|
|
915
|
+
if (address && typeof address !== "string" && "family" in address) return ipSocketAddress(address.family.toLowerCase(), address.address, address.port);
|
|
916
|
+
if (socket.localAddress) return socket.localAddress;
|
|
917
|
+
throw "invalid-state";
|
|
882
918
|
}
|
|
883
919
|
function socketTcpGetRemoteAddress(id) {
|
|
884
|
-
const {
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
if (code !== 0) throw convertSocketErrorCode(-code);
|
|
888
|
-
return ipSocketAddress(out.family.toLowerCase(), out.address, out.port);
|
|
920
|
+
const { tcpSocket } = tcpSockets.get(id);
|
|
921
|
+
if (!tcpSocket?.remoteFamily || !tcpSocket.remoteAddress || !tcpSocket.remotePort) throw "invalid-state";
|
|
922
|
+
return ipSocketAddress(tcpSocket.remoteFamily.toLowerCase(), tcpSocket.remoteAddress, tcpSocket.remotePort);
|
|
889
923
|
}
|
|
890
924
|
function socketTcpShutdown(id, _shutdownType) {
|
|
891
925
|
const socket = tcpSockets.get(id);
|
|
@@ -894,14 +928,16 @@ function socketTcpShutdown(id, _shutdownType) {
|
|
|
894
928
|
else socket.tcpSocket?.destroy();
|
|
895
929
|
}
|
|
896
930
|
function socketTcpSetKeepAlive(id, { keepAlive, keepAliveIdleTime }) {
|
|
897
|
-
const
|
|
898
|
-
|
|
899
|
-
|
|
931
|
+
const socket = tcpSockets.get(id);
|
|
932
|
+
socket.keepAlive = keepAlive;
|
|
933
|
+
socket.keepAliveIdleTime = Number(keepAliveIdleTime / 1000000000n);
|
|
934
|
+
socket.tcpSocket?.setKeepAlive(socket.keepAlive, socket.keepAliveIdleTime);
|
|
900
935
|
}
|
|
901
936
|
function socketTcpDispose(id) {
|
|
902
937
|
const socket = tcpSockets.get(id);
|
|
903
938
|
verifyPollsDroppedForDrop(socket.pollState, "tcp socket");
|
|
904
|
-
socket.
|
|
939
|
+
socket.server?.close();
|
|
940
|
+
socket.tcpSocket?.destroy();
|
|
905
941
|
tcpSockets.delete(id);
|
|
906
942
|
}
|
|
907
943
|
//#endregion
|
|
@@ -1556,6 +1592,7 @@ function handle(call, id, payload) {
|
|
|
1556
1592
|
}
|
|
1557
1593
|
case FILESYSTEM_DESCRIPTOR_OPEN: return openFileResource(payload.path, payload.flags);
|
|
1558
1594
|
case FILESYSTEM_DESCRIPTOR_CLOSE: return releaseFileResource(id);
|
|
1595
|
+
case FILESYSTEM_DESCRIPTOR_ADVISE: return adviseFileResource(id, payload.offset, payload.length, payload.advice);
|
|
1559
1596
|
case FILESYSTEM_DESCRIPTOR_SYNC_DATA: return syncFileResourceData(id);
|
|
1560
1597
|
case FILESYSTEM_DESCRIPTOR_GET_TYPE: return getFileResourceType(id);
|
|
1561
1598
|
case FILESYSTEM_DESCRIPTOR_SET_SIZE: return setFileResourceSize(id, payload);
|
package/dist/io/worker-thread.js
CHANGED
|
@@ -6,8 +6,8 @@ import { clearOutgoingResponse, createHttpRequest, setOutgoingResponse, startHtt
|
|
|
6
6
|
import { Readable } from "node:stream";
|
|
7
7
|
import { read } from "node:fs";
|
|
8
8
|
import { nextTick } from "node:process";
|
|
9
|
-
import { CALL_MASK, CALL_TYPE_MASK, CLOCKS_DURATION_SUBSCRIBE, CLOCKS_INSTANT_SUBSCRIBE, FILE, FILESYSTEM_DESCRIPTOR_CLOSE, FILESYSTEM_DESCRIPTOR_GET_TYPE, FILESYSTEM_DESCRIPTOR_METADATA_HASH, FILESYSTEM_DESCRIPTOR_OPEN, FILESYSTEM_DESCRIPTOR_READ, FILESYSTEM_DESCRIPTOR_SET_SIZE, FILESYSTEM_DESCRIPTOR_SET_TIMES, FILESYSTEM_DESCRIPTOR_STAT, FILESYSTEM_DESCRIPTOR_SYNC, FILESYSTEM_DESCRIPTOR_SYNC_DATA, FILESYSTEM_DESCRIPTOR_WRITE, FUTURE_DISPOSE, FUTURE_SUBSCRIBE, FUTURE_TAKE_VALUE, HTTP, HTTP_CREATE_REQUEST, HTTP_OUTGOING_BODY_DISPOSE, HTTP_OUTPUT_STREAM_FINISH, HTTP_SERVER_CLEAR_OUTGOING_RESPONSE, HTTP_SERVER_SET_OUTGOING_RESPONSE, HTTP_SERVER_START, HTTP_SERVER_STOP, HTTP_SERVER_GET_ADDRESS, INPUT_STREAM_BLOCKING_READ, INPUT_STREAM_BLOCKING_SKIP, INPUT_STREAM_CREATE, INPUT_STREAM_DISPOSE, INPUT_STREAM_READ, INPUT_STREAM_SKIP, INPUT_STREAM_SUBSCRIBE, OUTPUT_STREAM_BLOCKING_FLUSH, OUTPUT_STREAM_BLOCKING_SPLICE, OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH, OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH, OUTPUT_STREAM_CHECK_WRITE, OUTPUT_STREAM_CREATE, OUTPUT_STREAM_DISPOSE, OUTPUT_STREAM_FLUSH, OUTPUT_STREAM_SPLICE, OUTPUT_STREAM_SUBSCRIBE, OUTPUT_STREAM_WRITE, OUTPUT_STREAM_WRITE_ZEROES, POLL_POLLABLE_BLOCK, POLL_POLLABLE_DISPOSE, POLL_POLLABLE_READY, POLL_POLL_LIST, SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST, SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST, SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST, SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST, SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE, SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE, SOCKET_TCP_ACCEPT, SOCKET_TCP_BIND_FINISH, SOCKET_TCP_BIND_START, SOCKET_TCP_CONNECT_FINISH, SOCKET_TCP_CONNECT_START, SOCKET_TCP_CREATE_HANDLE, SOCKET_TCP_DISPOSE, SOCKET_TCP_GET_LOCAL_ADDRESS, SOCKET_TCP_GET_REMOTE_ADDRESS, SOCKET_TCP_IS_LISTENING, SOCKET_TCP_LISTEN_FINISH, SOCKET_TCP_LISTEN_START, SOCKET_TCP_SET_KEEP_ALIVE, SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE, SOCKET_TCP_SHUTDOWN, SOCKET_TCP_SUBSCRIBE, SOCKET_UDP_BIND_FINISH, SOCKET_UDP_BIND_START, SOCKET_UDP_CREATE_HANDLE, SOCKET_UDP_DISPOSE, SOCKET_UDP_GET_LOCAL_ADDRESS, SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE, SOCKET_UDP_GET_REMOTE_ADDRESS, SOCKET_UDP_GET_SEND_BUFFER_SIZE, SOCKET_UDP_GET_UNICAST_HOP_LIMIT, SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE, SOCKET_UDP_SET_SEND_BUFFER_SIZE, SOCKET_UDP_SET_UNICAST_HOP_LIMIT, SOCKET_UDP_STREAM, SOCKET_UDP_SUBSCRIBE, SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE, SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND, SOCKET_OUTGOING_DATAGRAM_STREAM_SEND, SOCKET_DATAGRAM_STREAM_SUBSCRIBE, SOCKET_DATAGRAM_STREAM_DISPOSE, STDERR, STDIN, STDOUT, reverseMap, } from "./calls.js";
|
|
10
|
-
import { fileResourceFd, getFileResourceType, metadataHashFileResource, openFileResource, readFileResource, releaseFileResource, retainFileResource, setFileResourceSize, setFileResourceTimes, statFileResource, syncFileResource, syncFileResourceData, writeFileResource, } from "./worker-filesystem.js";
|
|
9
|
+
import { CALL_MASK, CALL_TYPE_MASK, CLOCKS_DURATION_SUBSCRIBE, CLOCKS_INSTANT_SUBSCRIBE, FILE, FILESYSTEM_DESCRIPTOR_ADVISE, FILESYSTEM_DESCRIPTOR_CLOSE, FILESYSTEM_DESCRIPTOR_GET_TYPE, FILESYSTEM_DESCRIPTOR_METADATA_HASH, FILESYSTEM_DESCRIPTOR_OPEN, FILESYSTEM_DESCRIPTOR_READ, FILESYSTEM_DESCRIPTOR_SET_SIZE, FILESYSTEM_DESCRIPTOR_SET_TIMES, FILESYSTEM_DESCRIPTOR_STAT, FILESYSTEM_DESCRIPTOR_SYNC, FILESYSTEM_DESCRIPTOR_SYNC_DATA, FILESYSTEM_DESCRIPTOR_WRITE, FUTURE_DISPOSE, FUTURE_SUBSCRIBE, FUTURE_TAKE_VALUE, HTTP, HTTP_CREATE_REQUEST, HTTP_OUTGOING_BODY_DISPOSE, HTTP_OUTPUT_STREAM_FINISH, HTTP_SERVER_CLEAR_OUTGOING_RESPONSE, HTTP_SERVER_SET_OUTGOING_RESPONSE, HTTP_SERVER_START, HTTP_SERVER_STOP, HTTP_SERVER_GET_ADDRESS, INPUT_STREAM_BLOCKING_READ, INPUT_STREAM_BLOCKING_SKIP, INPUT_STREAM_CREATE, INPUT_STREAM_DISPOSE, INPUT_STREAM_READ, INPUT_STREAM_SKIP, INPUT_STREAM_SUBSCRIBE, OUTPUT_STREAM_BLOCKING_FLUSH, OUTPUT_STREAM_BLOCKING_SPLICE, OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH, OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH, OUTPUT_STREAM_CHECK_WRITE, OUTPUT_STREAM_CREATE, OUTPUT_STREAM_DISPOSE, OUTPUT_STREAM_FLUSH, OUTPUT_STREAM_SPLICE, OUTPUT_STREAM_SUBSCRIBE, OUTPUT_STREAM_WRITE, OUTPUT_STREAM_WRITE_ZEROES, POLL_POLLABLE_BLOCK, POLL_POLLABLE_DISPOSE, POLL_POLLABLE_READY, POLL_POLL_LIST, SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST, SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST, SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST, SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST, SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE, SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE, SOCKET_TCP_ACCEPT, SOCKET_TCP_BIND_FINISH, SOCKET_TCP_BIND_START, SOCKET_TCP_CONNECT_FINISH, SOCKET_TCP_CONNECT_START, SOCKET_TCP_CREATE_HANDLE, SOCKET_TCP_DISPOSE, SOCKET_TCP_GET_LOCAL_ADDRESS, SOCKET_TCP_GET_REMOTE_ADDRESS, SOCKET_TCP_IS_LISTENING, SOCKET_TCP_LISTEN_FINISH, SOCKET_TCP_LISTEN_START, SOCKET_TCP_SET_KEEP_ALIVE, SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE, SOCKET_TCP_SHUTDOWN, SOCKET_TCP_SUBSCRIBE, SOCKET_UDP_BIND_FINISH, SOCKET_UDP_BIND_START, SOCKET_UDP_CREATE_HANDLE, SOCKET_UDP_DISPOSE, SOCKET_UDP_GET_LOCAL_ADDRESS, SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE, SOCKET_UDP_GET_REMOTE_ADDRESS, SOCKET_UDP_GET_SEND_BUFFER_SIZE, SOCKET_UDP_GET_UNICAST_HOP_LIMIT, SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE, SOCKET_UDP_SET_SEND_BUFFER_SIZE, SOCKET_UDP_SET_UNICAST_HOP_LIMIT, SOCKET_UDP_STREAM, SOCKET_UDP_SUBSCRIBE, SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE, SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND, SOCKET_OUTGOING_DATAGRAM_STREAM_SEND, SOCKET_DATAGRAM_STREAM_SUBSCRIBE, SOCKET_DATAGRAM_STREAM_DISPOSE, STDERR, STDIN, STDOUT, reverseMap, } from "./calls.js";
|
|
10
|
+
import { adviseFileResource, fileResourceFd, getFileResourceType, metadataHashFileResource, openFileResource, readFileResource, releaseFileResource, retainFileResource, setFileResourceSize, setFileResourceTimes, statFileResource, syncFileResource, syncFileResourceData, writeFileResource, } from "./worker-filesystem.js";
|
|
11
11
|
import { SOCKET_STATE_BIND, SOCKET_STATE_BOUND, SOCKET_STATE_CONNECT, SOCKET_STATE_CONNECTION, SOCKET_STATE_LISTEN, SOCKET_STATE_LISTENER, socketResolveAddress, getDefaultSendBufferSize, getDefaultReceiveBufferSize, } from "./worker-sockets.js";
|
|
12
12
|
import { createTcpSocket, socketTcpAccept, socketTcpBindStart, socketTcpConnectStart, socketTcpDispose, socketTcpFinish, socketTcpGetLocalAddress, socketTcpGetRemoteAddress, socketTcpListenStart, socketTcpSetKeepAlive, socketTcpSetListenBacklogSize, socketTcpShutdown, tcpSockets, } from "./worker-socket-tcp.js";
|
|
13
13
|
import { createUdpSocket, datagramStreams, socketDatagramStreamDispose, socketIncomingDatagramStreamReceive, socketOutgoingDatagramStreamCheckSend, socketOutgoingDatagramStreamSend, socketUdpBindFinish, socketUdpBindStart, socketUdpDispose, socketUdpGetLocalAddress, socketUdpGetReceiveBufferSize, socketUdpGetRemoteAddress, socketUdpGetSendBufferSize, socketUdpGetUnicastHopLimit, socketUdpSetReceiveBufferSize, socketUdpSetSendBufferSize, socketUdpSetUnicastHopLimit, socketUdpStream, udpSockets, } from "./worker-socket-udp.js";
|
|
@@ -370,6 +370,8 @@ function handle(call, id, payload) {
|
|
|
370
370
|
return openFileResource(payload.path, payload.flags);
|
|
371
371
|
case FILESYSTEM_DESCRIPTOR_CLOSE:
|
|
372
372
|
return releaseFileResource(id);
|
|
373
|
+
case FILESYSTEM_DESCRIPTOR_ADVISE:
|
|
374
|
+
return adviseFileResource(id, payload.offset, payload.length, payload.advice);
|
|
373
375
|
case FILESYSTEM_DESCRIPTOR_SYNC_DATA:
|
|
374
376
|
return syncFileResourceData(id);
|
|
375
377
|
case FILESYSTEM_DESCRIPTOR_GET_TYPE:
|
|
@@ -13,7 +13,7 @@ declare class Descriptor implements IDescriptor {
|
|
|
13
13
|
readViaStream(offset: any): any;
|
|
14
14
|
writeViaStream(offset: any): any;
|
|
15
15
|
appendViaStream(): any;
|
|
16
|
-
advise(
|
|
16
|
+
advise(offset: any, length: any, advice: any): void;
|
|
17
17
|
syncData(): void;
|
|
18
18
|
getFlags(): any;
|
|
19
19
|
getType(): any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { earlyDispose, inputStreamCreate, ioCall, outputStreamCreate, registerDispose, } from "../io/worker-io.js";
|
|
2
|
-
import { FILE, FILESYSTEM_DESCRIPTOR_CLOSE, FILESYSTEM_DESCRIPTOR_GET_TYPE, FILESYSTEM_DESCRIPTOR_METADATA_HASH, FILESYSTEM_DESCRIPTOR_OPEN, FILESYSTEM_DESCRIPTOR_READ, FILESYSTEM_DESCRIPTOR_SET_SIZE, FILESYSTEM_DESCRIPTOR_SET_TIMES, FILESYSTEM_DESCRIPTOR_STAT, FILESYSTEM_DESCRIPTOR_SYNC, FILESYSTEM_DESCRIPTOR_SYNC_DATA, FILESYSTEM_DESCRIPTOR_WRITE, INPUT_STREAM_CREATE, OUTPUT_STREAM_CREATE, } from "../io/calls.js";
|
|
2
|
+
import { FILE, FILESYSTEM_DESCRIPTOR_ADVISE, FILESYSTEM_DESCRIPTOR_CLOSE, FILESYSTEM_DESCRIPTOR_GET_TYPE, FILESYSTEM_DESCRIPTOR_METADATA_HASH, FILESYSTEM_DESCRIPTOR_OPEN, FILESYSTEM_DESCRIPTOR_READ, FILESYSTEM_DESCRIPTOR_SET_SIZE, FILESYSTEM_DESCRIPTOR_SET_TIMES, FILESYSTEM_DESCRIPTOR_STAT, FILESYSTEM_DESCRIPTOR_SYNC, FILESYSTEM_DESCRIPTOR_SYNC_DATA, FILESYSTEM_DESCRIPTOR_WRITE, INPUT_STREAM_CREATE, OUTPUT_STREAM_CREATE, } from "../io/calls.js";
|
|
3
3
|
import { constants, linkSync, lstatSync, lutimesSync, mkdirSync, opendirSync, readlinkSync, renameSync, rmdirSync, statSync, symlinkSync, unlinkSync, utimesSync, } from "node:fs";
|
|
4
4
|
import { platform } from "node:process";
|
|
5
5
|
const symbolDispose = Symbol.dispose || Symbol.for("dispose");
|
|
@@ -100,10 +100,20 @@ class Descriptor {
|
|
|
100
100
|
appendViaStream() {
|
|
101
101
|
return this.writeViaStream(this.stat().size);
|
|
102
102
|
}
|
|
103
|
-
advise(
|
|
103
|
+
advise(offset, length, advice) {
|
|
104
104
|
if (this.getType() === "directory") {
|
|
105
105
|
throw "bad-descriptor";
|
|
106
106
|
}
|
|
107
|
+
try {
|
|
108
|
+
ioCall(FILESYSTEM_DESCRIPTOR_ADVISE, this.#fileResourceId, {
|
|
109
|
+
offset,
|
|
110
|
+
length,
|
|
111
|
+
advice,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
throw convertFsError(e);
|
|
116
|
+
}
|
|
107
117
|
}
|
|
108
118
|
syncData() {
|
|
109
119
|
if (this.#hostPreopen) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bytecodealliance/preview2-shim",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "WASI Preview2 shim for JS environments",
|
|
5
5
|
"homepage": "https://github.com/bytecodealliance/jco#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
"types": "./types/interfaces/*.d.ts"
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@bytecodealliance/jco-node-fs": "0.2.0"
|
|
61
|
+
},
|
|
59
62
|
"devDependencies": {
|
|
60
63
|
"@bytecodealliance/componentize-js": "0.22.0",
|
|
61
64
|
"@bytecodealliance/jco": "1.25.2",
|