@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.
Files changed (67) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +148 -0
  3. package/dist/compiler.d.ts +12 -0
  4. package/dist/compiler.d.ts.map +1 -0
  5. package/dist/compiler.js +954 -0
  6. package/dist/compiler.js.map +1 -0
  7. package/dist/environment-runtime.d.ts +2 -0
  8. package/dist/environment-runtime.d.ts.map +1 -0
  9. package/dist/environment-runtime.js +53 -0
  10. package/dist/environment-runtime.js.map +1 -0
  11. package/dist/filesystem-runtime.d.ts +2 -0
  12. package/dist/filesystem-runtime.d.ts.map +1 -0
  13. package/dist/filesystem-runtime.js +329 -0
  14. package/dist/filesystem-runtime.js.map +1 -0
  15. package/dist/host-runtime.d.ts +2 -0
  16. package/dist/host-runtime.d.ts.map +1 -0
  17. package/dist/host-runtime.js +149 -0
  18. package/dist/host-runtime.js.map +1 -0
  19. package/dist/http-runtime.d.ts +2 -0
  20. package/dist/http-runtime.d.ts.map +1 -0
  21. package/dist/http-runtime.js +612 -0
  22. package/dist/http-runtime.js.map +1 -0
  23. package/dist/index.d.ts +9 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +18 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/node-host-runtime.d.ts +2 -0
  28. package/dist/node-host-runtime.d.ts.map +1 -0
  29. package/dist/node-host-runtime.js +314 -0
  30. package/dist/node-host-runtime.js.map +1 -0
  31. package/dist/node-host-worker-runtime.d.ts +2 -0
  32. package/dist/node-host-worker-runtime.d.ts.map +1 -0
  33. package/dist/node-host-worker-runtime.js +1144 -0
  34. package/dist/node-host-worker-runtime.js.map +1 -0
  35. package/dist/process-runtime.d.ts +2 -0
  36. package/dist/process-runtime.d.ts.map +1 -0
  37. package/dist/process-runtime.js +167 -0
  38. package/dist/process-runtime.js.map +1 -0
  39. package/dist/process-worker-runtime.d.ts +2 -0
  40. package/dist/process-worker-runtime.d.ts.map +1 -0
  41. package/dist/process-worker-runtime.js +473 -0
  42. package/dist/process-worker-runtime.js.map +1 -0
  43. package/dist/serve-runtime.d.ts +2 -0
  44. package/dist/serve-runtime.d.ts.map +1 -0
  45. package/dist/serve-runtime.js +463 -0
  46. package/dist/serve-runtime.js.map +1 -0
  47. package/dist/sqlite-runtime.d.ts +3 -0
  48. package/dist/sqlite-runtime.d.ts.map +1 -0
  49. package/dist/sqlite-runtime.js +92 -0
  50. package/dist/sqlite-runtime.js.map +1 -0
  51. package/dist/terminal-runtime.d.ts +2 -0
  52. package/dist/terminal-runtime.d.ts.map +1 -0
  53. package/dist/terminal-runtime.js +290 -0
  54. package/dist/terminal-runtime.js.map +1 -0
  55. package/dist/terminal-worker-runtime.d.ts +2 -0
  56. package/dist/terminal-worker-runtime.d.ts.map +1 -0
  57. package/dist/terminal-worker-runtime.js +311 -0
  58. package/dist/terminal-worker-runtime.js.map +1 -0
  59. package/dist/websocket-runtime.d.ts +2 -0
  60. package/dist/websocket-runtime.d.ts.map +1 -0
  61. package/dist/websocket-runtime.js +46 -0
  62. package/dist/websocket-runtime.js.map +1 -0
  63. package/dist/worker-runtime.d.ts +2 -0
  64. package/dist/worker-runtime.d.ts.map +1 -0
  65. package/dist/worker-runtime.js +160 -0
  66. package/dist/worker-runtime.js.map +1 -0
  67. package/package.json +41 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-host-worker-runtime.js","sourceRoot":"","sources":["../src/node-host-worker-runtime.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,iFAAiF;AACjF,yEAAyE;AACzE,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmnCtD,CAAC,SAAS,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const VELAR_PROCESS_HOST_RUNTIME: string;
2
+ //# sourceMappingURL=process-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-runtime.d.ts","sourceRoot":"","sources":["../src/process-runtime.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,0BAA0B,QAiK/B,CAAC"}
@@ -0,0 +1,167 @@
1
+ // Canonical host-intrinsic boundary shared by the Node and Desktop targets of
2
+ // velar/process. It is compiler-extension infrastructure, not a public Velar
3
+ // module: target runtimes inline it before accepting application or bridge
4
+ // values so later JavaScript prototype replacement cannot change validation.
5
+ export const VELAR_PROCESS_HOST_RUNTIME = String.raw `
6
+ const __velarProcessNativeArray = globalThis.Array;
7
+ const __velarProcessNativeError = globalThis.Error;
8
+ const __velarProcessNativeMap = globalThis.Map;
9
+ const __velarProcessNativeNumber = globalThis.Number;
10
+ const __velarProcessNativeObject = globalThis.Object;
11
+ const __velarProcessNativePromise = globalThis.Promise;
12
+ const __velarProcessNativeRangeError = globalThis.RangeError;
13
+ const __velarProcessNativeReflect = globalThis.Reflect;
14
+ const __velarProcessNativeSet = globalThis.Set;
15
+ const __velarProcessNativeString = globalThis.String;
16
+ const __velarProcessNativeTypeError = globalThis.TypeError;
17
+ const __velarProcessOwnDescriptor = __velarProcessNativeObject.getOwnPropertyDescriptor;
18
+ const __velarProcessApply = __velarProcessNativeReflect.apply;
19
+ function __velarProcessDataOperation(target, name) {
20
+ const descriptor = __velarProcessOwnDescriptor(target, name);
21
+ if (!descriptor || !("value" in descriptor) || typeof descriptor.value !== "function") {
22
+ throw new __velarProcessNativeError("VelarScript process host operation '" + name + "' is unavailable");
23
+ }
24
+ return descriptor.value;
25
+ }
26
+ const __velarProcessArrayIsArray = __velarProcessDataOperation(__velarProcessNativeArray, "isArray");
27
+ const __velarProcessArrayShift = __velarProcessDataOperation(__velarProcessNativeArray.prototype, "shift");
28
+ const __velarProcessNumberIsSafeInteger = __velarProcessDataOperation(__velarProcessNativeNumber, "isSafeInteger");
29
+ const __velarProcessObjectCreate = __velarProcessDataOperation(__velarProcessNativeObject, "create");
30
+ const __velarProcessObjectFreeze = __velarProcessDataOperation(__velarProcessNativeObject, "freeze");
31
+ const __velarProcessObjectGetPrototypeOf = __velarProcessDataOperation(__velarProcessNativeObject, "getPrototypeOf");
32
+ const __velarProcessObjectSeal = __velarProcessDataOperation(__velarProcessNativeObject, "seal");
33
+ const __velarProcessOwnKeys = __velarProcessDataOperation(__velarProcessNativeReflect, "ownKeys");
34
+ const __velarProcessPromiseReject = __velarProcessDataOperation(__velarProcessNativePromise, "reject");
35
+ const __velarProcessPromiseResolve = __velarProcessDataOperation(__velarProcessNativePromise, "resolve");
36
+ const __velarProcessPromiseThen = __velarProcessDataOperation(__velarProcessNativePromise.prototype, "then");
37
+ const __velarProcessSetHas = __velarProcessDataOperation(__velarProcessNativeSet.prototype, "has");
38
+ const __velarProcessStringIncludes = __velarProcessDataOperation(__velarProcessNativeString.prototype, "includes");
39
+ const __velarProcessMapEntries = __velarProcessDataOperation(__velarProcessNativeMap.prototype, "entries");
40
+ const __velarProcessMapSize = __velarProcessOwnDescriptor(__velarProcessNativeMap.prototype, "size")?.get;
41
+ const __velarProcessMapIterator = __velarProcessApply(__velarProcessMapEntries, new __velarProcessNativeMap(), []);
42
+ const __velarProcessMapIteratorNext = __velarProcessDataOperation(__velarProcessObjectGetPrototypeOf(__velarProcessMapIterator), "next");
43
+ const __velarProcessEnvironmentPattern = /^[A-Za-z_][A-Za-z0-9_]*$/u;
44
+ const __velarProcessRegExpTest = __velarProcessDataOperation(globalThis.RegExp.prototype, "test");
45
+ const __velarProcessSetTimeout = globalThis.setTimeout;
46
+ const __velarProcessClearTimeout = globalThis.clearTimeout;
47
+ function __velarProcessCall(operation, receiver, arguments_) {
48
+ return __velarProcessApply(operation, receiver, arguments_);
49
+ }
50
+ function __velarProcessIsArray(value) {
51
+ return __velarProcessCall(__velarProcessArrayIsArray, __velarProcessNativeArray, [value]);
52
+ }
53
+ function __velarProcessIsSafeInteger(value) {
54
+ return __velarProcessCall(__velarProcessNumberIsSafeInteger, __velarProcessNativeNumber, [value]);
55
+ }
56
+ function __velarProcessIncludes(value, search) {
57
+ return __velarProcessCall(__velarProcessStringIncludes, value, [search]);
58
+ }
59
+ function __velarProcessFreeze(value) {
60
+ return __velarProcessCall(__velarProcessObjectFreeze, __velarProcessNativeObject, [value]);
61
+ }
62
+ function __velarProcessSeal(value) {
63
+ return __velarProcessCall(__velarProcessObjectSeal, __velarProcessNativeObject, [value]);
64
+ }
65
+ function __velarProcessCreate(prototype) {
66
+ return __velarProcessCall(__velarProcessObjectCreate, __velarProcessNativeObject, [prototype]);
67
+ }
68
+ function __velarProcessGetPrototypeOf(value) {
69
+ return __velarProcessCall(__velarProcessObjectGetPrototypeOf, __velarProcessNativeObject, [value]);
70
+ }
71
+ function __velarProcessKeys(value) {
72
+ return __velarProcessCall(__velarProcessOwnKeys, __velarProcessNativeReflect, [value]);
73
+ }
74
+ function __velarProcessSetContains(value, item) {
75
+ return __velarProcessCall(__velarProcessSetHas, value, [item]);
76
+ }
77
+ function __velarProcessShift(value) {
78
+ return __velarProcessCall(__velarProcessArrayShift, value, []);
79
+ }
80
+ function __velarProcessReject(error) {
81
+ return __velarProcessCall(__velarProcessPromiseReject, __velarProcessNativePromise, [error]);
82
+ }
83
+ function __velarProcessResolve(value) {
84
+ return __velarProcessCall(__velarProcessPromiseResolve, __velarProcessNativePromise, [value]);
85
+ }
86
+ function __velarProcessThen(value, fulfilled, rejected) {
87
+ return __velarProcessCall(__velarProcessPromiseThen, value, [fulfilled, rejected]);
88
+ }
89
+ function __velarProcessObservedReject(error) {
90
+ const result = __velarProcessReject(error);
91
+ __velarProcessThen(result, undefined, () => null);
92
+ return result;
93
+ }
94
+ async function __velarProcessRetryableStop(owner, begin) {
95
+ owner.stopRequested = true;
96
+ let pending = owner.stopping;
97
+ if (!pending) {
98
+ pending = begin();
99
+ owner.stopping = pending;
100
+ }
101
+ try { await pending; }
102
+ catch (error) {
103
+ if (owner.stopping === pending) owner.stopping = null;
104
+ throw error;
105
+ }
106
+ return null;
107
+ }
108
+ function __velarProcessRetainRun(owner) {
109
+ if (owner.cleanup !== null) return;
110
+ const retry = async () => {
111
+ try {
112
+ await owner.stop();
113
+ owner.cleanup = null;
114
+ } catch {
115
+ owner.cleanup = __velarProcessCall(__velarProcessSetTimeout, globalThis, [retry, 1000]);
116
+ }
117
+ };
118
+ owner.cleanup = true;
119
+ void retry();
120
+ }
121
+ function __velarProcessEnvironmentName(value) {
122
+ return typeof value === "string" && __velarProcessCall(__velarProcessRegExpTest, __velarProcessEnvironmentPattern, [value]);
123
+ }
124
+ function __velarProcessMapSnapshot(value) {
125
+ if (typeof __velarProcessMapSize !== "function") throw new __velarProcessNativeTypeError("Process env must be Map<string, string>");
126
+ let size;
127
+ let iterator;
128
+ try {
129
+ size = __velarProcessCall(__velarProcessMapSize, value, []);
130
+ iterator = __velarProcessCall(__velarProcessMapEntries, value, []);
131
+ } catch {
132
+ throw new __velarProcessNativeTypeError("Process env must be Map<string, string>");
133
+ }
134
+ const entries = [];
135
+ while (true) {
136
+ let step;
137
+ try { step = __velarProcessCall(__velarProcessMapIteratorNext, iterator, []); }
138
+ catch { throw new __velarProcessNativeTypeError("Process env must be Map<string, string>"); }
139
+ const done = __velarProcessOwnDescriptor(step, "done");
140
+ if (!done || !("value" in done) || typeof done.value !== "boolean") throw new __velarProcessNativeTypeError("Process env must be Map<string, string>");
141
+ if (done.value) return {size, entries};
142
+ const item = __velarProcessOwnDescriptor(step, "value");
143
+ if (!item || !("value" in item) || !__velarProcessIsArray(item.value) || item.value.length !== 2) throw new __velarProcessNativeTypeError("Process env must be Map<string, string>");
144
+ const name = __velarProcessOwnDescriptor(item.value, "0");
145
+ const valueDescriptor = __velarProcessOwnDescriptor(item.value, "1");
146
+ if (!name || !("value" in name) || !valueDescriptor || !("value" in valueDescriptor)) throw new __velarProcessNativeTypeError("Process env must be Map<string, string>");
147
+ entries[entries.length] = [name.value, valueDescriptor.value];
148
+ }
149
+ }
150
+ function __velarProcessRecord(value, name, allowed) {
151
+ if (!value || typeof value !== "object" || __velarProcessIsArray(value)) throw new __velarProcessNativeTypeError(name + " must be a record");
152
+ const prototype = __velarProcessGetPrototypeOf(value);
153
+ if (prototype !== __velarProcessNativeObject.prototype && prototype !== null) throw new __velarProcessNativeTypeError(name + " must be a plain record");
154
+ const output = __velarProcessCreate(null);
155
+ const keys = __velarProcessKeys(value);
156
+ for (let index = 0; index < keys.length; index += 1) {
157
+ const key = keys[index];
158
+ if (typeof key !== "string") throw new __velarProcessNativeTypeError(name + " fields must use string names");
159
+ if (!__velarProcessSetContains(allowed, key)) throw new __velarProcessNativeTypeError(name + " has unknown field '" + key + "'");
160
+ const descriptor = __velarProcessOwnDescriptor(value, key);
161
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new __velarProcessNativeTypeError(name + " fields must be enumerable data values");
162
+ output[key] = descriptor.value;
163
+ }
164
+ return output;
165
+ }
166
+ `.trim();
167
+ //# sourceMappingURL=process-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-runtime.js","sourceRoot":"","sources":["../src/process-runtime.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiKnD,CAAC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const VELAR_NODE_PROCESS_WORKER_SOURCE: string;
2
+ //# sourceMappingURL=process-worker-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-worker-runtime.d.ts","sourceRoot":"","sources":["../src/process-worker-runtime.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gCAAgC,QAkd5C,CAAC"}
@@ -0,0 +1,473 @@
1
+ // Complete Node-only process host. It is evaluated in an eagerly initialized
2
+ // Worker realm that never loads application dependencies, because Node's own
3
+ // child_process implementation consults public EventEmitter/stream prototypes
4
+ // while spawning and cannot be made post-initialization-stable in a shared
5
+ // application realm by wrapping only the outer calls.
6
+ export const VELAR_NODE_PROCESS_WORKER_SOURCE = String.raw `
7
+ import {spawn} from "node:child_process";
8
+ import {StringDecoder} from "node:string_decoder";
9
+ import {workerData} from "node:worker_threads";
10
+
11
+ const port = workerData;
12
+ const maxTextBytes = 16 * 1024 * 1024;
13
+ const maxProcessHandles = 128;
14
+ const maxOutputChunks = 1000000;
15
+ const stopConfirmationTimeoutMs = 5000;
16
+ const exitPipeConfirmationTimeoutMs = 5000;
17
+ const fatalDrainTimeoutMs = 8000;
18
+ const requestFields = new Set(["id", "operation", "args"]);
19
+ const optionFields = new Set(["cwd", "env", "stdin", "timeout", "maxOutputBytes"]);
20
+ const processHandles = new Map();
21
+ let nextProcessHandle = 1;
22
+ let fatalDrainStarted = false;
23
+ const terminationMarker = Object.freeze({});
24
+ const rootExitMarker = Object.freeze({});
25
+ const stopMarker = Object.freeze({});
26
+
27
+ function ownRecord(value, name, allowed) {
28
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError(name + " must be a record");
29
+ const prototype = Object.getPrototypeOf(value);
30
+ if (prototype !== Object.prototype && prototype !== null) throw new TypeError(name + " must be a plain record");
31
+ const output = Object.create(null);
32
+ for (const key of Reflect.ownKeys(value)) {
33
+ if (typeof key !== "string" || !allowed.has(key)) throw new TypeError(name + " has an unknown field");
34
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
35
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError(name + " fields must be enumerable data values");
36
+ output[key] = descriptor.value;
37
+ }
38
+ return output;
39
+ }
40
+
41
+ function boundedText(value, name, maximum = 4096) {
42
+ if (typeof value !== "string" || value.length === 0) throw new TypeError(name + " must be non-empty text");
43
+ if (value.length > maximum || value.includes("\0")) throw new RangeError(name + " is outside the supported bounds");
44
+ return value;
45
+ }
46
+
47
+ function integer(value, minimum, maximum, name) {
48
+ if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
49
+ throw new RangeError(name + " must be an integer from " + minimum + " through " + maximum);
50
+ }
51
+ return value;
52
+ }
53
+
54
+ function argumentsOf(value) {
55
+ if (!Array.isArray(value) || value.length > 1000) throw new TypeError("Process args must be a bounded List<string>");
56
+ const output = [];
57
+ let units = 0;
58
+ for (let index = 0; index < value.length; index += 1) {
59
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
60
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError("Process args must contain enumerable data values");
61
+ const item = boundedText(descriptor.value, "Process argument", 1024 * 1024);
62
+ units += item.length;
63
+ if (units > 1024 * 1024) throw new RangeError("Process arguments cannot exceed 1 MiB");
64
+ output.push(item);
65
+ }
66
+ return output;
67
+ }
68
+
69
+ function environmentOf(value) {
70
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Process environment must be a record");
71
+ const prototype = Object.getPrototypeOf(value);
72
+ if (prototype !== Object.prototype && prototype !== null) throw new TypeError("Process environment must be a plain record");
73
+ const output = Object.create(null);
74
+ const keys = Reflect.ownKeys(value);
75
+ if (keys.length > 1010) throw new RangeError("Process environment cannot exceed its field limit");
76
+ let units = 0;
77
+ for (const name of keys) {
78
+ const descriptor = Object.getOwnPropertyDescriptor(value, name);
79
+ if (typeof name !== "string" || !descriptor?.enumerable || !("value" in descriptor)
80
+ || !/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)
81
+ || typeof descriptor.value !== "string" || descriptor.value.includes("\0")) {
82
+ throw new TypeError("Process environment must contain valid string variables");
83
+ }
84
+ const item = descriptor.value;
85
+ units += name.length + item.length;
86
+ if (units > 2 * 1024 * 1024) throw new RangeError("Process environment exceeds its transport boundary");
87
+ output[name] = item;
88
+ }
89
+ return output;
90
+ }
91
+
92
+ function optionsOf(value) {
93
+ value = ownRecord(value, "Process options", optionFields);
94
+ const cwd = value.cwd == null ? undefined : boundedText(value.cwd, "Process cwd");
95
+ const stdin = value.stdin ?? "";
96
+ if (typeof stdin !== "string" || Buffer.byteLength(stdin, "utf8") > maxTextBytes) throw new RangeError("Process stdin cannot exceed 16 MiB");
97
+ const timeout = integer(value.timeout ?? 120000, 0, 600000, "Process timeout");
98
+ const maxOutputBytes = integer(value.maxOutputBytes ?? 4 * 1024 * 1024, 1, maxTextBytes, "Process maxOutputBytes");
99
+ return {cwd, env: environmentOf(value.env), stdin, timeout, maxOutputBytes};
100
+ }
101
+
102
+ function processHandle(value) {
103
+ return integer(value, 1, Number.MAX_SAFE_INTEGER, "Node process handle");
104
+ }
105
+
106
+ function errorRecord(error) {
107
+ const name = error instanceof TypeError ? "TypeError" : error instanceof RangeError ? "RangeError" : "Error";
108
+ let message = error instanceof Error ? error.message : "Node process host failed";
109
+ if (typeof message !== "string" || message.length === 0) message = "Node process host failed";
110
+ if (message.length > 65536) message = message.slice(0, 65536);
111
+ return {name, message};
112
+ }
113
+
114
+ function terminalOutcome(task) {
115
+ return task.result.then(
116
+ (result) => ({result, error: null, retained: false}),
117
+ (failure) => ({result: null, error: errorRecord(failure), retained: false}),
118
+ );
119
+ }
120
+
121
+ async function confirmationOutcome(terminal) {
122
+ let timer = null;
123
+ const confirmationFailure = new Error("Process termination could not be confirmed within " + stopConfirmationTimeoutMs + " milliseconds");
124
+ try {
125
+ return await Promise.race([
126
+ terminal,
127
+ new Promise((resolve) => {
128
+ timer = setTimeout(
129
+ () => resolve({result: null, error: errorRecord(confirmationFailure), retained: true}),
130
+ stopConfirmationTimeoutMs,
131
+ );
132
+ }),
133
+ ]);
134
+ } finally {
135
+ if (timer !== null) clearTimeout(timer);
136
+ }
137
+ }
138
+
139
+ async function waitForTask(task) {
140
+ const terminal = terminalOutcome(task);
141
+ if (!task.terminationRequested) {
142
+ const first = await Promise.race([terminal, task.termination.then(() => terminationMarker)]);
143
+ if (first !== terminationMarker) return first;
144
+ }
145
+ if (task.rootExited && !task.stopping) {
146
+ const afterExit = await Promise.race([terminal, task.stopRequest.then(() => stopMarker)]);
147
+ if (afterExit !== stopMarker) return afterExit;
148
+ return await confirmationOutcome(terminal);
149
+ }
150
+ const confirmation = confirmationOutcome(terminal);
151
+ const first = await Promise.race([
152
+ terminal,
153
+ confirmation,
154
+ task.stopping ? new Promise(() => {}) : task.rootExit.then(() => rootExitMarker),
155
+ ]);
156
+ if (first !== rootExitMarker) return first;
157
+ if (task.stopping) return await confirmation;
158
+ const afterExit = await Promise.race([terminal, task.stopRequest.then(() => stopMarker)]);
159
+ if (afterExit !== stopMarker) return afterExit;
160
+ return await confirmationOutcome(terminal);
161
+ }
162
+
163
+ function send(value) {
164
+ port.postMessage(value);
165
+ }
166
+
167
+ function signalTree(child, signal) {
168
+ if (!child.pid) return;
169
+ if (process.platform === "win32") {
170
+ try {
171
+ const args = ["/pid", String(child.pid), "/t"];
172
+ if (signal === "SIGKILL") args.push("/f");
173
+ const killer = spawn("taskkill", args, {shell: false, stdio: "ignore", windowsHide: true});
174
+ killer.unref();
175
+ return;
176
+ } catch {}
177
+ try { child.kill(signal); } catch {}
178
+ return;
179
+ }
180
+ try { process.kill(-child.pid, signal); }
181
+ catch { try { child.kill(signal); } catch {} }
182
+ }
183
+
184
+ async function waitForProcessGroupExit(child) {
185
+ if (process.platform === "win32" || !child.pid) return;
186
+ while (true) {
187
+ try { process.kill(-child.pid, 0); }
188
+ catch (error) {
189
+ if (error && typeof error === "object" && error.code === "ESRCH") return;
190
+ throw error;
191
+ }
192
+ await new Promise(resolve => setTimeout(resolve, 20));
193
+ }
194
+ }
195
+
196
+ function launchProcess(command, commandArgs, options, settled) {
197
+ const child = spawn(command, commandArgs, {
198
+ cwd: options.cwd,
199
+ env: options.env,
200
+ shell: false,
201
+ stdio: ["pipe", "pipe", "pipe"],
202
+ windowsHide: true,
203
+ detached: process.platform !== "win32",
204
+ });
205
+ let resolveTermination;
206
+ const termination = new Promise((resolve) => { resolveTermination = resolve; });
207
+ let resolveRootExit;
208
+ const rootExit = new Promise((resolve) => { resolveRootExit = resolve; });
209
+ let resolveStopRequest;
210
+ const stopRequest = new Promise((resolve) => { resolveStopRequest = resolve; });
211
+ const task = {
212
+ child,
213
+ pid: child.pid ?? 0,
214
+ settled: false,
215
+ stopping: false,
216
+ terminationRequested: false,
217
+ termination,
218
+ rootExited: false,
219
+ rootExit,
220
+ stopRequest,
221
+ stdout: [],
222
+ stderr: [],
223
+ outputBytes: 0,
224
+ outputChunks: 0,
225
+ outputQueue: [],
226
+ outputWaiter: null,
227
+ reading: false,
228
+ waitStarted: false,
229
+ waitRetained: false,
230
+ stdoutDecoder: new StringDecoder("utf8"),
231
+ stderrDecoder: new StringDecoder("utf8"),
232
+ failure: null,
233
+ timer: null,
234
+ exitTimer: null,
235
+ result: null,
236
+ terminate(failure, signal) {
237
+ if (failure && !task.failure) task.failure = failure;
238
+ if (!task.terminationRequested) {
239
+ task.terminationRequested = true;
240
+ resolveTermination();
241
+ }
242
+ if (task.outputWaiter) {
243
+ const waiter = task.outputWaiter;
244
+ task.outputWaiter = null;
245
+ waiter.reject(task.failure ?? new Error("Process output is unavailable after stop()"));
246
+ }
247
+ signalTree(child, signal);
248
+ },
249
+ stop() {
250
+ if (task.settled) return;
251
+ if (task.stopping) {
252
+ signalTree(child, "SIGKILL");
253
+ return;
254
+ }
255
+ task.stopping = true;
256
+ resolveStopRequest();
257
+ if (task.exitTimer) {
258
+ clearTimeout(task.exitTimer);
259
+ task.exitTimer = null;
260
+ }
261
+ task.terminate(null, "SIGTERM");
262
+ setTimeout(() => { if (!task.settled) signalTree(child, "SIGKILL"); }, 2000).unref();
263
+ },
264
+ async next() {
265
+ if (task.waitStarted) throw new Error("Process output must be consumed before wait()");
266
+ if (task.stopping) throw new Error("Process output is unavailable after stop()");
267
+ if (task.terminationRequested) throw task.failure ?? new Error("Process output is unavailable after termination");
268
+ if (task.reading) throw new Error("Process.next() allows only one active pull");
269
+ task.reading = true;
270
+ try {
271
+ if (task.outputQueue.length > 0) return task.outputQueue.shift();
272
+ if (task.settled) {
273
+ if (task.failure) throw task.failure;
274
+ return null;
275
+ }
276
+ return await new Promise((resolve, reject) => { task.outputWaiter = {resolve, reject}; });
277
+ } finally {
278
+ task.reading = false;
279
+ }
280
+ },
281
+ };
282
+ task.result = new Promise((resolve, reject) => {
283
+ const deliver = (channel, text) => {
284
+ if (text.length === 0 || task.failure) return;
285
+ task.outputChunks += 1;
286
+ if (task.outputChunks > maxOutputChunks) {
287
+ task.terminate(new RangeError("Process output cannot exceed 1000000 chunks"), "SIGKILL");
288
+ return;
289
+ }
290
+ const value = Object.freeze({channel, text});
291
+ if (task.outputWaiter) {
292
+ const waiter = task.outputWaiter;
293
+ task.outputWaiter = null;
294
+ waiter.resolve(value);
295
+ } else task.outputQueue.push(value);
296
+ };
297
+ const collect = (target, decoder, channel, chunk) => {
298
+ if (task.failure) return;
299
+ task.outputBytes += chunk.byteLength;
300
+ if (task.outputBytes > options.maxOutputBytes) {
301
+ task.terminate(new RangeError("Process output exceeded maxOutputBytes"), "SIGKILL");
302
+ return;
303
+ }
304
+ const copy = Buffer.from(chunk);
305
+ target.push(copy);
306
+ deliver(channel, decoder.write(copy));
307
+ };
308
+ child.stdout.on("data", (chunk) => collect(task.stdout, task.stdoutDecoder, "stdout", chunk));
309
+ child.stderr.on("data", (chunk) => collect(task.stderr, task.stderrDecoder, "stderr", chunk));
310
+ child.once("error", (error) => { task.terminate(error, "SIGKILL"); });
311
+ child.once("exit", () => {
312
+ task.rootExited = true;
313
+ resolveRootExit();
314
+ if (!task.stopping) {
315
+ signalTree(child, "SIGTERM");
316
+ setTimeout(() => { if (!task.settled) signalTree(child, "SIGKILL"); }, 2000).unref();
317
+ task.exitTimer = setTimeout(() => {
318
+ if (task.settled) return;
319
+ if (!task.failure) task.failure = new Error("Process output streams did not close within " + exitPipeConfirmationTimeoutMs + " milliseconds after process exit");
320
+ child.stdout.destroy();
321
+ child.stderr.destroy();
322
+ }, exitPipeConfirmationTimeoutMs);
323
+ task.exitTimer.unref();
324
+ }
325
+ });
326
+ child.once("close", (code, signal) => { void (async () => {
327
+ // A POSIX root can close before all live descendants have stopped.
328
+ // stop() owns the whole detached process group, so its result is not
329
+ // terminal until that group has no live members. waitForTask() keeps this
330
+ // confirmation bounded and retains the handle when it cannot be proven.
331
+ if (task.stopping) await waitForProcessGroupExit(child);
332
+ task.settled = true;
333
+ if (task.timer) clearTimeout(task.timer);
334
+ if (task.exitTimer) clearTimeout(task.exitTimer);
335
+ deliver("stdout", task.stdoutDecoder.end());
336
+ deliver("stderr", task.stderrDecoder.end());
337
+ if (task.outputWaiter) {
338
+ const waiter = task.outputWaiter;
339
+ task.outputWaiter = null;
340
+ if (task.outputQueue.length > 0) waiter.resolve(task.outputQueue.shift());
341
+ else if (task.failure) waiter.reject(task.failure);
342
+ else waiter.resolve(null);
343
+ }
344
+ settled();
345
+ if (task.failure) reject(task.failure);
346
+ else resolve(Object.freeze({
347
+ code: code == null ? null : code,
348
+ // taskkill reports an exit code rather than a POSIX signal. The public
349
+ // Process contract reports the termination stop() requested, so callers
350
+ // get one portable answer instead of an OS implementation detail.
351
+ signal: signal == null && task.stopping && process.platform === "win32" ? "SIGTERM" : signal == null ? null : signal,
352
+ stdout: Buffer.concat(task.stdout).toString("utf8"),
353
+ stderr: Buffer.concat(task.stderr).toString("utf8"),
354
+ }));
355
+ })().catch((error) => {
356
+ if (!task.failure) task.failure = error instanceof Error ? error : new Error("Process group exit confirmation failed");
357
+ task.settled = true;
358
+ if (task.timer) clearTimeout(task.timer);
359
+ if (task.exitTimer) clearTimeout(task.exitTimer);
360
+ settled();
361
+ reject(task.failure);
362
+ }); });
363
+ });
364
+ task.timer = options.timeout === 0 ? null : setTimeout(() => {
365
+ if (task.settled) return;
366
+ task.terminate(new Error("Process timed out after " + options.timeout + " milliseconds"), "SIGKILL");
367
+ }, options.timeout);
368
+ child.stdin.end(options.stdin);
369
+ return task;
370
+ }
371
+
372
+ async function processStart(args) {
373
+ if (processHandles.size >= maxProcessHandles) throw new RangeError("Node process handle limit reached");
374
+ if (!Array.isArray(args) || args.length !== 3) throw new TypeError("Node process start arguments are invalid");
375
+ const command = boundedText(args[0], "Process command");
376
+ const commandArgs = argumentsOf(args[1]);
377
+ const options = optionsOf(args[2]);
378
+ const handle = nextProcessHandle++;
379
+ const task = launchProcess(command, commandArgs, options, () => send({kind: "settled", handle}));
380
+ processHandles.set(handle, task);
381
+ // Transfer cleanup ownership before the start response. The application
382
+ // proxy can then reap this process group even if this Worker exits between
383
+ // accepting the child and resolving start().
384
+ send({kind: "owned", handle, pid: task.pid});
385
+ task.result.catch(() => {});
386
+ return {handle, pid: task.pid};
387
+ }
388
+
389
+ async function processRead(args) {
390
+ if (!Array.isArray(args) || args.length !== 1) throw new TypeError("Node process read arguments are invalid");
391
+ const handle = processHandle(args[0]);
392
+ const task = processHandles.get(handle);
393
+ if (!task) throw new Error("Node process handle is unknown or already released");
394
+ return task.next();
395
+ }
396
+
397
+ async function processWait(args) {
398
+ if (!Array.isArray(args) || args.length !== 1) throw new TypeError("Node process wait arguments are invalid");
399
+ const handle = processHandle(args[0]);
400
+ const task = processHandles.get(handle);
401
+ if (!task) throw new Error("Node process handle is unknown or already released");
402
+ if (task.reading) throw new Error("Process wait() cannot run while next() is pending");
403
+ task.waitStarted = true;
404
+ if (task.waitRetained && !task.settled) signalTree(task.child, "SIGKILL");
405
+ const outcome = await waitForTask(task);
406
+ task.waitRetained = outcome.retained;
407
+ if (!outcome.retained) processHandles.delete(handle);
408
+ return outcome;
409
+ }
410
+
411
+ async function processStop(args) {
412
+ if (!Array.isArray(args) || args.length !== 1) throw new TypeError("Node process stop arguments are invalid");
413
+ const handle = processHandle(args[0]);
414
+ const task = processHandles.get(handle);
415
+ if (!task) return {result: null, error: null};
416
+ task.stop();
417
+ const outcome = await waitForTask(task);
418
+ if (outcome.retained) throw new Error(outcome.error.message);
419
+ processHandles.delete(handle);
420
+ return {result: outcome.result, error: outcome.error};
421
+ }
422
+
423
+ async function fatalDrain() {
424
+ if (fatalDrainStarted) return;
425
+ fatalDrainStarted = true;
426
+ port.removeAllListeners("message");
427
+ const tasks = Array.from(processHandles.values());
428
+ for (const task of tasks) task.stop();
429
+ let timer = null;
430
+ try {
431
+ await Promise.race([
432
+ Promise.allSettled(tasks.map(task => task.result)),
433
+ new Promise(resolve => { timer = setTimeout(resolve, fatalDrainTimeoutMs); }),
434
+ ]);
435
+ } finally {
436
+ if (timer !== null) clearTimeout(timer);
437
+ for (const task of tasks) if (!task.settled) signalTree(task.child, "SIGKILL");
438
+ process.exit(1);
439
+ }
440
+ }
441
+
442
+ async function dispatch(value) {
443
+ const request = ownRecord(value, "Node process request", requestFields);
444
+ const id = integer(request.id, 1, Number.MAX_SAFE_INTEGER, "Node process request id");
445
+ if (!Array.isArray(request.args)) throw new TypeError("Node process request args must be a List");
446
+ let result;
447
+ if (request.operation === "start") result = await processStart(request.args);
448
+ else if (request.operation === "read") result = await processRead(request.args);
449
+ else if (request.operation === "wait") result = await processWait(request.args);
450
+ else if (request.operation === "stop") result = await processStop(request.args);
451
+ else throw new TypeError("Unknown Node process operation");
452
+ return {id, result};
453
+ }
454
+
455
+ port.on("message", (value) => {
456
+ Promise.resolve(dispatch(value)).then(
457
+ ({id, result}) => send({kind: "response", id, ok: true, value: result}),
458
+ (error) => {
459
+ const descriptor = value && typeof value === "object" ? Object.getOwnPropertyDescriptor(value, "id") : null;
460
+ const id = descriptor && "value" in descriptor && Number.isSafeInteger(descriptor.value) ? descriptor.value : 0;
461
+ send({kind: "response", id, ok: false, error: errorRecord(error)});
462
+ },
463
+ );
464
+ });
465
+ process.on("uncaughtException", () => { void fatalDrain(); });
466
+ process.on("unhandledRejection", () => { void fatalDrain(); });
467
+ port.on("close", () => { void fatalDrain(); });
468
+ process.once("exit", () => {
469
+ for (const task of processHandles.values()) signalTree(task.child, "SIGKILL");
470
+ });
471
+ send({kind: "ready"});
472
+ `;
473
+ //# sourceMappingURL=process-worker-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-worker-runtime.js","sourceRoot":"","sources":["../src/process-worker-runtime.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6EAA6E;AAC7E,8EAA8E;AAC9E,2EAA2E;AAC3E,sDAAsD;AACtD,MAAM,CAAC,MAAM,gCAAgC,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkdzD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const VELAR_NODE_SERVE_RUNTIME: string;
2
+ //# sourceMappingURL=serve-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-runtime.d.ts","sourceRoot":"","sources":["../src/serve-runtime.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,QA0cxB,CAAC"}