@cldmv/slothlet 2.11.0 → 3.0.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/AGENT-USAGE.md +355 -325
- package/README.md +554 -238
- package/dist/lib/builders/api-assignment.mjs +605 -0
- package/dist/lib/builders/api_builder.mjs +1073 -0
- package/dist/lib/builders/builder.mjs +94 -0
- package/dist/lib/builders/modes-processor.mjs +1816 -0
- package/dist/lib/errors.mjs +227 -0
- package/dist/lib/factories/component-base.mjs +96 -0
- package/dist/lib/factories/context.mjs +38 -0
- package/dist/lib/handlers/api-cache-manager.mjs +216 -0
- package/dist/lib/handlers/api-manager.mjs +2364 -0
- package/dist/lib/handlers/context-async.mjs +184 -0
- package/dist/lib/handlers/context-live.mjs +184 -0
- package/dist/lib/handlers/hook-manager.mjs +789 -0
- package/dist/lib/handlers/lifecycle-token.mjs +44 -0
- package/dist/lib/handlers/lifecycle.mjs +131 -0
- package/dist/lib/handlers/materialize-manager.mjs +64 -0
- package/dist/lib/handlers/metadata.mjs +500 -0
- package/dist/lib/handlers/ownership.mjs +338 -0
- package/dist/lib/handlers/unified-wrapper.mjs +3031 -0
- package/dist/lib/helpers/class-instance-wrapper.mjs +125 -0
- package/dist/lib/helpers/config.mjs +343 -0
- package/dist/lib/helpers/eventemitter-context.mjs +365 -0
- package/dist/lib/helpers/hint-detector.mjs +63 -0
- package/dist/lib/helpers/modes-utils.mjs +53 -0
- package/dist/lib/helpers/resolve-from-caller.mjs +123 -117
- package/dist/lib/helpers/sanitize.mjs +247 -168
- package/dist/lib/helpers/utilities.mjs +46 -81
- package/dist/lib/i18n/languages/de-de.json +377 -0
- package/dist/lib/i18n/languages/en-gb.json +377 -0
- package/dist/lib/i18n/languages/en-us.json +377 -0
- package/dist/lib/i18n/languages/es-mx.json +377 -0
- package/dist/lib/i18n/languages/fr-fr.json +377 -0
- package/dist/lib/i18n/languages/hi-in.json +377 -0
- package/dist/lib/i18n/languages/ja-jp.json +377 -0
- package/dist/lib/i18n/languages/ko-kr.json +377 -0
- package/dist/lib/i18n/languages/pt-br.json +377 -0
- package/dist/lib/i18n/languages/ru-ru.json +377 -0
- package/dist/lib/i18n/languages/zh-cn.json +377 -0
- package/dist/lib/i18n/translations.mjs +140 -0
- package/dist/lib/modes/eager.mjs +75 -0
- package/dist/lib/modes/lazy.mjs +97 -0
- package/dist/lib/processors/flatten.mjs +453 -0
- package/dist/lib/processors/loader.mjs +355 -0
- package/dist/lib/processors/type-generator.mjs +291 -0
- package/dist/lib/processors/typescript.mjs +188 -0
- package/dist/lib/runtime/runtime-asynclocalstorage.mjs +80 -522
- package/dist/lib/runtime/runtime-livebindings.mjs +45 -390
- package/dist/lib/runtime/runtime.mjs +39 -159
- package/dist/slothlet.mjs +525 -744
- package/docs/API-RULES.md +338 -486
- package/index.cjs +4 -4
- package/index.mjs +82 -45
- package/package.json +143 -30
- package/types/dist/lib/builders/api-assignment.d.mts +97 -0
- package/types/dist/lib/builders/api-assignment.d.mts.map +1 -0
- package/types/dist/lib/builders/api_builder.d.mts +96 -0
- package/types/dist/lib/builders/api_builder.d.mts.map +1 -0
- package/types/dist/lib/builders/builder.d.mts +60 -0
- package/types/dist/lib/builders/builder.d.mts.map +1 -0
- package/types/dist/lib/builders/modes-processor.d.mts +32 -0
- package/types/dist/lib/builders/modes-processor.d.mts.map +1 -0
- package/types/dist/lib/errors.d.mts +118 -0
- package/types/dist/lib/errors.d.mts.map +1 -0
- package/types/dist/lib/factories/component-base.d.mts +182 -0
- package/types/dist/lib/factories/component-base.d.mts.map +1 -0
- package/types/dist/lib/factories/context.d.mts +26 -0
- package/types/dist/lib/factories/context.d.mts.map +1 -0
- package/types/dist/lib/handlers/api-cache-manager.d.mts +208 -0
- package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/api-manager.d.mts +392 -0
- package/types/dist/lib/handlers/api-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/context-async.d.mts +66 -0
- package/types/dist/lib/handlers/context-async.d.mts.map +1 -0
- package/types/dist/lib/handlers/context-live.d.mts +65 -0
- package/types/dist/lib/handlers/context-live.d.mts.map +1 -0
- package/types/dist/lib/handlers/hook-manager.d.mts +199 -0
- package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/lifecycle-token.d.mts +49 -0
- package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -0
- package/types/dist/lib/handlers/lifecycle.d.mts +90 -0
- package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -0
- package/types/dist/lib/handlers/materialize-manager.d.mts +75 -0
- package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/metadata.d.mts +215 -0
- package/types/dist/lib/handlers/metadata.d.mts.map +1 -0
- package/types/dist/lib/handlers/ownership.d.mts +170 -0
- package/types/dist/lib/handlers/ownership.d.mts.map +1 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts +250 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -0
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts +54 -0
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -0
- package/types/dist/lib/helpers/config.d.mts +96 -0
- package/types/dist/lib/helpers/config.d.mts.map +1 -0
- package/types/dist/lib/helpers/eventemitter-context.d.mts +31 -0
- package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -0
- package/types/dist/lib/helpers/hint-detector.d.mts +20 -0
- package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -0
- package/types/dist/lib/helpers/modes-utils.d.mts +35 -0
- package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -0
- package/types/dist/lib/helpers/resolve-from-caller.d.mts +29 -145
- package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
- package/types/dist/lib/helpers/sanitize.d.mts +95 -94
- package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
- package/types/dist/lib/helpers/utilities.d.mts +53 -116
- package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
- package/types/dist/lib/i18n/translations.d.mts +39 -0
- package/types/dist/lib/i18n/translations.d.mts.map +1 -0
- package/types/dist/lib/modes/eager.d.mts +36 -0
- package/types/dist/lib/modes/eager.d.mts.map +1 -0
- package/types/dist/lib/modes/lazy.d.mts +49 -0
- package/types/dist/lib/modes/lazy.d.mts.map +1 -0
- package/types/dist/lib/processors/flatten.d.mts +114 -0
- package/types/dist/lib/processors/flatten.d.mts.map +1 -0
- package/types/dist/lib/processors/loader.d.mts +47 -0
- package/types/dist/lib/processors/loader.d.mts.map +1 -0
- package/types/dist/lib/processors/type-generator.d.mts +19 -0
- package/types/dist/lib/processors/type-generator.d.mts.map +1 -0
- package/types/dist/lib/processors/typescript.d.mts +55 -0
- package/types/dist/lib/processors/typescript.d.mts.map +1 -0
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +47 -42
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-livebindings.d.mts +34 -65
- package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime.d.mts +39 -9
- package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
- package/types/dist/slothlet.d.mts +184 -111
- package/types/dist/slothlet.d.mts.map +1 -1
- package/types/index.d.mts +1 -3
- package/dist/lib/engine/README.md +0 -21
- package/dist/lib/engine/slothlet_child.mjs +0 -59
- package/dist/lib/engine/slothlet_engine.mjs +0 -372
- package/dist/lib/engine/slothlet_esm.mjs +0 -230
- package/dist/lib/engine/slothlet_helpers.mjs +0 -455
- package/dist/lib/engine/slothlet_worker.mjs +0 -149
- package/dist/lib/helpers/als-eventemitter.mjs +0 -256
- package/dist/lib/helpers/api_builder/add_api.mjs +0 -553
- package/dist/lib/helpers/api_builder/analysis.mjs +0 -532
- package/dist/lib/helpers/api_builder/construction.mjs +0 -495
- package/dist/lib/helpers/api_builder/decisions.mjs +0 -748
- package/dist/lib/helpers/api_builder/metadata.mjs +0 -248
- package/dist/lib/helpers/api_builder.mjs +0 -41
- package/dist/lib/helpers/auto-wrap.mjs +0 -62
- package/dist/lib/helpers/hooks.mjs +0 -389
- package/dist/lib/helpers/instance-manager.mjs +0 -111
- package/dist/lib/helpers/metadata-api.mjs +0 -201
- package/dist/lib/helpers/multidefault.mjs +0 -216
- package/dist/lib/modes/slothlet_eager.mjs +0 -154
- package/dist/lib/modes/slothlet_lazy.mjs +0 -594
- package/docs/API-RULES-CONDITIONS.md +0 -712
- package/types/dist/lib/engine/slothlet_child.d.mts +0 -2
- package/types/dist/lib/engine/slothlet_child.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_engine.d.mts +0 -31
- package/types/dist/lib/engine/slothlet_engine.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_esm.d.mts +0 -19
- package/types/dist/lib/engine/slothlet_esm.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_helpers.d.mts +0 -25
- package/types/dist/lib/engine/slothlet_helpers.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_worker.d.mts +0 -2
- package/types/dist/lib/engine/slothlet_worker.d.mts.map +0 -1
- package/types/dist/lib/helpers/als-eventemitter.d.mts +0 -56
- package/types/dist/lib/helpers/als-eventemitter.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/add_api.d.mts +0 -102
- package/types/dist/lib/helpers/api_builder/add_api.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/analysis.d.mts +0 -189
- package/types/dist/lib/helpers/api_builder/analysis.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/construction.d.mts +0 -107
- package/types/dist/lib/helpers/api_builder/construction.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/decisions.d.mts +0 -213
- package/types/dist/lib/helpers/api_builder/decisions.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/metadata.d.mts +0 -99
- package/types/dist/lib/helpers/api_builder/metadata.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder.d.mts +0 -6
- package/types/dist/lib/helpers/api_builder.d.mts.map +0 -1
- package/types/dist/lib/helpers/auto-wrap.d.mts +0 -49
- package/types/dist/lib/helpers/auto-wrap.d.mts.map +0 -1
- package/types/dist/lib/helpers/hooks.d.mts +0 -342
- package/types/dist/lib/helpers/hooks.d.mts.map +0 -1
- package/types/dist/lib/helpers/instance-manager.d.mts +0 -41
- package/types/dist/lib/helpers/instance-manager.d.mts.map +0 -1
- package/types/dist/lib/helpers/metadata-api.d.mts +0 -132
- package/types/dist/lib/helpers/metadata-api.d.mts.map +0 -1
- package/types/dist/lib/helpers/multidefault.d.mts +0 -90
- package/types/dist/lib/helpers/multidefault.d.mts.map +0 -1
- package/types/dist/lib/modes/slothlet_eager.d.mts +0 -65
- package/types/dist/lib/modes/slothlet_eager.d.mts.map +0 -1
- package/types/dist/lib/modes/slothlet_lazy.d.mts +0 -31
- package/types/dist/lib/modes/slothlet_lazy.d.mts.map +0 -1
- package/types/index.d.mts.map +0 -1
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2026 CLDMV/Shinrai
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
import { Worker } from "node:worker_threads";
|
|
20
|
-
import { fork } from "node:child_process";
|
|
21
|
-
import { fileURLToPath } from "node:url";
|
|
22
|
-
import vm from "node:vm";
|
|
23
|
-
import util from "node:util";
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
asUrl,
|
|
27
|
-
|
|
28
|
-
HAS_STM,
|
|
29
|
-
makeNodeishContext,
|
|
30
|
-
installContextGlobalsVM,
|
|
31
|
-
bootSlothletVM,
|
|
32
|
-
|
|
33
|
-
normalizeContext,
|
|
34
|
-
marshalArgsReplaceFunctions
|
|
35
|
-
} from "./slothlet_helpers.mjs";
|
|
36
|
-
|
|
37
|
-
let shutdownFn = null;
|
|
38
|
-
|
|
39
|
-
export function setShutdown(fn) {
|
|
40
|
-
const prev = shutdownFn;
|
|
41
|
-
shutdownFn = fn;
|
|
42
|
-
return prev;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
export async function createEngine(allOptions) {
|
|
47
|
-
const { entry, mode = "vm" } = allOptions ?? {};
|
|
48
|
-
if (!entry) throw new Error('createEngine: "entry" is required');
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const { context = null, reference = null, ...loadConfig } = allOptions;
|
|
52
|
-
|
|
53
|
-
if (mode === "vm") {
|
|
54
|
-
if (!HAS_STM) {
|
|
55
|
-
|
|
56
|
-
return backendWorker(entry, loadConfig, { context, reference });
|
|
57
|
-
}
|
|
58
|
-
return backendVm(entry, loadConfig, { context, reference });
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (mode === "worker") {
|
|
62
|
-
return backendWorker(entry, loadConfig, { context, reference });
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (mode === "fork" || mode === "child") {
|
|
66
|
-
return backendFork(entry, loadConfig, { context, reference });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
throw new Error(`Unknown mode "${mode}" (use "vm" | "worker" | "fork")`);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
async function backendVm(entry, loadConfig, ctxRef) {
|
|
74
|
-
const context = makeNodeishContext();
|
|
75
|
-
installContextGlobalsVM(context, ctxRef.context);
|
|
76
|
-
await bootSlothletVM(context, asUrl(entry), loadConfig, ctxRef);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
await vm.runInContext("slothletReady", context, { filename: "slothlet_engine-backendVm.mjs" });
|
|
84
|
-
const portal = vm.runInContext("_portal", context, { filename: "slothlet_engine-backendVm.mjs" });
|
|
85
|
-
|
|
86
|
-
const api = makeFacade({
|
|
87
|
-
call: (path, args) => Promise.resolve(portal.call(path, args)),
|
|
88
|
-
batch: (ops) => Promise.resolve(portal.batch(ops))
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const dispose = async () => {};
|
|
92
|
-
Object.defineProperty(api, "__dispose__", {
|
|
93
|
-
value: dispose,
|
|
94
|
-
writable: false,
|
|
95
|
-
enumerable: false,
|
|
96
|
-
configurable: false
|
|
97
|
-
});
|
|
98
|
-
return { api, dispose };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
async function backendWorker(entry, loadConfig, ctxRef) {
|
|
103
|
-
const workerPath = new URL("./slothlet_worker.mjs", import.meta.url);
|
|
104
|
-
let nextId = 1;
|
|
105
|
-
const pending = new Map();
|
|
106
|
-
|
|
107
|
-
let cbId = 1;
|
|
108
|
-
const callbacks = new Map();
|
|
109
|
-
|
|
110
|
-
const w = new Worker(workerPath, {
|
|
111
|
-
workerData: {
|
|
112
|
-
entry: asUrl(entry),
|
|
113
|
-
loadConfig,
|
|
114
|
-
|
|
115
|
-
contextMap: normalizeContext(ctxRef.context),
|
|
116
|
-
reference: ctxRef.reference ?? null
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
w.on("message", (msg) => {
|
|
121
|
-
|
|
122
|
-
if (msg && msg.t === "callback" && typeof msg.cb === "number") {
|
|
123
|
-
const fn = callbacks.get(msg.cb);
|
|
124
|
-
if (!fn) {
|
|
125
|
-
w.postMessage({ t: "callbackResult", cb: msg.cb, ok: false, error: "Callback not found" });
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
Promise.resolve()
|
|
129
|
-
.then(() => fn(...(msg.args ?? [])))
|
|
130
|
-
.then((result) => {
|
|
131
|
-
w.postMessage({ t: "callbackResult", cb: msg.cb, ok: true, result });
|
|
132
|
-
})
|
|
133
|
-
.catch((error) => {
|
|
134
|
-
w.postMessage({ t: "callbackResult", cb: msg.cb, ok: false, error: error?.message || String(error) });
|
|
135
|
-
});
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const { id, ok, result, error } = msg;
|
|
140
|
-
const rec = pending.get(id);
|
|
141
|
-
if (!rec) return;
|
|
142
|
-
pending.delete(id);
|
|
143
|
-
ok ? rec.resolve(result) : rec.reject(new Error(error));
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
function registerCb(fn) {
|
|
148
|
-
const id = cbId++;
|
|
149
|
-
callbacks.set(id, fn);
|
|
150
|
-
return id;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
function marshalArgs(args) {
|
|
155
|
-
return marshalArgsReplaceFunctions(args, registerCb);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const rpc = (msg) =>
|
|
159
|
-
new Promise((resolve, reject) => {
|
|
160
|
-
const id = nextId++;
|
|
161
|
-
pending.set(id, { resolve, reject });
|
|
162
|
-
let message = { id, ...msg };
|
|
163
|
-
|
|
164
|
-
if (Array.isArray(message.args)) {
|
|
165
|
-
message = { ...message, args: marshalArgs(message.args) };
|
|
166
|
-
}
|
|
167
|
-
w.postMessage(message);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
const api = makeFacade({
|
|
171
|
-
call: (path, args) => rpc({ t: "call", path, args }),
|
|
172
|
-
batch: (ops) => rpc({ t: "batch", ops })
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const dispose = async () => {
|
|
176
|
-
await rpc({ t: "dispose" });
|
|
177
|
-
await w.terminate();
|
|
178
|
-
};
|
|
179
|
-
Object.defineProperty(api, "__dispose__", {
|
|
180
|
-
value: dispose,
|
|
181
|
-
writable: false,
|
|
182
|
-
enumerable: false,
|
|
183
|
-
configurable: false
|
|
184
|
-
});
|
|
185
|
-
return { api, dispose };
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
async function backendFork(entry, loadConfig, ctxRef) {
|
|
190
|
-
const childPath = fileURLToPath(new URL("./slothlet_child.mjs", import.meta.url));
|
|
191
|
-
let nextId = 1;
|
|
192
|
-
const pending = new Map();
|
|
193
|
-
|
|
194
|
-
const cp = fork(childPath, [], { stdio: ["inherit", "inherit", "inherit", "ipc"] });
|
|
195
|
-
|
|
196
|
-
cp.on("message", ({ id, ok, result, error }) => {
|
|
197
|
-
const rec = pending.get(id);
|
|
198
|
-
if (!rec) return;
|
|
199
|
-
pending.delete(id);
|
|
200
|
-
ok ? rec.resolve(result) : rec.reject(new Error(error));
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
const rpc = (msg) =>
|
|
204
|
-
new Promise((resolve, reject) => {
|
|
205
|
-
const id = nextId++;
|
|
206
|
-
pending.set(id, { resolve, reject });
|
|
207
|
-
cp.send({ id, ...msg });
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
await rpc({
|
|
211
|
-
t: "init",
|
|
212
|
-
entry: asUrl(entry),
|
|
213
|
-
loadConfig,
|
|
214
|
-
contextMap: normalizeContext(ctxRef.context),
|
|
215
|
-
reference: ctxRef.reference ?? null
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
const api = makeFacade({
|
|
219
|
-
call: (path, args) => rpc({ t: "call", path, args }),
|
|
220
|
-
batch: (ops) => rpc({ t: "batch", ops })
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
const dispose = async () => {
|
|
224
|
-
await rpc({ t: "dispose" });
|
|
225
|
-
};
|
|
226
|
-
Object.defineProperty(api, "__dispose__", {
|
|
227
|
-
value: dispose,
|
|
228
|
-
writable: false,
|
|
229
|
-
enumerable: false,
|
|
230
|
-
configurable: false
|
|
231
|
-
});
|
|
232
|
-
return { api, dispose };
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function makeFn(name) {
|
|
236
|
-
const fn = function () {
|
|
237
|
-
throw new Error("cross-thread stubs are not callable");
|
|
238
|
-
};
|
|
239
|
-
try {
|
|
240
|
-
Object.defineProperty(fn, "name", { value: name || "", configurable: true });
|
|
241
|
-
} catch {
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
return fn;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
function revive(x) {
|
|
248
|
-
if (x && typeof x === "object") {
|
|
249
|
-
if ("__fn" in x) {
|
|
250
|
-
|
|
251
|
-
const fn = makeFn(x.__fn);
|
|
252
|
-
const props = x.props || {};
|
|
253
|
-
for (const [k, v] of Object.entries(props)) fn[k] = revive(v);
|
|
254
|
-
return fn;
|
|
255
|
-
}
|
|
256
|
-
if (Array.isArray(x)) return x.map(revive);
|
|
257
|
-
const out = {};
|
|
258
|
-
for (const [k, v] of Object.entries(x)) out[k] = revive(v);
|
|
259
|
-
return out;
|
|
260
|
-
}
|
|
261
|
-
return x;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
function makeFacade(portal) {
|
|
266
|
-
const build = (segs = []) => {
|
|
267
|
-
const proxy = new Proxy(function () {}, {
|
|
268
|
-
get: (_, prop) => {
|
|
269
|
-
if (prop === "then") return undefined;
|
|
270
|
-
if (prop === "describe") {
|
|
271
|
-
|
|
272
|
-
return async () => {
|
|
273
|
-
const result = await portal.call(["describe"], []);
|
|
274
|
-
try {
|
|
275
|
-
|
|
276
|
-
return revive(result);
|
|
277
|
-
|
|
278
|
-
} catch {
|
|
279
|
-
return result;
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
return build(segs.concat(String(prop)));
|
|
284
|
-
},
|
|
285
|
-
apply: (_, __, args) => portal.call(segs, args)
|
|
286
|
-
});
|
|
287
|
-
return proxy;
|
|
288
|
-
};
|
|
289
|
-
return build([]);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function buildCallableFromDescribe(node, portal, path = []) {
|
|
293
|
-
|
|
294
|
-
const isFnBox = node && typeof node === "object" && (node.__fn != null || node.__kind === "fn" || (node.name && node.props));
|
|
295
|
-
|
|
296
|
-
if (isFnBox) {
|
|
297
|
-
const name = node.__fn ?? node.name ?? "";
|
|
298
|
-
const props = node.props ?? {};
|
|
299
|
-
|
|
300
|
-
const children = {};
|
|
301
|
-
for (const [k, v] of Object.entries(props)) {
|
|
302
|
-
children[k] = buildCallableFromDescribe(v, portal, path.concat(String(k)));
|
|
303
|
-
}
|
|
304
|
-
const label = `[Function${name ? `: ${name}` : ""}]`;
|
|
305
|
-
|
|
306
|
-
return new Proxy(function () {}, {
|
|
307
|
-
apply: (_t, _thisArg, args) => portal.call(path, args),
|
|
308
|
-
|
|
309
|
-
get: (_t, prop) => {
|
|
310
|
-
if (prop === "name") return name;
|
|
311
|
-
if (typeof util !== "undefined" && prop === util?.inspect?.custom) {
|
|
312
|
-
return function (_depth, opts, inspect = util.inspect) {
|
|
313
|
-
const head = opts?.colors ? opts.stylize(label, "special") : label;
|
|
314
|
-
const keys = Object.keys(children);
|
|
315
|
-
if (!keys.length) return head;
|
|
316
|
-
const body = keys.map((k) => `${k}: ${inspect(children[k], { ...opts, depth: (opts?.depth ?? 2) - 1 })}`).join(", ");
|
|
317
|
-
return `${head} { ${body} }`;
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
if (prop in children) return children[prop];
|
|
321
|
-
|
|
322
|
-
return buildCallableFromDescribe({ __fn: String(prop), props: {} }, portal, path.concat(String(prop)));
|
|
323
|
-
},
|
|
324
|
-
|
|
325
|
-
ownKeys: () => Object.keys(children),
|
|
326
|
-
getOwnPropertyDescriptor: (_t, key) =>
|
|
327
|
-
key in children ? { enumerable: true, configurable: true, writable: true, value: children[key] } : undefined
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (node && typeof node === "object") {
|
|
332
|
-
if (Array.isArray(node)) {
|
|
333
|
-
return node.map((v, i) => buildCallableFromDescribe(v, portal, path.concat(String(i))));
|
|
334
|
-
}
|
|
335
|
-
const out = {};
|
|
336
|
-
for (const [k, v] of Object.entries(node)) {
|
|
337
|
-
out[k] = buildCallableFromDescribe(v, portal, path.concat(String(k)));
|
|
338
|
-
}
|
|
339
|
-
return out;
|
|
340
|
-
}
|
|
341
|
-
return node;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
export function makeFacade2(portal) {
|
|
345
|
-
const build = (segs = []) => {
|
|
346
|
-
const describe = async () => {
|
|
347
|
-
const shape = await portal.call(["describe"], []);
|
|
348
|
-
return buildCallableFromDescribe(shape, portal, []);
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
return new Proxy(function () {}, {
|
|
352
|
-
get: (_t, prop) => {
|
|
353
|
-
|
|
354
|
-
if (prop === "then") {
|
|
355
|
-
if (segs.length === 0) {
|
|
356
|
-
return (resolve, reject) => {
|
|
357
|
-
Promise.resolve().then(describe).then(resolve, reject);
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
return undefined;
|
|
361
|
-
}
|
|
362
|
-
if (prop === "describe") return describe;
|
|
363
|
-
|
|
364
|
-
return build(segs.concat(String(prop)));
|
|
365
|
-
},
|
|
366
|
-
|
|
367
|
-
apply: (_t, _thisArg, args) => portal.call(segs, args)
|
|
368
|
-
});
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
return build([]);
|
|
372
|
-
}
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2026 CLDMV/Shinrai
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
import fs from "node:fs/promises";
|
|
20
|
-
import path from "node:path";
|
|
21
|
-
import { fileURLToPath } from "node:url";
|
|
22
|
-
import { builtinModules } from "module";
|
|
23
|
-
const builtins = new Set(builtinModules);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export async function loadEsmModuleFallback(context, fileUrl, visited = new Set()) {
|
|
27
|
-
|
|
28
|
-
if (typeof context.fileURLToPath !== "function") {
|
|
29
|
-
const { fileURLToPath } = await import("node:url");
|
|
30
|
-
context.fileURLToPath = fileURLToPath;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
context.import = async (specifier) => import(specifier);
|
|
34
|
-
|
|
35
|
-
let specToCheck = fileUrl;
|
|
36
|
-
if (specToCheck.startsWith("node:")) specToCheck = specToCheck.slice(5);
|
|
37
|
-
if (!fileUrl.startsWith("file:")) {
|
|
38
|
-
if (builtins.has(specToCheck) || /^[\w@][\w\-/]*$/.test(specToCheck)) {
|
|
39
|
-
return await import(fileUrl);
|
|
40
|
-
}
|
|
41
|
-
throw new Error(`Unsupported import specifier: ${fileUrl}`);
|
|
42
|
-
}
|
|
43
|
-
if (visited.has(fileUrl)) return context[fileUrl];
|
|
44
|
-
visited.add(fileUrl);
|
|
45
|
-
let code = await fs.readFile(fileURLToPath(fileUrl), "utf8");
|
|
46
|
-
|
|
47
|
-
const commentRanges = [];
|
|
48
|
-
const blockCommentRegex = /\/\*[\s\S]*?\*\
|
|
49
|
-
const lineCommentRegex = /(^|[^:])\/\/.*$/gm;
|
|
50
|
-
let blockMatch;
|
|
51
|
-
while ((blockMatch = blockCommentRegex.exec(code))) {
|
|
52
|
-
commentRanges.push([blockMatch.index, blockCommentRegex.lastIndex]);
|
|
53
|
-
}
|
|
54
|
-
let lineMatch;
|
|
55
|
-
while ((lineMatch = lineCommentRegex.exec(code))) {
|
|
56
|
-
let start = lineMatch.index + (lineMatch[1] ? lineMatch[1].length : 0);
|
|
57
|
-
let end = code.indexOf("\n", lineMatch.index);
|
|
58
|
-
if (end === -1) end = code.length;
|
|
59
|
-
commentRanges.push([start, end]);
|
|
60
|
-
}
|
|
61
|
-
function inComment(idx) {
|
|
62
|
-
return commentRanges.some(([start, end]) => idx >= start && idx < end);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const importRegex = /import\s+(?:([\w{}*, ]+)\s+from\s+)?["'](.+?)["'];?/g;
|
|
66
|
-
let match;
|
|
67
|
-
const imports = [];
|
|
68
|
-
while ((match = importRegex.exec(code))) {
|
|
69
|
-
if (!inComment(match.index)) {
|
|
70
|
-
imports.push({ spec: match[2], names: match[1] });
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
for (const imp of imports) {
|
|
75
|
-
if (!imp.names) continue;
|
|
76
|
-
let mod;
|
|
77
|
-
|
|
78
|
-
if (imp.spec.startsWith("./") || imp.spec.startsWith("../")) {
|
|
79
|
-
const resolvedUrl = new URL(imp.spec, fileUrl).href;
|
|
80
|
-
mod = await loadEsmModuleFallback(context, resolvedUrl, visited);
|
|
81
|
-
} else {
|
|
82
|
-
mod = await import(imp.spec);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const importStr = imp.names.trim();
|
|
86
|
-
if (importStr.startsWith("* as ")) {
|
|
87
|
-
|
|
88
|
-
const nsName = importStr.slice(5).trim();
|
|
89
|
-
context[nsName] = mod;
|
|
90
|
-
} else if (importStr.startsWith("{")) {
|
|
91
|
-
|
|
92
|
-
let fields = importStr
|
|
93
|
-
.slice(1, -1)
|
|
94
|
-
.split(",")
|
|
95
|
-
.map((f) => f.trim())
|
|
96
|
-
.filter(Boolean);
|
|
97
|
-
for (let field of fields) {
|
|
98
|
-
let [orig, alias] = field.split(" as ").map((x) => x.trim());
|
|
99
|
-
context[alias || orig] = mod[orig];
|
|
100
|
-
}
|
|
101
|
-
} else if (importStr) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
let parts = importStr
|
|
105
|
-
.split(/,(.+)/)
|
|
106
|
-
.map((s) => s.trim())
|
|
107
|
-
.filter(Boolean);
|
|
108
|
-
if (parts.length) {
|
|
109
|
-
const defaultName = parts[0];
|
|
110
|
-
context[defaultName] = mod.default || mod[defaultName];
|
|
111
|
-
if (parts[1] && parts[1].startsWith("{")) {
|
|
112
|
-
let fields = parts[1]
|
|
113
|
-
.slice(1, -1)
|
|
114
|
-
.split(",")
|
|
115
|
-
.map((f) => f.trim())
|
|
116
|
-
.filter(Boolean);
|
|
117
|
-
for (let field of fields) {
|
|
118
|
-
let [orig, alias] = field.split(" as ").map((x) => x.trim());
|
|
119
|
-
context[alias || orig] = mod[orig];
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const dependencies = {};
|
|
126
|
-
for (const imp of imports) {
|
|
127
|
-
let specToCheck = imp.spec;
|
|
128
|
-
if (specToCheck.startsWith("node:")) specToCheck = specToCheck.slice(5);
|
|
129
|
-
if (builtins.has(specToCheck) || /^[\w@][\w\-/]*$/.test(specToCheck)) {
|
|
130
|
-
dependencies[imp.spec] = await import(imp.spec);
|
|
131
|
-
} else if (imp.spec.startsWith("file:")) {
|
|
132
|
-
const childUrl = new URL(imp.spec, fileUrl).href;
|
|
133
|
-
dependencies[imp.spec] = await loadEsmModuleFallback(context, childUrl, visited);
|
|
134
|
-
} else {
|
|
135
|
-
|
|
136
|
-
const childUrl = new URL(imp.spec, fileUrl).href;
|
|
137
|
-
if (!childUrl.startsWith("file:")) {
|
|
138
|
-
throw new Error(`Unsupported import specifier: ${imp.spec}`);
|
|
139
|
-
}
|
|
140
|
-
dependencies[imp.spec] = await loadEsmModuleFallback(context, childUrl, visited);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
let evalCode = code
|
|
145
|
-
|
|
146
|
-
.replace(/import\s+[^;]*?;\s*/gs, "")
|
|
147
|
-
|
|
148
|
-
.replace(/import\s+type\s+[^;]*?;\s*/gs, "")
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
.replace(/export\s+default\s+([\w$]+)/g, "")
|
|
152
|
-
|
|
153
|
-
.replace(/export\s+(const|let|var|function|class)\s+([\w$]+)/g, "$1 $2")
|
|
154
|
-
|
|
155
|
-
.replace(/export\s+(default\s+)?/g, "")
|
|
156
|
-
|
|
157
|
-
.replace(/import\.meta\.url/g, JSON.stringify(fileUrl));
|
|
158
|
-
|
|
159
|
-
const localDefRegex = /(const|let|var|function|class)\s+([\w$]+)/g;
|
|
160
|
-
let localDefs = new Set();
|
|
161
|
-
let defMatch;
|
|
162
|
-
while ((defMatch = localDefRegex.exec(code))) {
|
|
163
|
-
if (!inComment(defMatch.index)) {
|
|
164
|
-
localDefs.add(defMatch[2]);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const namedExportRegex = /export\s+(const|let|var|function|class)\s+([\w$]+)/g;
|
|
169
|
-
let namedExports = [];
|
|
170
|
-
let namedMatch;
|
|
171
|
-
while ((namedMatch = namedExportRegex.exec(code))) {
|
|
172
|
-
if (!inComment(namedMatch.index) && localDefs.has(namedMatch[2])) {
|
|
173
|
-
namedExports.push(namedMatch[2]);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
let exportDefaultMatch = null;
|
|
178
|
-
const exportDefaultRegex = /export\s+default\s+([\w$]+)/g;
|
|
179
|
-
let exportDefaultMatchRaw;
|
|
180
|
-
while ((exportDefaultMatchRaw = exportDefaultRegex.exec(code))) {
|
|
181
|
-
if (!inComment(exportDefaultMatchRaw.index)) {
|
|
182
|
-
exportDefaultMatch = exportDefaultMatchRaw;
|
|
183
|
-
break;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (!context.__dynamicImport) {
|
|
187
|
-
|
|
188
|
-
for (const name of namedExports) {
|
|
189
|
-
evalCode += `\nglobalThis["${name}"] = ${name};`;
|
|
190
|
-
}
|
|
191
|
-
if (exportDefaultMatch) {
|
|
192
|
-
evalCode += `\nglobalThis["default"] = ${exportDefaultMatch[1]};`;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
for (const [spec, ns] of Object.entries(dependencies)) {
|
|
197
|
-
const modName = path.basename(spec, path.extname(spec));
|
|
198
|
-
context[modName] = ns;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const vm = await import("node:vm");
|
|
202
|
-
const script = new vm.Script(evalCode, {
|
|
203
|
-
filename: fileUrl,
|
|
204
|
-
importModuleDynamically: async (specifier) => import(specifier)
|
|
205
|
-
});
|
|
206
|
-
script.runInContext(context);
|
|
207
|
-
|
|
208
|
-
const namespace = {};
|
|
209
|
-
for (const k of Object.keys(context)) {
|
|
210
|
-
if (k !== "globalThis" && k !== "global") {
|
|
211
|
-
namespace[k] = context[k];
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
context[fileUrl] = namespace;
|
|
215
|
-
return { namespace };
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
export async function isEsmFile(fileUrl) {
|
|
220
|
-
const ext = path.extname(fileURLToPath(fileUrl)).toLowerCase();
|
|
221
|
-
if (ext === ".mjs") return true;
|
|
222
|
-
if (ext === ".cjs") return false;
|
|
223
|
-
if (ext === ".js") {
|
|
224
|
-
const code = await fs.readFile(fileURLToPath(fileUrl), "utf8");
|
|
225
|
-
return /\bimport\b/.test(code);
|
|
226
|
-
}
|
|
227
|
-
return false;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
|