@velarscript/node 0.10.1
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/LICENSE +201 -0
- package/README.md +148 -0
- package/dist/compiler.d.ts +12 -0
- package/dist/compiler.d.ts.map +1 -0
- package/dist/compiler.js +954 -0
- package/dist/compiler.js.map +1 -0
- package/dist/environment-runtime.d.ts +2 -0
- package/dist/environment-runtime.d.ts.map +1 -0
- package/dist/environment-runtime.js +53 -0
- package/dist/environment-runtime.js.map +1 -0
- package/dist/filesystem-runtime.d.ts +2 -0
- package/dist/filesystem-runtime.d.ts.map +1 -0
- package/dist/filesystem-runtime.js +329 -0
- package/dist/filesystem-runtime.js.map +1 -0
- package/dist/host-runtime.d.ts +2 -0
- package/dist/host-runtime.d.ts.map +1 -0
- package/dist/host-runtime.js +149 -0
- package/dist/host-runtime.js.map +1 -0
- package/dist/http-runtime.d.ts +2 -0
- package/dist/http-runtime.d.ts.map +1 -0
- package/dist/http-runtime.js +612 -0
- package/dist/http-runtime.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/node-host-runtime.d.ts +2 -0
- package/dist/node-host-runtime.d.ts.map +1 -0
- package/dist/node-host-runtime.js +314 -0
- package/dist/node-host-runtime.js.map +1 -0
- package/dist/node-host-worker-runtime.d.ts +2 -0
- package/dist/node-host-worker-runtime.d.ts.map +1 -0
- package/dist/node-host-worker-runtime.js +1144 -0
- package/dist/node-host-worker-runtime.js.map +1 -0
- package/dist/process-runtime.d.ts +2 -0
- package/dist/process-runtime.d.ts.map +1 -0
- package/dist/process-runtime.js +167 -0
- package/dist/process-runtime.js.map +1 -0
- package/dist/process-worker-runtime.d.ts +2 -0
- package/dist/process-worker-runtime.d.ts.map +1 -0
- package/dist/process-worker-runtime.js +473 -0
- package/dist/process-worker-runtime.js.map +1 -0
- package/dist/serve-runtime.d.ts +2 -0
- package/dist/serve-runtime.d.ts.map +1 -0
- package/dist/serve-runtime.js +463 -0
- package/dist/serve-runtime.js.map +1 -0
- package/dist/sqlite-runtime.d.ts +3 -0
- package/dist/sqlite-runtime.d.ts.map +1 -0
- package/dist/sqlite-runtime.js +92 -0
- package/dist/sqlite-runtime.js.map +1 -0
- package/dist/terminal-runtime.d.ts +2 -0
- package/dist/terminal-runtime.d.ts.map +1 -0
- package/dist/terminal-runtime.js +290 -0
- package/dist/terminal-runtime.js.map +1 -0
- package/dist/terminal-worker-runtime.d.ts +2 -0
- package/dist/terminal-worker-runtime.d.ts.map +1 -0
- package/dist/terminal-worker-runtime.js +311 -0
- package/dist/terminal-worker-runtime.js.map +1 -0
- package/dist/websocket-runtime.d.ts +2 -0
- package/dist/websocket-runtime.d.ts.map +1 -0
- package/dist/websocket-runtime.js +46 -0
- package/dist/websocket-runtime.js.map +1 -0
- package/dist/worker-runtime.d.ts +2 -0
- package/dist/worker-runtime.d.ts.map +1 -0
- package/dist/worker-runtime.js +160 -0
- package/dist/worker-runtime.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// Application-facing proxy for the isolated terminal host. It captures all
|
|
2
|
+
// validation, MessagePort and Worker operations before application code runs;
|
|
3
|
+
// stdin ownership, decoding, and fd writes live in terminal-worker-runtime.ts.
|
|
4
|
+
export const VELAR_NODE_TERMINAL_RUNTIME = String.raw `
|
|
5
|
+
import { EventEmitter as __VelarTerminalEventEmitter } from "node:events";
|
|
6
|
+
import { MessageChannel as __VelarTerminalMessageChannel, MessagePort as __VelarTerminalMessagePort, Worker as __VelarTerminalWorker } from "node:worker_threads";
|
|
7
|
+
|
|
8
|
+
const __velarTerminalNativeArray = globalThis.Array;
|
|
9
|
+
const __velarTerminalNativeError = globalThis.Error;
|
|
10
|
+
const __velarTerminalNativeNumber = globalThis.Number;
|
|
11
|
+
const __velarTerminalNativeObject = globalThis.Object;
|
|
12
|
+
const __velarTerminalNativePromise = globalThis.Promise;
|
|
13
|
+
const __velarTerminalNativeRangeError = globalThis.RangeError;
|
|
14
|
+
const __velarTerminalNativeReflect = globalThis.Reflect;
|
|
15
|
+
const __velarTerminalNativeString = globalThis.String;
|
|
16
|
+
const __velarTerminalNativeTypeError = globalThis.TypeError;
|
|
17
|
+
const __velarTerminalOwnDescriptor = __velarTerminalNativeObject.getOwnPropertyDescriptor;
|
|
18
|
+
const __velarTerminalApply = __velarTerminalNativeReflect.apply;
|
|
19
|
+
function __velarTerminalDataOperation(target, name) {
|
|
20
|
+
const descriptor = __velarTerminalOwnDescriptor(target, name);
|
|
21
|
+
if (!descriptor || !("value" in descriptor) || typeof descriptor.value !== "function") {
|
|
22
|
+
throw new __velarTerminalNativeError("VelarScript terminal host operation '" + name + "' is unavailable");
|
|
23
|
+
}
|
|
24
|
+
return descriptor.value;
|
|
25
|
+
}
|
|
26
|
+
const __velarTerminalArrayPush = __velarTerminalDataOperation(__velarTerminalNativeArray.prototype, "push");
|
|
27
|
+
const __velarTerminalArraySlice = __velarTerminalDataOperation(__velarTerminalNativeArray.prototype, "slice");
|
|
28
|
+
const __velarTerminalArrayIsArray = __velarTerminalDataOperation(__velarTerminalNativeArray, "isArray");
|
|
29
|
+
const __velarTerminalNumberIsSafeInteger = __velarTerminalDataOperation(__velarTerminalNativeNumber, "isSafeInteger");
|
|
30
|
+
const __velarTerminalObjectCreate = __velarTerminalDataOperation(__velarTerminalNativeObject, "create");
|
|
31
|
+
const __velarTerminalObjectFreeze = __velarTerminalDataOperation(__velarTerminalNativeObject, "freeze");
|
|
32
|
+
const __velarTerminalOwnKeys = __velarTerminalDataOperation(__velarTerminalNativeReflect, "ownKeys");
|
|
33
|
+
const __velarTerminalPromiseThen = __velarTerminalDataOperation(__velarTerminalNativePromise.prototype, "then");
|
|
34
|
+
const __velarTerminalStringIncludes = __velarTerminalDataOperation(__velarTerminalNativeString.prototype, "includes");
|
|
35
|
+
const __velarTerminalMessagePortPost = __velarTerminalDataOperation(__VelarTerminalMessagePort.prototype, "postMessage");
|
|
36
|
+
const __velarTerminalMessagePortStart = __velarTerminalDataOperation(__VelarTerminalMessagePort.prototype, "start");
|
|
37
|
+
const __velarTerminalMessagePortRef = __velarTerminalDataOperation(__VelarTerminalMessagePort.prototype, "ref");
|
|
38
|
+
const __velarTerminalMessagePortUnref = __velarTerminalDataOperation(__VelarTerminalMessagePort.prototype, "unref");
|
|
39
|
+
const __velarTerminalMessagePortClose = __velarTerminalDataOperation(__VelarTerminalMessagePort.prototype, "close");
|
|
40
|
+
const __velarTerminalWorkerUnref = __velarTerminalDataOperation(__VelarTerminalWorker.prototype, "unref");
|
|
41
|
+
const __velarTerminalWorkerTerminate = __velarTerminalDataOperation(__VelarTerminalWorker.prototype, "terminate");
|
|
42
|
+
const __velarTerminalEventOn = __velarTerminalDataOperation(__VelarTerminalEventEmitter.prototype, "on");
|
|
43
|
+
const __velarTerminalMessageData = __velarTerminalOwnDescriptor(globalThis.MessageEvent.prototype, "data")?.get;
|
|
44
|
+
if (typeof __velarTerminalMessageData !== "function") throw new __velarTerminalNativeError("Node terminal MessageEvent data operation is unavailable");
|
|
45
|
+
const __velarTerminalSetTimeout = globalThis.setTimeout;
|
|
46
|
+
const __velarTerminalClearTimeout = globalThis.clearTimeout;
|
|
47
|
+
const __velarTerminalProcess = globalThis.process;
|
|
48
|
+
const __velarTerminalMaxArgumentCount = 256;
|
|
49
|
+
const __velarTerminalMaxTextBytes = 1024 * 1024;
|
|
50
|
+
const __velarTerminalMaxPending = 256;
|
|
51
|
+
const __velarTerminalPending = __velarTerminalCall(__velarTerminalObjectCreate, __velarTerminalNativeObject, [null]);
|
|
52
|
+
let __velarTerminalPendingCount = 0;
|
|
53
|
+
let __velarTerminalNextRequest = 1;
|
|
54
|
+
let __velarTerminalClosed = false;
|
|
55
|
+
let __velarTerminalClosing = false;
|
|
56
|
+
let __velarTerminalInteractive = false;
|
|
57
|
+
let __velarTerminalReady = false;
|
|
58
|
+
let __velarTerminalFailure = null;
|
|
59
|
+
let __velarTerminalExpectedWorkerExit = false;
|
|
60
|
+
let __velarTerminalReadyResolve;
|
|
61
|
+
let __velarTerminalReadyReject;
|
|
62
|
+
|
|
63
|
+
function __velarTerminalCall(operation, receiver, arguments_) {
|
|
64
|
+
return __velarTerminalApply(operation, receiver, arguments_);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function __velarTerminalPush(values, value) {
|
|
68
|
+
__velarTerminalCall(__velarTerminalArrayPush, values, [value]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function __velarTerminalIsSafeInteger(value) {
|
|
72
|
+
return __velarTerminalCall(__velarTerminalNumberIsSafeInteger, __velarTerminalNativeNumber, [value]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function __velarTerminalBoundedText(value, operation) {
|
|
76
|
+
if (typeof value !== "string") throw new __velarTerminalNativeTypeError(operation + " requires text");
|
|
77
|
+
if (__velarUtf8ByteLength(value) > __velarTerminalMaxTextBytes) {
|
|
78
|
+
throw new __velarTerminalNativeRangeError(operation + " text exceeds its 1 MiB boundary");
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function __velarTerminalProgramArguments() {
|
|
84
|
+
const source = __velarTerminalProcess.argv;
|
|
85
|
+
const values = [];
|
|
86
|
+
if (source.length - 2 > __velarTerminalMaxArgumentCount) {
|
|
87
|
+
throw new __velarTerminalNativeRangeError("Terminal args cannot exceed 256 items");
|
|
88
|
+
}
|
|
89
|
+
let bytes = 0;
|
|
90
|
+
for (let index = 2; index < source.length; index += 1) {
|
|
91
|
+
const value = source[index];
|
|
92
|
+
if (typeof value !== "string") throw new __velarTerminalNativeTypeError("Terminal args must be text");
|
|
93
|
+
bytes += __velarUtf8ByteLength(value);
|
|
94
|
+
if (__velarTerminalCall(__velarTerminalStringIncludes, value, ["\0"]) || bytes > __velarTerminalMaxTextBytes) {
|
|
95
|
+
throw new __velarTerminalNativeRangeError("Terminal args are outside the supported boundary");
|
|
96
|
+
}
|
|
97
|
+
__velarTerminalPush(values, value);
|
|
98
|
+
}
|
|
99
|
+
return __velarTerminalCall(__velarTerminalObjectFreeze, __velarTerminalNativeObject, [values]);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function __velarTerminalRecord(value, name) {
|
|
103
|
+
if (!value || typeof value !== "object" || __velarTerminalCall(__velarTerminalArrayIsArray, __velarTerminalNativeArray, [value])) {
|
|
104
|
+
throw new __velarTerminalNativeTypeError(name + " must be a record");
|
|
105
|
+
}
|
|
106
|
+
const output = __velarTerminalCall(__velarTerminalObjectCreate, __velarTerminalNativeObject, [null]);
|
|
107
|
+
const keys = __velarTerminalCall(__velarTerminalOwnKeys, __velarTerminalNativeReflect, [value]);
|
|
108
|
+
for (let index = 0; index < keys.length; index += 1) {
|
|
109
|
+
const key = keys[index];
|
|
110
|
+
if (typeof key !== "string") throw new __velarTerminalNativeTypeError(name + " fields must use string names");
|
|
111
|
+
const descriptor = __velarTerminalOwnDescriptor(value, key);
|
|
112
|
+
if (!descriptor?.enumerable || !("value" in descriptor)) throw new __velarTerminalNativeTypeError(name + " fields must be enumerable data values");
|
|
113
|
+
output[key] = descriptor.value;
|
|
114
|
+
}
|
|
115
|
+
return output;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function __velarTerminalError(value) {
|
|
119
|
+
value = __velarTerminalRecord(value, "Node terminal host error");
|
|
120
|
+
if (typeof value.message !== "string" || value.message.length === 0 || value.message.length > 65536) {
|
|
121
|
+
throw new __velarTerminalNativeTypeError("Node terminal host returned an invalid error");
|
|
122
|
+
}
|
|
123
|
+
if (value.name === "RangeError") return new __velarTerminalNativeRangeError(value.message);
|
|
124
|
+
if (value.name === "TypeError") return new __velarTerminalNativeTypeError(value.message);
|
|
125
|
+
if (value.name === "Error") return new __velarTerminalNativeError(value.message);
|
|
126
|
+
throw new __velarTerminalNativeTypeError("Node terminal host returned an invalid error");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function __velarTerminalUpdateReference() {
|
|
130
|
+
const operation = __velarTerminalPendingCount > 0 || __velarTerminalClosing
|
|
131
|
+
? __velarTerminalMessagePortRef
|
|
132
|
+
: __velarTerminalMessagePortUnref;
|
|
133
|
+
__velarTerminalCall(operation, __velarTerminalPort, []);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function __velarTerminalFail(error) {
|
|
137
|
+
if (__velarTerminalFailure) return;
|
|
138
|
+
const failure = error instanceof __velarTerminalNativeError
|
|
139
|
+
? error
|
|
140
|
+
: new __velarTerminalNativeError("Node terminal worker failed");
|
|
141
|
+
__velarTerminalFailure = failure;
|
|
142
|
+
if (!__velarTerminalReady) __velarTerminalReadyReject(failure);
|
|
143
|
+
__velarTerminalClosed = true;
|
|
144
|
+
__velarTerminalClosing = false;
|
|
145
|
+
const keys = __velarTerminalCall(__velarTerminalOwnKeys, __velarTerminalNativeReflect, [__velarTerminalPending]);
|
|
146
|
+
for (let index = 0; index < keys.length; index += 1) {
|
|
147
|
+
const descriptor = __velarTerminalOwnDescriptor(__velarTerminalPending, keys[index]);
|
|
148
|
+
if (descriptor && "value" in descriptor) descriptor.value.reject(failure);
|
|
149
|
+
delete __velarTerminalPending[keys[index]];
|
|
150
|
+
}
|
|
151
|
+
__velarTerminalPendingCount = 0;
|
|
152
|
+
__velarTerminalUpdateReference();
|
|
153
|
+
__velarTerminalCall(__velarTerminalMessagePortClose, __velarTerminalPort, []);
|
|
154
|
+
__velarTerminalExpectedWorkerExit = true;
|
|
155
|
+
const terminated = __velarTerminalCall(__velarTerminalWorkerTerminate, __velarTerminalWorker, []);
|
|
156
|
+
__velarTerminalCall(__velarTerminalPromiseThen, terminated, [() => null, () => null]);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function __velarTerminalMessage(value) {
|
|
160
|
+
const message = __velarTerminalRecord(value, "Node terminal host message");
|
|
161
|
+
if (message.kind === "ready") {
|
|
162
|
+
if (__velarTerminalReady || typeof message.interactive !== "boolean") {
|
|
163
|
+
throw new __velarTerminalNativeTypeError("Node terminal worker returned invalid readiness");
|
|
164
|
+
}
|
|
165
|
+
__velarTerminalInteractive = message.interactive;
|
|
166
|
+
__velarTerminalReady = true;
|
|
167
|
+
__velarTerminalReadyResolve(null);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (message.kind === "closed") {
|
|
171
|
+
if (!__velarTerminalClosing || message.error !== null) {
|
|
172
|
+
throw message.error === null
|
|
173
|
+
? new __velarTerminalNativeError("Node terminal worker returned unexpected closure")
|
|
174
|
+
: __velarTerminalError(message.error);
|
|
175
|
+
}
|
|
176
|
+
__velarTerminalClosing = false;
|
|
177
|
+
__velarTerminalUpdateReference();
|
|
178
|
+
__velarTerminalCall(__velarTerminalMessagePortClose, __velarTerminalPort, []);
|
|
179
|
+
__velarTerminalExpectedWorkerExit = true;
|
|
180
|
+
const terminated = __velarTerminalCall(__velarTerminalWorkerTerminate, __velarTerminalWorker, []);
|
|
181
|
+
__velarTerminalCall(__velarTerminalPromiseThen, terminated, [() => null, () => null]);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (message.kind !== "response" || !__velarTerminalIsSafeInteger(message.id) || message.id < 1 || typeof message.ok !== "boolean") {
|
|
185
|
+
throw new __velarTerminalNativeTypeError("Node terminal worker returned an invalid response");
|
|
186
|
+
}
|
|
187
|
+
const descriptor = __velarTerminalOwnDescriptor(__velarTerminalPending, __velarTerminalNativeString(message.id));
|
|
188
|
+
if (!descriptor || !("value" in descriptor)) throw new __velarTerminalNativeError("Node terminal worker returned an unknown response");
|
|
189
|
+
const pending = descriptor.value;
|
|
190
|
+
const responseError = message.ok ? null : __velarTerminalError(message.error);
|
|
191
|
+
if (pending.operation === "readLine") {
|
|
192
|
+
if (message.ok && message.value !== null && typeof message.value !== "string") throw new __velarTerminalNativeTypeError("Node terminal worker returned invalid input");
|
|
193
|
+
if (message.ok && typeof message.value === "string") __velarTerminalBoundedText(message.value, "Terminal input");
|
|
194
|
+
} else if (message.ok && message.value !== null) {
|
|
195
|
+
throw new __velarTerminalNativeTypeError("Node terminal worker returned invalid write completion");
|
|
196
|
+
}
|
|
197
|
+
delete __velarTerminalPending[message.id];
|
|
198
|
+
__velarTerminalPendingCount -= 1;
|
|
199
|
+
__velarTerminalUpdateReference();
|
|
200
|
+
if (responseError) pending.reject(responseError);
|
|
201
|
+
else pending.resolve(message.value);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const __velarTerminalArguments = __velarTerminalProgramArguments();
|
|
205
|
+
const __velarTerminalReadyPromise = new __velarTerminalNativePromise((resolve, reject) => {
|
|
206
|
+
__velarTerminalReadyResolve = resolve;
|
|
207
|
+
__velarTerminalReadyReject = reject;
|
|
208
|
+
});
|
|
209
|
+
const __velarTerminalChannel = new __VelarTerminalMessageChannel();
|
|
210
|
+
const __velarTerminalPort = __velarTerminalChannel.port1;
|
|
211
|
+
__velarTerminalPort.onmessage = event => {
|
|
212
|
+
try { __velarTerminalMessage(__velarTerminalCall(__velarTerminalMessageData, event, [])); }
|
|
213
|
+
catch (error) { __velarTerminalFail(error); }
|
|
214
|
+
};
|
|
215
|
+
__velarTerminalPort.onmessageerror = () => __velarTerminalFail(new __velarTerminalNativeError("Node terminal worker returned an unreadable message"));
|
|
216
|
+
__velarTerminalCall(__velarTerminalMessagePortStart, __velarTerminalPort, []);
|
|
217
|
+
const __velarTerminalWorker = new __VelarTerminalWorker(WORKER_SOURCE, {
|
|
218
|
+
eval: true,
|
|
219
|
+
workerData: {port: __velarTerminalChannel.port2},
|
|
220
|
+
transferList: [__velarTerminalChannel.port2],
|
|
221
|
+
});
|
|
222
|
+
__velarTerminalCall(__velarTerminalEventOn, __velarTerminalWorker, ["error", error => __velarTerminalFail(error)]);
|
|
223
|
+
__velarTerminalCall(__velarTerminalEventOn, __velarTerminalWorker, ["exit", code => {
|
|
224
|
+
if (!__velarTerminalExpectedWorkerExit) {
|
|
225
|
+
__velarTerminalFail(new __velarTerminalNativeError("Node terminal worker exited unexpectedly with code " + code));
|
|
226
|
+
}
|
|
227
|
+
}]);
|
|
228
|
+
const __velarTerminalReadyTimer = __velarTerminalSetTimeout(
|
|
229
|
+
() => __velarTerminalReadyReject(new __velarTerminalNativeError("Node terminal worker did not become ready")),
|
|
230
|
+
10000,
|
|
231
|
+
);
|
|
232
|
+
try { await __velarTerminalReadyPromise; }
|
|
233
|
+
finally { __velarTerminalClearTimeout(__velarTerminalReadyTimer); }
|
|
234
|
+
__velarTerminalCall(__velarTerminalWorkerUnref, __velarTerminalWorker, []);
|
|
235
|
+
__velarTerminalCall(__velarTerminalMessagePortUnref, __velarTerminalPort, []);
|
|
236
|
+
|
|
237
|
+
function __velarTerminalInvoke(operation, value) {
|
|
238
|
+
if (__velarTerminalClosed) {
|
|
239
|
+
if (__velarTerminalFailure) return new __velarTerminalNativePromise((_resolve, reject) => reject(__velarTerminalFailure));
|
|
240
|
+
if (operation === "readLine") return new __velarTerminalNativePromise(resolve => resolve(null));
|
|
241
|
+
return new __velarTerminalNativePromise((_resolve, reject) => reject(new __velarTerminalNativeError("Terminal is closed")));
|
|
242
|
+
}
|
|
243
|
+
if (__velarTerminalPendingCount >= __velarTerminalMaxPending) {
|
|
244
|
+
return new __velarTerminalNativePromise((_resolve, reject) => reject(new __velarTerminalNativeRangeError("Terminal cannot have more than 256 pending operations")));
|
|
245
|
+
}
|
|
246
|
+
const id = __velarTerminalNextRequest;
|
|
247
|
+
__velarTerminalNextRequest += 1;
|
|
248
|
+
const result = new __velarTerminalNativePromise((resolve, reject) => {
|
|
249
|
+
__velarTerminalPending[id] = {operation, resolve, reject};
|
|
250
|
+
});
|
|
251
|
+
__velarTerminalPendingCount += 1;
|
|
252
|
+
__velarTerminalUpdateReference();
|
|
253
|
+
try {
|
|
254
|
+
__velarTerminalCall(__velarTerminalMessagePortPost, __velarTerminalPort, [{kind: "request", id, operation, value}]);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
delete __velarTerminalPending[id];
|
|
257
|
+
__velarTerminalPendingCount -= 1;
|
|
258
|
+
__velarTerminalUpdateReference();
|
|
259
|
+
return new __velarTerminalNativePromise((_resolve, reject) => reject(error));
|
|
260
|
+
}
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export const terminal = __velarTerminalCall(__velarTerminalObjectFreeze, __velarTerminalNativeObject, [{
|
|
265
|
+
args() { return __velarTerminalCall(__velarTerminalArraySlice, __velarTerminalArguments, []); },
|
|
266
|
+
isInteractive() { return __velarTerminalInteractive; },
|
|
267
|
+
readLine(prompt = "") { return __velarTerminalInvoke("readLine", __velarTerminalBoundedText(prompt, "Terminal prompt")); },
|
|
268
|
+
write(text) { return __velarTerminalInvoke("write", __velarTerminalBoundedText(text, "Terminal write")); },
|
|
269
|
+
writeError(text) { return __velarTerminalInvoke("writeError", __velarTerminalBoundedText(text, "Terminal error write")); },
|
|
270
|
+
close() {
|
|
271
|
+
if (__velarTerminalClosed) return null;
|
|
272
|
+
__velarTerminalClosed = true;
|
|
273
|
+
const keys = __velarTerminalCall(__velarTerminalOwnKeys, __velarTerminalNativeReflect, [__velarTerminalPending]);
|
|
274
|
+
for (let index = 0; index < keys.length; index += 1) {
|
|
275
|
+
const descriptor = __velarTerminalOwnDescriptor(__velarTerminalPending, keys[index]);
|
|
276
|
+
if (descriptor && "value" in descriptor) {
|
|
277
|
+
if (descriptor.value.operation === "readLine") descriptor.value.resolve(null);
|
|
278
|
+
else descriptor.value.reject(new __velarTerminalNativeError("Terminal closed before the write completed"));
|
|
279
|
+
}
|
|
280
|
+
delete __velarTerminalPending[keys[index]];
|
|
281
|
+
}
|
|
282
|
+
__velarTerminalPendingCount = 0;
|
|
283
|
+
__velarTerminalClosing = true;
|
|
284
|
+
__velarTerminalUpdateReference();
|
|
285
|
+
__velarTerminalCall(__velarTerminalMessagePortPost, __velarTerminalPort, [{kind: "close"}]);
|
|
286
|
+
return null;
|
|
287
|
+
},
|
|
288
|
+
}]);
|
|
289
|
+
`.trimStart();
|
|
290
|
+
//# sourceMappingURL=terminal-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-runtime.js","sourceRoot":"","sources":["../src/terminal-runtime.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6RpD,CAAC,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-worker-runtime.d.ts","sourceRoot":"","sources":["../src/terminal-worker-runtime.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,iCAAiC,QA0RjC,CAAC"}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
const VELAR_NODE_TERMINAL_INPUT_SOURCE = String.raw `
|
|
2
|
+
process.stdin.pause();
|
|
3
|
+
process.on("error", () => process.exit(0));
|
|
4
|
+
const send = value => {
|
|
5
|
+
if (process.connected && typeof process.send === "function") {
|
|
6
|
+
process.send(value, error => { if (error) process.exit(0); });
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
process.stdin.on("data", data => send({kind: "input-data", data}));
|
|
10
|
+
process.stdin.on("end", () => { send({kind: "input-end"}); process.disconnect(); });
|
|
11
|
+
process.stdin.on("error", () => { send({kind: "input-error"}); process.disconnect(); });
|
|
12
|
+
process.on("message", value => {
|
|
13
|
+
if (!value || typeof value !== "object") return;
|
|
14
|
+
if (value.kind === "input-state" && typeof value.active === "boolean") {
|
|
15
|
+
if (value.active) process.stdin.resume();
|
|
16
|
+
else process.stdin.pause();
|
|
17
|
+
} else if (value.kind === "close") {
|
|
18
|
+
process.stdin.pause();
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
process.on("disconnect", () => process.exit(0));
|
|
23
|
+
send({kind: "ready"});
|
|
24
|
+
`.trimStart();
|
|
25
|
+
// Isolated terminal host. The Worker never loads application code or packages;
|
|
26
|
+
// an on-demand child owns the inherited stdin handle so a blocking pipe read is
|
|
27
|
+
// cancellable without exposing application-Realm stream prototypes.
|
|
28
|
+
export const VELAR_NODE_TERMINAL_WORKER_SOURCE = String.raw `
|
|
29
|
+
import { Buffer } from "node:buffer";
|
|
30
|
+
import { spawn } from "node:child_process";
|
|
31
|
+
import { write } from "node:fs";
|
|
32
|
+
import { StringDecoder } from "node:string_decoder";
|
|
33
|
+
import { isatty } from "node:tty";
|
|
34
|
+
import { workerData } from "node:worker_threads";
|
|
35
|
+
|
|
36
|
+
const port = workerData.port;
|
|
37
|
+
const inputHostSource = ${JSON.stringify(VELAR_NODE_TERMINAL_INPUT_SOURCE)};
|
|
38
|
+
const maxTextBytes = 1024 * 1024;
|
|
39
|
+
const maxQueuedLines = 256;
|
|
40
|
+
const decoder = new StringDecoder("utf8");
|
|
41
|
+
const waiting = [];
|
|
42
|
+
const queued = [];
|
|
43
|
+
let queuedBytes = 0;
|
|
44
|
+
let queueOverflowed = false;
|
|
45
|
+
let closed = false;
|
|
46
|
+
let inputHost = null;
|
|
47
|
+
let inputHostReady = false;
|
|
48
|
+
let inputHostEnded = false;
|
|
49
|
+
let inputHostActive = false;
|
|
50
|
+
let failure = null;
|
|
51
|
+
let lineParts = [];
|
|
52
|
+
let lineBytes = 0;
|
|
53
|
+
let lineOverflowed = false;
|
|
54
|
+
let swallowLineFeed = false;
|
|
55
|
+
let operationTail = Promise.resolve();
|
|
56
|
+
|
|
57
|
+
function errorRecord(error) {
|
|
58
|
+
const name = error instanceof RangeError ? "RangeError" : error instanceof TypeError ? "TypeError" : "Error";
|
|
59
|
+
const message = error instanceof Error && typeof error.message === "string" && error.message.length > 0
|
|
60
|
+
? error.message.slice(0, 65536)
|
|
61
|
+
: "Node terminal host failed";
|
|
62
|
+
return {name, message};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function respond(id, ok, value, error = null) {
|
|
66
|
+
port.postMessage({kind: "response", id, ok, value, error});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function referenceInputHost(active) {
|
|
70
|
+
if (inputHost === null) return;
|
|
71
|
+
if (active) {
|
|
72
|
+
inputHost.ref();
|
|
73
|
+
inputHost.channel?.ref();
|
|
74
|
+
} else {
|
|
75
|
+
inputHost.channel?.unref();
|
|
76
|
+
inputHost.unref();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function ensureInputHost() {
|
|
81
|
+
if (inputHost !== null || closed) return inputHost;
|
|
82
|
+
inputHost = spawn(process.execPath, ["--input-type=module", "--eval", inputHostSource], {
|
|
83
|
+
stdio: ["inherit", "ignore", "inherit", "ipc"],
|
|
84
|
+
serialization: "advanced",
|
|
85
|
+
windowsHide: true,
|
|
86
|
+
});
|
|
87
|
+
inputHost.on("message", value => {
|
|
88
|
+
try {
|
|
89
|
+
if (!value || typeof value !== "object") throw new TypeError("Node terminal input host returned an invalid message");
|
|
90
|
+
if (value.kind === "ready") {
|
|
91
|
+
inputHostReady = true;
|
|
92
|
+
inputHost.send({kind: "input-state", active: inputHostActive});
|
|
93
|
+
} else if (value.kind === "input-data") acceptForwardedData(value);
|
|
94
|
+
else if (value.kind === "input-end") { inputHostEnded = true; endForwardedInput(); }
|
|
95
|
+
else if (value.kind === "input-error") { inputHostEnded = true; endForwardedInput(new Error("Terminal input failed")); }
|
|
96
|
+
else throw new TypeError("Node terminal input host returned an invalid message");
|
|
97
|
+
} catch (error) { settleInput(error); }
|
|
98
|
+
});
|
|
99
|
+
inputHost.on("error", error => settleInput(error));
|
|
100
|
+
inputHost.on("exit", code => {
|
|
101
|
+
if (!closed && !inputHostEnded) settleInput(new Error("Node terminal input host exited unexpectedly with code " + code));
|
|
102
|
+
});
|
|
103
|
+
referenceInputHost(false);
|
|
104
|
+
return inputHost;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function requestForwardedInput(active) {
|
|
108
|
+
if (closed || inputHostActive === active) return;
|
|
109
|
+
inputHostActive = active;
|
|
110
|
+
const host = active ? ensureInputHost() : inputHost;
|
|
111
|
+
if (host === null) return;
|
|
112
|
+
referenceInputHost(active);
|
|
113
|
+
if (inputHostReady) host.send({kind: "input-state", active});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function requestOf(value) {
|
|
117
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Node terminal host received an invalid request");
|
|
118
|
+
const keys = Object.keys(value);
|
|
119
|
+
if (keys.length !== 4 || !keys.includes("kind") || !keys.includes("id") || !keys.includes("operation") || !keys.includes("value")) {
|
|
120
|
+
throw new TypeError("Node terminal host received an invalid request");
|
|
121
|
+
}
|
|
122
|
+
if (value.kind !== "request" || !Number.isSafeInteger(value.id) || value.id < 1
|
|
123
|
+
|| value.operation !== "readLine" && value.operation !== "write" && value.operation !== "writeError") {
|
|
124
|
+
throw new TypeError("Node terminal host received an invalid request");
|
|
125
|
+
}
|
|
126
|
+
if (typeof value.value !== "string" || Buffer.byteLength(value.value, "utf8") > maxTextBytes) {
|
|
127
|
+
throw new RangeError("Node terminal request text exceeds its 1 MiB boundary");
|
|
128
|
+
}
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function writeText(fd, text) {
|
|
133
|
+
const data = Buffer.from(text, "utf8");
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
let offset = 0;
|
|
136
|
+
const next = () => {
|
|
137
|
+
if (offset >= data.length) { resolve(null); return; }
|
|
138
|
+
write(fd, data, offset, data.length - offset, null, (error, written) => {
|
|
139
|
+
if (error) { reject(error); return; }
|
|
140
|
+
if (!Number.isSafeInteger(written) || written < 1) {
|
|
141
|
+
reject(new Error("Node terminal host made no write progress"));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
offset += written;
|
|
145
|
+
next();
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
next();
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function deliver(entry) {
|
|
153
|
+
const request = waiting.shift();
|
|
154
|
+
if (request) {
|
|
155
|
+
if (entry.error) respond(request.id, false, null, errorRecord(entry.error));
|
|
156
|
+
else respond(request.id, true, entry.value);
|
|
157
|
+
if (waiting.length === 0) requestForwardedInput(false);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (queueOverflowed) return;
|
|
161
|
+
if (queued.length >= maxQueuedLines || queuedBytes + entry.bytes > maxTextBytes) {
|
|
162
|
+
queueOverflowed = true;
|
|
163
|
+
queued.push({
|
|
164
|
+
value: null,
|
|
165
|
+
error: new RangeError("Terminal queued input exceeds its 1 MiB boundary"),
|
|
166
|
+
bytes: 0,
|
|
167
|
+
queueOverflow: true,
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
queued.push(entry);
|
|
172
|
+
queuedBytes += entry.bytes;
|
|
173
|
+
requestForwardedInput(false);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function appendLine(text, start, end) {
|
|
177
|
+
if (start >= end || lineOverflowed) return;
|
|
178
|
+
const fragment = text.slice(start, end);
|
|
179
|
+
const bytes = Buffer.byteLength(fragment, "utf8");
|
|
180
|
+
if (lineBytes + bytes > maxTextBytes) {
|
|
181
|
+
lineParts = [];
|
|
182
|
+
lineBytes = 0;
|
|
183
|
+
lineOverflowed = true;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
lineParts.push(fragment);
|
|
187
|
+
lineBytes += bytes;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function completeLine() {
|
|
191
|
+
if (lineOverflowed) {
|
|
192
|
+
deliver({
|
|
193
|
+
value: null,
|
|
194
|
+
error: new RangeError("Terminal input text exceeds its 1 MiB boundary"),
|
|
195
|
+
bytes: 0,
|
|
196
|
+
queueOverflow: false,
|
|
197
|
+
});
|
|
198
|
+
} else {
|
|
199
|
+
deliver({value: lineParts.join(""), error: null, bytes: lineBytes, queueOverflow: false});
|
|
200
|
+
}
|
|
201
|
+
lineParts = [];
|
|
202
|
+
lineBytes = 0;
|
|
203
|
+
lineOverflowed = false;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function consume(text) {
|
|
207
|
+
let start = 0;
|
|
208
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
209
|
+
const unit = text.charCodeAt(index);
|
|
210
|
+
if (swallowLineFeed) {
|
|
211
|
+
swallowLineFeed = false;
|
|
212
|
+
if (unit === 10) { start = index + 1; continue; }
|
|
213
|
+
}
|
|
214
|
+
if (unit !== 10 && unit !== 13) continue;
|
|
215
|
+
appendLine(text, start, index);
|
|
216
|
+
completeLine();
|
|
217
|
+
start = index + 1;
|
|
218
|
+
if (unit === 13) swallowLineFeed = true;
|
|
219
|
+
}
|
|
220
|
+
appendLine(text, start, text.length);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function settleInput(error = null) {
|
|
224
|
+
if (closed) return;
|
|
225
|
+
closed = true;
|
|
226
|
+
failure = error;
|
|
227
|
+
requestForwardedInput(false);
|
|
228
|
+
while (waiting.length > 0) {
|
|
229
|
+
const request = waiting.shift();
|
|
230
|
+
if (error) respond(request.id, false, null, errorRecord(error));
|
|
231
|
+
else respond(request.id, true, null);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function acceptRead(id) {
|
|
236
|
+
if (queued.length > 0) {
|
|
237
|
+
const entry = queued.shift();
|
|
238
|
+
queuedBytes -= entry.bytes;
|
|
239
|
+
if (entry.queueOverflow) queueOverflowed = false;
|
|
240
|
+
if (entry.error) respond(id, false, null, errorRecord(entry.error));
|
|
241
|
+
else respond(id, true, entry.value);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (failure) { respond(id, false, null, errorRecord(failure)); return; }
|
|
245
|
+
if (closed) { respond(id, true, null); return; }
|
|
246
|
+
waiting.push({id});
|
|
247
|
+
requestForwardedInput(true);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function acceptForwardedData(value) {
|
|
251
|
+
if (closed || !value || typeof value !== "object" || !(value.data instanceof Uint8Array)
|
|
252
|
+
|| value.data.byteLength > maxTextBytes) {
|
|
253
|
+
throw new TypeError("Node terminal host received invalid forwarded input");
|
|
254
|
+
}
|
|
255
|
+
consume(decoder.write(value.data));
|
|
256
|
+
if (waiting.length === 0) requestForwardedInput(false);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function endForwardedInput(error = null) {
|
|
260
|
+
if (closed) return;
|
|
261
|
+
if (error !== null) { settleInput(error); return; }
|
|
262
|
+
const tail = decoder.end();
|
|
263
|
+
if (tail) consume(tail);
|
|
264
|
+
if (lineParts.length > 0 || lineOverflowed) completeLine();
|
|
265
|
+
settleInput();
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async function dispatch(value) {
|
|
269
|
+
let request;
|
|
270
|
+
try {
|
|
271
|
+
request = requestOf(value);
|
|
272
|
+
if (request.operation === "write" || request.operation === "writeError") {
|
|
273
|
+
await writeText(request.operation === "write" ? 1 : 2, request.value);
|
|
274
|
+
respond(request.id, true, null);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (request.value.length > 0) await writeText(1, request.value);
|
|
278
|
+
acceptRead(request.id);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
if (request) respond(request.id, false, null, errorRecord(error));
|
|
281
|
+
else throw error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function closeInput() {
|
|
286
|
+
closed = true;
|
|
287
|
+
failure = null;
|
|
288
|
+
while (waiting.length > 0) waiting.shift();
|
|
289
|
+
while (queued.length > 0) queued.shift();
|
|
290
|
+
queuedBytes = 0;
|
|
291
|
+
requestForwardedInput(false);
|
|
292
|
+
if (inputHost !== null) {
|
|
293
|
+
try { inputHost.send({kind: "close"}); } catch {}
|
|
294
|
+
}
|
|
295
|
+
port.postMessage({kind: "closed", error: null});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
port.on("message", value => {
|
|
299
|
+
if (value && typeof value === "object" && value.kind === "close") {
|
|
300
|
+
closeInput();
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
operationTail = operationTail.then(() => dispatch(value));
|
|
304
|
+
operationTail.catch(error => { queueMicrotask(() => { throw error; }); });
|
|
305
|
+
});
|
|
306
|
+
port.on("messageerror", () => { throw new Error("Node terminal host received an unreadable request"); });
|
|
307
|
+
port.start();
|
|
308
|
+
process.once("exit", () => { if (inputHost !== null) inputHost.kill("SIGKILL"); });
|
|
309
|
+
port.postMessage({kind: "ready", interactive: isatty(0) && isatty(1)});
|
|
310
|
+
`.trimStart();
|
|
311
|
+
//# sourceMappingURL=terminal-worker-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-worker-runtime.js","sourceRoot":"","sources":["../src/terminal-worker-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,gCAAgC,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;CAuBlD,CAAC,SAAS,EAAE,CAAC;AAEd,+EAA+E;AAC/E,gFAAgF;AAChF,oEAAoE;AACpE,MAAM,CAAC,MAAM,iCAAiC,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;0BASjC,IAAI,CAAC,SAAS,CAAC,gCAAgC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiRzE,CAAC,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-runtime.d.ts","sourceRoot":"","sources":["../src/websocket-runtime.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,QA4C5B,CAAC"}
|