@ai-ecoverse/slicc-kernel 1.80.0 → 1.82.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/index.js +44 -3
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +264 -41
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +20 -9
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +227 -37
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +20 -9
- package/dist/process-worker.js.map +2 -2
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -570,6 +570,7 @@ function id(value) {
|
|
|
570
570
|
return value;
|
|
571
571
|
}
|
|
572
572
|
function changeCred(cur, change) {
|
|
573
|
+
if (typeof change !== "object" || change === null) throw fsError("EINVAL", "not a change");
|
|
573
574
|
const privileged = cur.euid === 0;
|
|
574
575
|
const next2 = copyCred(cur);
|
|
575
576
|
for (const keys of [UIDS, GIDS]) {
|
|
@@ -3032,6 +3033,97 @@ var MemoryMeta = class {
|
|
|
3032
3033
|
}
|
|
3033
3034
|
};
|
|
3034
3035
|
|
|
3036
|
+
// src/fs/integrity.ts
|
|
3037
|
+
var KERNEL_CALLER = { pid: 0, uid: 0 };
|
|
3038
|
+
function integrityOptions(options) {
|
|
3039
|
+
if (options && typeof options.lookup !== "function") {
|
|
3040
|
+
throw new TypeError("protect.integrity.lookup must be a function");
|
|
3041
|
+
}
|
|
3042
|
+
integrityUnknown(options);
|
|
3043
|
+
}
|
|
3044
|
+
function integrityUnknown(options) {
|
|
3045
|
+
const unknown = options?.unknown ?? "allow";
|
|
3046
|
+
if (unknown !== "allow" && unknown !== "deny") {
|
|
3047
|
+
throw new TypeError("protect.integrity.unknown must be 'allow' or 'deny'");
|
|
3048
|
+
}
|
|
3049
|
+
return unknown;
|
|
3050
|
+
}
|
|
3051
|
+
function hex(digest) {
|
|
3052
|
+
return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3053
|
+
}
|
|
3054
|
+
async function sha256(bytes) {
|
|
3055
|
+
return hex(await crypto.subtle.digest("SHA-256", bytes));
|
|
3056
|
+
}
|
|
3057
|
+
var Integrity = class {
|
|
3058
|
+
prefixes;
|
|
3059
|
+
root;
|
|
3060
|
+
lookup;
|
|
3061
|
+
unknown;
|
|
3062
|
+
report;
|
|
3063
|
+
unverified = /* @__PURE__ */ new Set();
|
|
3064
|
+
constructor(prefixes2, root, options, report) {
|
|
3065
|
+
this.prefixes = prefixes2;
|
|
3066
|
+
this.root = root;
|
|
3067
|
+
this.lookup = options.lookup;
|
|
3068
|
+
this.unknown = integrityUnknown(options);
|
|
3069
|
+
this.report = report;
|
|
3070
|
+
}
|
|
3071
|
+
async real(path) {
|
|
3072
|
+
const at = normalizePath(path);
|
|
3073
|
+
const real = await this.root.realpath?.(at, true).catch(() => void 0) ?? at;
|
|
3074
|
+
return isProtected(this.prefixes, real) ? real : void 0;
|
|
3075
|
+
}
|
|
3076
|
+
async key(path) {
|
|
3077
|
+
const real = await this.real(path);
|
|
3078
|
+
if (real === void 0 || !this.root.version) return void 0;
|
|
3079
|
+
return `${real}\0${await this.root.version(real)}`;
|
|
3080
|
+
}
|
|
3081
|
+
async read(path, caller, plain) {
|
|
3082
|
+
return (await this.readKeyed(path, caller, plain)).bytes;
|
|
3083
|
+
}
|
|
3084
|
+
async readKeyed(path, caller, plain) {
|
|
3085
|
+
const real = await this.real(path);
|
|
3086
|
+
if (real === void 0) return { bytes: await plain() };
|
|
3087
|
+
const read = this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
|
|
3088
|
+
const { bytes } = read;
|
|
3089
|
+
const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
|
|
3090
|
+
const actual = await sha256(bytes);
|
|
3091
|
+
const denial = { pid: caller.pid, uid: caller.uid, path: real, actual };
|
|
3092
|
+
const tagged = caller.tag !== void 0 ? { tag: caller.tag } : {};
|
|
3093
|
+
let expected;
|
|
3094
|
+
try {
|
|
3095
|
+
expected = await this.expected(real);
|
|
3096
|
+
} catch {
|
|
3097
|
+
this.say({ ...denial, ...tagged, op: "exec-integrity", errno: "EACCES" });
|
|
3098
|
+
throw fsError("EACCES", `integrity lookup failed: ${real}`);
|
|
3099
|
+
}
|
|
3100
|
+
if (expected === void 0) {
|
|
3101
|
+
if (this.unknown === "allow") {
|
|
3102
|
+
if (!this.unverified.has(real)) {
|
|
3103
|
+
this.unverified.add(real);
|
|
3104
|
+
this.say({ ...denial, ...tagged, op: "exec-unverified", errno: "ENODATA" });
|
|
3105
|
+
}
|
|
3106
|
+
return keyed;
|
|
3107
|
+
}
|
|
3108
|
+
} else if (expected === actual) {
|
|
3109
|
+
return keyed;
|
|
3110
|
+
}
|
|
3111
|
+
const known = expected !== void 0 ? { expected } : {};
|
|
3112
|
+
this.say({ ...denial, ...tagged, ...known, op: "exec-integrity", errno: "EACCES" });
|
|
3113
|
+
throw fsError("EACCES", `integrity check failed: ${real}`);
|
|
3114
|
+
}
|
|
3115
|
+
async expected(path) {
|
|
3116
|
+
const answer = await this.lookup(path);
|
|
3117
|
+
return typeof answer === "string" ? answer.toLowerCase() : void 0;
|
|
3118
|
+
}
|
|
3119
|
+
say(event) {
|
|
3120
|
+
try {
|
|
3121
|
+
this.report(event);
|
|
3122
|
+
} catch {
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
};
|
|
3126
|
+
|
|
3035
3127
|
// src/fs/protect.ts
|
|
3036
3128
|
function writerTags(protection) {
|
|
3037
3129
|
const writers = protection?.writers ?? [];
|
|
@@ -3884,6 +3976,29 @@ var OpfsFs = class {
|
|
|
3884
3976
|
false
|
|
3885
3977
|
);
|
|
3886
3978
|
}
|
|
3979
|
+
async readVersioned(path) {
|
|
3980
|
+
const handle = await this.existing(path);
|
|
3981
|
+
return this.retrying(
|
|
3982
|
+
path,
|
|
3983
|
+
async () => {
|
|
3984
|
+
const file = await handle.getFile();
|
|
3985
|
+
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
3986
|
+
return { bytes, version: `${file.lastModified}:${file.size}` };
|
|
3987
|
+
},
|
|
3988
|
+
false
|
|
3989
|
+
);
|
|
3990
|
+
}
|
|
3991
|
+
async version(path) {
|
|
3992
|
+
const handle = await this.existing(path);
|
|
3993
|
+
return this.retrying(
|
|
3994
|
+
path,
|
|
3995
|
+
async () => {
|
|
3996
|
+
const file = await handle.getFile();
|
|
3997
|
+
return `${file.lastModified}:${file.size}`;
|
|
3998
|
+
},
|
|
3999
|
+
false
|
|
4000
|
+
);
|
|
4001
|
+
}
|
|
3887
4002
|
async pread(path, offset, length2) {
|
|
3888
4003
|
const handle = await this.existing(path);
|
|
3889
4004
|
return this.retrying(
|
|
@@ -5538,7 +5653,7 @@ function owned(path, st) {
|
|
|
5538
5653
|
function unchanged(a, b, bytes) {
|
|
5539
5654
|
return a.ino === b.ino && a.mtime.getTime() === b.mtime.getTime() && a.size === b.size && bytes.length === b.size;
|
|
5540
5655
|
}
|
|
5541
|
-
async function
|
|
5656
|
+
async function sha2562(bytes) {
|
|
5542
5657
|
const digest = new Uint8Array(
|
|
5543
5658
|
await crypto.subtle.digest("SHA-256", bytes)
|
|
5544
5659
|
);
|
|
@@ -5594,7 +5709,7 @@ async function attest(fs, asked, o) {
|
|
|
5594
5709
|
const bytes = (await fs.readFileBuffer(path)).slice();
|
|
5595
5710
|
const after = await fs.lstat(path);
|
|
5596
5711
|
if (unchanged(before, after, bytes)) {
|
|
5597
|
-
return attested(path, after, bytes, await
|
|
5712
|
+
return attested(path, after, bytes, await sha2562(bytes), o, parents);
|
|
5598
5713
|
}
|
|
5599
5714
|
if (tries >= 1) refuse("EAGAIN", path, "changed while it was read");
|
|
5600
5715
|
}
|
|
@@ -16294,6 +16409,13 @@ var Launcher = class {
|
|
|
16294
16409
|
unwatchScopes = () => void 0;
|
|
16295
16410
|
warned = /* @__PURE__ */ new Set();
|
|
16296
16411
|
compiled = /* @__PURE__ */ new Map();
|
|
16412
|
+
texts = /* @__PURE__ */ new Map();
|
|
16413
|
+
integrity;
|
|
16414
|
+
scannedFs;
|
|
16415
|
+
get scanned() {
|
|
16416
|
+
this.scannedFs ??= this.verifiedFs(this.base);
|
|
16417
|
+
return this.scannedFs;
|
|
16418
|
+
}
|
|
16297
16419
|
processes = /* @__PURE__ */ new Map();
|
|
16298
16420
|
zombies = /* @__PURE__ */ new Set();
|
|
16299
16421
|
orphans = /* @__PURE__ */ new Set();
|
|
@@ -16397,7 +16519,7 @@ var Launcher = class {
|
|
|
16397
16519
|
if (options.uplink) this.net.useUplink({ uplink: options.uplink, routes: this.routes });
|
|
16398
16520
|
enableNetwork(this.net, {
|
|
16399
16521
|
transport: this.transport,
|
|
16400
|
-
engine: kernelTlsEngine(packageTlsEngine(options.fs, this.modulesDir)),
|
|
16522
|
+
engine: kernelTlsEngine(packageTlsEngine(this.verifiedFs(options.fs), this.modulesDir)),
|
|
16401
16523
|
ca: this.ca
|
|
16402
16524
|
});
|
|
16403
16525
|
enableCdp(this.net, this.cdp);
|
|
@@ -16432,6 +16554,16 @@ var Launcher = class {
|
|
|
16432
16554
|
this.prefixes = protectedPrefixes(options.protect?.paths ?? []);
|
|
16433
16555
|
this.processFs = this.prefixes.length > 0 ? new ProtectedFs(this.prefixes).view(this.fs) : this.fs;
|
|
16434
16556
|
options.fs.protect?.(this.prefixes);
|
|
16557
|
+
const integrity = options.protect?.integrity;
|
|
16558
|
+
integrityOptions(integrity);
|
|
16559
|
+
if (integrity && this.prefixes.length > 0) {
|
|
16560
|
+
this.integrity = new Integrity(
|
|
16561
|
+
this.prefixes,
|
|
16562
|
+
options.fs,
|
|
16563
|
+
integrity,
|
|
16564
|
+
(event) => options.onDenial?.(event)
|
|
16565
|
+
);
|
|
16566
|
+
}
|
|
16435
16567
|
this.users = new UserDb(this.fs, this.owners);
|
|
16436
16568
|
this.sudoer = new Sudo({
|
|
16437
16569
|
fs: this.fs,
|
|
@@ -16477,7 +16609,7 @@ var Launcher = class {
|
|
|
16477
16609
|
commands(scope = "") {
|
|
16478
16610
|
let found = this.catalogs.get(scope);
|
|
16479
16611
|
if (!found) {
|
|
16480
|
-
found = this.roots(scope).then((roots) => scanCommands(this.
|
|
16612
|
+
found = this.roots(scope).then((roots) => scanCommands(this.scanned, roots)).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
16481
16613
|
this.catalogs.set(scope, found);
|
|
16482
16614
|
}
|
|
16483
16615
|
return found;
|
|
@@ -16485,7 +16617,7 @@ var Launcher = class {
|
|
|
16485
16617
|
ownCommands(scope) {
|
|
16486
16618
|
let found = this.ownCatalogs.get(scope);
|
|
16487
16619
|
if (!found) {
|
|
16488
|
-
found = pnpmGlobalRoots(this.base, scope).then((roots) => scanCommands(this.
|
|
16620
|
+
found = pnpmGlobalRoots(this.base, scope).then((roots) => scanCommands(this.scanned, roots)).then((commands) => new Set(commands.keys()));
|
|
16489
16621
|
this.ownCatalogs.set(scope, found);
|
|
16490
16622
|
}
|
|
16491
16623
|
return found;
|
|
@@ -16494,7 +16626,7 @@ var Launcher = class {
|
|
|
16494
16626
|
let found = this.binfmts.get(scope);
|
|
16495
16627
|
if (!found) {
|
|
16496
16628
|
found = this.roots(scope).then(
|
|
16497
|
-
(roots) => scanBinfmts(this.
|
|
16629
|
+
(roots) => scanBinfmts(this.scanned, roots, (message3) => {
|
|
16498
16630
|
if (this.warned.has(message3)) return;
|
|
16499
16631
|
this.warned.add(message3);
|
|
16500
16632
|
console.warn(message3);
|
|
@@ -16613,10 +16745,16 @@ var Launcher = class {
|
|
|
16613
16745
|
}
|
|
16614
16746
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
16615
16747
|
const via = [interp, ...inner?.via ?? []];
|
|
16616
|
-
|
|
16748
|
+
const sources = [script, ...inner?.sources ?? []];
|
|
16749
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command), via, sources };
|
|
16617
16750
|
}
|
|
16618
16751
|
const target = withScriptEnv(found, command);
|
|
16619
|
-
return {
|
|
16752
|
+
return {
|
|
16753
|
+
target,
|
|
16754
|
+
args: [...target.prefix ?? [], ...passed],
|
|
16755
|
+
via: [interp],
|
|
16756
|
+
sources: [script]
|
|
16757
|
+
};
|
|
16620
16758
|
}
|
|
16621
16759
|
async plan(file, argv, cwd, scope, argv0) {
|
|
16622
16760
|
const found = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
@@ -16648,7 +16786,7 @@ var Launcher = class {
|
|
|
16648
16786
|
}
|
|
16649
16787
|
async binfmtManifests(scripts) {
|
|
16650
16788
|
const sources = /* @__PURE__ */ new Map();
|
|
16651
|
-
const binfmts = await scanBinfmts(this.
|
|
16789
|
+
const binfmts = await scanBinfmts(this.scanned, await this.roots(), void 0, sources);
|
|
16652
16790
|
const manifests = [];
|
|
16653
16791
|
for (const script of scripts) {
|
|
16654
16792
|
const head = await this.head(script);
|
|
@@ -16683,25 +16821,72 @@ var Launcher = class {
|
|
|
16683
16821
|
if (!head || head[0] === 35 && head[1] === 33) return "ENOENT";
|
|
16684
16822
|
return binfmtOf(await this.interpreters(scope), path) ? "ENOENT" : "ENOEXEC";
|
|
16685
16823
|
}
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16824
|
+
verifiedFs(fs) {
|
|
16825
|
+
const read = (path) => this.verified(path, KERNEL_CALLER, fs);
|
|
16826
|
+
return Object.assign(Object.create(fs), {
|
|
16827
|
+
readFileBuffer: read,
|
|
16828
|
+
readFile: (path) => this.integrity ? this.text(path, KERNEL_CALLER) : fs.readFile(path)
|
|
16829
|
+
});
|
|
16830
|
+
}
|
|
16831
|
+
async cacheKey(path) {
|
|
16832
|
+
const verified = await this.integrity?.key(path);
|
|
16833
|
+
if (verified !== void 0) return verified;
|
|
16834
|
+
const st = await this.base.stat(path);
|
|
16835
|
+
return `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
16836
|
+
}
|
|
16837
|
+
verified(path, caller, fs = this.base) {
|
|
16838
|
+
const plain = () => fs.readFileBuffer(path);
|
|
16839
|
+
return this.integrity ? this.integrity.read(path, caller, plain) : plain();
|
|
16840
|
+
}
|
|
16841
|
+
keyed(path, caller) {
|
|
16842
|
+
const plain = async () => this.base.readFileBuffer(path);
|
|
16843
|
+
return this.integrity ? this.integrity.readKeyed(path, caller, plain) : plain().then((bytes) => ({ bytes }));
|
|
16844
|
+
}
|
|
16845
|
+
cached(cache, key, load) {
|
|
16846
|
+
const hit = cache.get(key);
|
|
16847
|
+
if (hit !== void 0) return hit;
|
|
16848
|
+
const loading2 = load();
|
|
16849
|
+
const found = loading2.then(({ value }) => value);
|
|
16850
|
+
cache.set(key, found);
|
|
16851
|
+
loading2.then(
|
|
16852
|
+
(done4) => {
|
|
16853
|
+
if (done4.key === key || done4.key === void 0 && !key.includes("\0")) return;
|
|
16854
|
+
if (cache.get(key) === found) cache.delete(key);
|
|
16855
|
+
if (done4.key !== void 0) cache.set(done4.key, found);
|
|
16856
|
+
},
|
|
16857
|
+
() => cache.delete(key)
|
|
16858
|
+
);
|
|
16859
|
+
return found;
|
|
16860
|
+
}
|
|
16861
|
+
async module(path, caller) {
|
|
16862
|
+
const key = await this.cacheKey(path);
|
|
16863
|
+
return this.cached(this.compiled, key, async () => {
|
|
16864
|
+
const { bytes, key: read } = await this.keyed(path, caller);
|
|
16865
|
+
const memory = importedMemory(bytes);
|
|
16866
|
+
const foreign = foreignImports(bytes);
|
|
16867
|
+
const compiled = await WebAssembly.compile(bytes);
|
|
16868
|
+
return { value: { module: compiled, ...memory ? { memory } : {}, foreign }, key: read };
|
|
16869
|
+
});
|
|
16870
|
+
}
|
|
16871
|
+
async checkedSources(planned, caller) {
|
|
16872
|
+
const { target } = planned;
|
|
16873
|
+
const files = [target.wasm, target.glue, target.imports, ...planned.sources ?? []];
|
|
16874
|
+
const manifests = /* @__PURE__ */ new Set();
|
|
16875
|
+
for (const file of files) {
|
|
16876
|
+
const root = file === void 0 ? void 0 : PACKAGE_ROOT.exec(file)?.[1];
|
|
16877
|
+
if (root !== void 0) manifests.add(`${root}/package.json`);
|
|
16878
|
+
}
|
|
16879
|
+
for (const source of planned.sources ?? []) await this.text(source, caller);
|
|
16880
|
+
for (const manifest of manifests) {
|
|
16881
|
+
if (await this.base.exists(manifest)) await this.text(manifest, caller);
|
|
16882
|
+
}
|
|
16883
|
+
}
|
|
16884
|
+
async text(path, caller) {
|
|
16885
|
+
if (!this.integrity) return this.base.readFile(path);
|
|
16886
|
+
const key = await this.cacheKey(path);
|
|
16887
|
+
return this.cached(this.texts, key, async () => {
|
|
16888
|
+
const { bytes, key: read } = await this.keyed(path, caller);
|
|
16889
|
+
return { value: new TextDecoder().decode(bytes), key: read };
|
|
16705
16890
|
});
|
|
16706
16891
|
}
|
|
16707
16892
|
async names(path, module) {
|
|
@@ -16713,23 +16898,23 @@ var Launcher = class {
|
|
|
16713
16898
|
const optional = `${root}-names${beside.slice(root.length)}`;
|
|
16714
16899
|
return await this.base.exists(optional) ? optional : void 0;
|
|
16715
16900
|
}
|
|
16716
|
-
async program(target, env) {
|
|
16901
|
+
async program(target, env, caller) {
|
|
16717
16902
|
if (target.abi === "js" && target.wasm === SUDO_PATH) {
|
|
16718
16903
|
return { abi: "js", glue: SUDO_SOURCE, path: SUDO_PATH };
|
|
16719
16904
|
}
|
|
16720
16905
|
if (target.abi === "js") {
|
|
16721
|
-
return { abi: "js", glue: await this.
|
|
16906
|
+
return { abi: "js", glue: await this.text(target.wasm, caller), path: target.wasm };
|
|
16722
16907
|
}
|
|
16723
16908
|
if (target.abi !== "wasi") {
|
|
16724
16909
|
const [glue, { module: module2 }] = await Promise.all([
|
|
16725
|
-
this.
|
|
16726
|
-
this.module(target.wasm)
|
|
16910
|
+
this.text(target.glue, caller),
|
|
16911
|
+
this.module(target.wasm, caller)
|
|
16727
16912
|
]);
|
|
16728
16913
|
return { glue, module: module2 };
|
|
16729
16914
|
}
|
|
16730
|
-
const { module, memory, foreign } = await this.module(target.wasm);
|
|
16915
|
+
const { module, memory, foreign } = await this.module(target.wasm, caller);
|
|
16731
16916
|
const names = env.SLICC_WASM_BACKTRACE === "1" ? await this.names(target.wasm, module) : void 0;
|
|
16732
|
-
const imports = target.imports ? await this.
|
|
16917
|
+
const imports = target.imports ? await this.text(target.imports, caller) : void 0;
|
|
16733
16918
|
return {
|
|
16734
16919
|
abi: "wasi",
|
|
16735
16920
|
glue: "",
|
|
@@ -16751,7 +16936,9 @@ var Launcher = class {
|
|
|
16751
16936
|
env.HOSTNAME = this.hostname;
|
|
16752
16937
|
let program;
|
|
16753
16938
|
try {
|
|
16754
|
-
|
|
16939
|
+
const caller = { pid: req.ppid ?? 0, uid: req.cred.euid, tag: req.tag };
|
|
16940
|
+
if (this.integrity) await this.checkedSources(planned, caller);
|
|
16941
|
+
program = await this.program(target, env, caller);
|
|
16755
16942
|
} catch (err) {
|
|
16756
16943
|
await req.fds.closeAll();
|
|
16757
16944
|
throw err;
|
|
@@ -17243,11 +17430,14 @@ var Launcher = class {
|
|
|
17243
17430
|
}
|
|
17244
17431
|
};
|
|
17245
17432
|
}
|
|
17246
|
-
const module = (await scanFilesystems(this.
|
|
17433
|
+
const module = (await scanFilesystems(this.scanned, await this.roots())).get(type);
|
|
17247
17434
|
if (!module) throw fsError("ENODEV", `unknown file system type ${type}`);
|
|
17248
17435
|
if (!this.createDriverWorker)
|
|
17249
17436
|
throw fsError("ENODEV", `this kernel cannot start ${type} drivers`);
|
|
17250
|
-
const
|
|
17437
|
+
const root = PACKAGE_ROOT.exec(module)?.[1];
|
|
17438
|
+
if (this.integrity && root !== void 0)
|
|
17439
|
+
await this.text(`${root}/package.json`, KERNEL_CALLER);
|
|
17440
|
+
const code = new TextDecoder().decode(await this.verified(module, KERNEL_CALLER));
|
|
17251
17441
|
const worker = this.createDriverWorker();
|
|
17252
17442
|
const driver = new MessageChannel();
|
|
17253
17443
|
const client = new MessageChannel();
|