@ai-ecoverse/slicc-kernel 1.13.0 → 1.15.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 +19 -2
- package/dist/index.js +28 -9
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +296 -29
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +3 -0
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +256 -20
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +3 -0
- package/dist/process-worker.js.map +2 -2
- package/package.json +2 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -177,6 +177,37 @@ function openMeta(name2, factory) {
|
|
|
177
177
|
});
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
// src/mount/media.ts
|
|
181
|
+
var MEDIA_STORE = "handles";
|
|
182
|
+
function memoryMedia() {
|
|
183
|
+
const handles = /* @__PURE__ */ new Map();
|
|
184
|
+
return {
|
|
185
|
+
get: async (id) => handles.get(id),
|
|
186
|
+
put: async (id, handle) => void handles.set(id, handle)
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function settle2(request2, value) {
|
|
190
|
+
return new Promise((resolve, reject) => {
|
|
191
|
+
request2.onsuccess = () => resolve(value());
|
|
192
|
+
request2.onerror = () => reject(request2.error);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function openMedia(name2, factory) {
|
|
196
|
+
const request2 = factory.open(name2, 1);
|
|
197
|
+
request2.onupgradeneeded = () => request2.result.createObjectStore(MEDIA_STORE);
|
|
198
|
+
return settle2(request2, () => {
|
|
199
|
+
const db = request2.result;
|
|
200
|
+
const store = (mode) => db.transaction(MEDIA_STORE, mode).objectStore(MEDIA_STORE);
|
|
201
|
+
return {
|
|
202
|
+
get: (id) => {
|
|
203
|
+
const got = store("readonly").get(id);
|
|
204
|
+
return settle2(got, () => got.result);
|
|
205
|
+
},
|
|
206
|
+
put: (id, handle) => settle2(store("readwrite").put(handle, id), () => void 0)
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
180
211
|
// src/pin.ts
|
|
181
212
|
function pinScript(url) {
|
|
182
213
|
try {
|
|
@@ -643,7 +674,8 @@ var ERRNO_BY_DOM_ERROR = {
|
|
|
643
674
|
TypeMismatchError: "ENOTDIR",
|
|
644
675
|
InvalidModificationError: "ENOTEMPTY",
|
|
645
676
|
NoModificationAllowedError: "EBUSY",
|
|
646
|
-
TypeError: "EINVAL"
|
|
677
|
+
TypeError: "EINVAL",
|
|
678
|
+
NotAllowedError: "EACCES"
|
|
647
679
|
};
|
|
648
680
|
function translate(err, path) {
|
|
649
681
|
if (typeof err?.code === "string") return err;
|
|
@@ -3022,9 +3054,28 @@ async function packages(fs, modules) {
|
|
|
3022
3054
|
}
|
|
3023
3055
|
return dirs;
|
|
3024
3056
|
}
|
|
3057
|
+
async function pnpmGlobalRoots(fs, home) {
|
|
3058
|
+
const roots = [];
|
|
3059
|
+
const global = `${home}/global`;
|
|
3060
|
+
for (const version of (await fs.readdir(global).catch(() => [])).sort()) {
|
|
3061
|
+
for (const group of (await fs.readdir(`${global}/${version}`).catch(() => [])).sort()) {
|
|
3062
|
+
const dir = `${global}/${version}/${group}`;
|
|
3063
|
+
const st = await fs.lstat(dir).catch(() => void 0);
|
|
3064
|
+
if (st?.isDirectory && await fs.exists(`${dir}/node_modules`))
|
|
3065
|
+
roots.push(`${dir}/node_modules`);
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
return roots;
|
|
3069
|
+
}
|
|
3070
|
+
async function packagesIn(fs, roots) {
|
|
3071
|
+
const dirs = [];
|
|
3072
|
+
for (const root of typeof roots === "string" ? [roots] : roots)
|
|
3073
|
+
dirs.push(...await packages(fs, root));
|
|
3074
|
+
return dirs;
|
|
3075
|
+
}
|
|
3025
3076
|
async function scanCommands(fs, modules) {
|
|
3026
3077
|
const found = /* @__PURE__ */ new Map();
|
|
3027
|
-
for (const pkg of await
|
|
3078
|
+
for (const pkg of await packagesIn(fs, modules)) {
|
|
3028
3079
|
let manifest;
|
|
3029
3080
|
try {
|
|
3030
3081
|
manifest = JSON.parse(await fs.readFile(`${pkg}/package.json`));
|
|
@@ -3043,7 +3094,7 @@ async function scanCommands(fs, modules) {
|
|
|
3043
3094
|
}
|
|
3044
3095
|
async function scanFilesystems(fs, modules) {
|
|
3045
3096
|
const found = /* @__PURE__ */ new Map();
|
|
3046
|
-
for (const pkg of await
|
|
3097
|
+
for (const pkg of await packagesIn(fs, modules)) {
|
|
3047
3098
|
let manifest;
|
|
3048
3099
|
try {
|
|
3049
3100
|
manifest = JSON.parse(await fs.readFile(`${pkg}/package.json`));
|
|
@@ -3642,7 +3693,7 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
3642
3693
|
Atomics.notify(header2, SAB_I_PUB);
|
|
3643
3694
|
if (offset + chunk2 >= entry.payload.byteLength) drop(id);
|
|
3644
3695
|
}
|
|
3645
|
-
function
|
|
3696
|
+
function settle3(id, result) {
|
|
3646
3697
|
if (disposed) return;
|
|
3647
3698
|
const { status, payload } = encodeSabResult(result);
|
|
3648
3699
|
drop(id);
|
|
@@ -3661,7 +3712,7 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
3661
3712
|
const entry = pending.get(data.id);
|
|
3662
3713
|
const offset = data.offset;
|
|
3663
3714
|
if (!entry || typeof offset !== "number" || !Number.isInteger(offset) || offset < 0 || offset > entry.payload.byteLength) {
|
|
3664
|
-
|
|
3715
|
+
settle3(data.id, { ok: false, errno: "EIO", message: "sync-sab: bad continuation" });
|
|
3665
3716
|
return;
|
|
3666
3717
|
}
|
|
3667
3718
|
publish(data.id, entry, offset);
|
|
@@ -3675,7 +3726,7 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
3675
3726
|
try {
|
|
3676
3727
|
dispatched = dispatch2(req);
|
|
3677
3728
|
} catch (err) {
|
|
3678
|
-
|
|
3729
|
+
settle3(id, {
|
|
3679
3730
|
ok: false,
|
|
3680
3731
|
errno: "EIO",
|
|
3681
3732
|
message: err instanceof Error ? err.message : String(err)
|
|
@@ -3683,8 +3734,8 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
3683
3734
|
return;
|
|
3684
3735
|
}
|
|
3685
3736
|
void dispatched.then(
|
|
3686
|
-
(result) =>
|
|
3687
|
-
(err) =>
|
|
3737
|
+
(result) => settle3(id, result),
|
|
3738
|
+
(err) => settle3(id, {
|
|
3688
3739
|
ok: false,
|
|
3689
3740
|
errno: "EIO",
|
|
3690
3741
|
message: err instanceof Error ? err.message : String(err)
|
|
@@ -5778,8 +5829,8 @@ function spawnWasmProcess(opts) {
|
|
|
5778
5829
|
return dispatchSyncFs(req);
|
|
5779
5830
|
};
|
|
5780
5831
|
const responder = attachSyncSabResponder(worker, sab, token, { dispatch: dispatch2 });
|
|
5781
|
-
let
|
|
5782
|
-
const exited = new Promise((resolve) =>
|
|
5832
|
+
let settle3;
|
|
5833
|
+
const exited = new Promise((resolve) => settle3 = resolve);
|
|
5783
5834
|
let done4 = false;
|
|
5784
5835
|
let endedBy;
|
|
5785
5836
|
const finish = (code, sig) => {
|
|
@@ -5794,8 +5845,8 @@ function spawnWasmProcess(opts) {
|
|
|
5794
5845
|
opts.held?.delete(holds);
|
|
5795
5846
|
worker.terminate();
|
|
5796
5847
|
void process.exit().then(
|
|
5797
|
-
() =>
|
|
5798
|
-
() =>
|
|
5848
|
+
() => settle3(code),
|
|
5849
|
+
() => settle3(code)
|
|
5799
5850
|
);
|
|
5800
5851
|
};
|
|
5801
5852
|
const handle = (data) => {
|
|
@@ -6108,6 +6159,148 @@ function serveFilesystem(port, handlers, capabilities = {}) {
|
|
|
6108
6159
|
return { invalidate: (paths) => reply({ invalidate: paths }) };
|
|
6109
6160
|
}
|
|
6110
6161
|
|
|
6162
|
+
// src/mount/fsa.ts
|
|
6163
|
+
var FSA_CAPABILITIES = { listingStats: true };
|
|
6164
|
+
var codeOf = (err) => err?.code;
|
|
6165
|
+
var denied = (err) => codeOf(err) === "EACCES" || err?.name === "NotAllowedError";
|
|
6166
|
+
function attrOf(st) {
|
|
6167
|
+
return {
|
|
6168
|
+
kind: st.isDirectory ? "directory" : st.isSymbolicLink ? "symlink" : "file",
|
|
6169
|
+
size: st.size,
|
|
6170
|
+
mtime: st.mtime.getTime(),
|
|
6171
|
+
mode: st.mode,
|
|
6172
|
+
ino: st.ino
|
|
6173
|
+
};
|
|
6174
|
+
}
|
|
6175
|
+
function kernelFsHandlers(fs) {
|
|
6176
|
+
const handles = /* @__PURE__ */ new Map();
|
|
6177
|
+
let nextFh = 0;
|
|
6178
|
+
const handle = (fh) => {
|
|
6179
|
+
const found = handles.get(fh);
|
|
6180
|
+
if (!found) throw fsError2("EBADF", `handle ${fh}`);
|
|
6181
|
+
return found;
|
|
6182
|
+
};
|
|
6183
|
+
async function existing(path) {
|
|
6184
|
+
try {
|
|
6185
|
+
return await fs.stat(path);
|
|
6186
|
+
} catch (err) {
|
|
6187
|
+
if (codeOf(err) === "ENOENT") return void 0;
|
|
6188
|
+
throw err;
|
|
6189
|
+
}
|
|
6190
|
+
}
|
|
6191
|
+
return {
|
|
6192
|
+
getattr: async (path) => attrOf(await fs.lstat(path)),
|
|
6193
|
+
readdir: async (path) => (await fs.readdirStat(path)).flatMap(([name2, st]) => {
|
|
6194
|
+
if (!st) return [];
|
|
6195
|
+
const attr = attrOf(st);
|
|
6196
|
+
return [{ name: name2, kind: attr.kind, attr }];
|
|
6197
|
+
}),
|
|
6198
|
+
async open(path, flags) {
|
|
6199
|
+
const st = await existing(path);
|
|
6200
|
+
if (st && flags.exclusive) throw fsError2("EEXIST", path);
|
|
6201
|
+
if (st?.isDirectory && flags.write) throw fsError2("EISDIR", path);
|
|
6202
|
+
if (!st && !flags.create) throw fsError2("ENOENT", path);
|
|
6203
|
+
const data = st && !flags.truncate ? await fs.readFileBuffer(path) : new Uint8Array(0);
|
|
6204
|
+
handles.set(++nextFh, { path, data, length: data.length, dirty: !st || flags.truncate });
|
|
6205
|
+
return nextFh;
|
|
6206
|
+
},
|
|
6207
|
+
async read(fh, offset, size) {
|
|
6208
|
+
const h = handle(fh);
|
|
6209
|
+
return h.data.slice(offset, Math.min(h.length, offset + size));
|
|
6210
|
+
},
|
|
6211
|
+
async write(fh, offset, bytes) {
|
|
6212
|
+
const h = handle(fh);
|
|
6213
|
+
const end = offset + bytes.length;
|
|
6214
|
+
if (end > h.data.length) {
|
|
6215
|
+
const grown = new Uint8Array(Math.max(end, h.data.length * 2));
|
|
6216
|
+
grown.set(h.data.subarray(0, h.length));
|
|
6217
|
+
h.data = grown;
|
|
6218
|
+
}
|
|
6219
|
+
h.data.set(bytes, offset);
|
|
6220
|
+
h.length = Math.max(h.length, end);
|
|
6221
|
+
h.dirty = true;
|
|
6222
|
+
},
|
|
6223
|
+
async release(fh) {
|
|
6224
|
+
const h = handle(fh);
|
|
6225
|
+
handles.delete(fh);
|
|
6226
|
+
if (h.dirty) await fs.writeFile(h.path, h.data.slice(0, h.length));
|
|
6227
|
+
},
|
|
6228
|
+
mkdir: (path) => fs.mkdir(path),
|
|
6229
|
+
async rmdir(path) {
|
|
6230
|
+
if (!(await fs.lstat(path)).isDirectory) throw fsError2("ENOTDIR", path);
|
|
6231
|
+
if ((await fs.readdir(path)).length > 0) throw fsError2("ENOTEMPTY", path);
|
|
6232
|
+
await fs.rm(path);
|
|
6233
|
+
},
|
|
6234
|
+
async unlink(path) {
|
|
6235
|
+
if ((await fs.lstat(path)).isDirectory) throw fsError2("EISDIR", path);
|
|
6236
|
+
await fs.rm(path);
|
|
6237
|
+
},
|
|
6238
|
+
rename: (from, to) => fs.rename(from, to),
|
|
6239
|
+
symlink: (target, path) => fs.symlink(target, path),
|
|
6240
|
+
readlink: (path) => fs.readlink(path),
|
|
6241
|
+
async setattr(path, change) {
|
|
6242
|
+
if (change.mode !== void 0) await fs.chmod(path, change.mode);
|
|
6243
|
+
if (change.mtime !== void 0) {
|
|
6244
|
+
await fs.utimes(path, new Date(change.mtime), new Date(change.mtime));
|
|
6245
|
+
}
|
|
6246
|
+
}
|
|
6247
|
+
};
|
|
6248
|
+
}
|
|
6249
|
+
var EMPTY_ROOT = { kind: "directory", size: 0, mtime: 0, mode: 16749 };
|
|
6250
|
+
function granted(handle) {
|
|
6251
|
+
if (!handle.queryPermission) return Promise.resolve(true);
|
|
6252
|
+
return handle.queryPermission({ mode: "readwrite" }).then(
|
|
6253
|
+
(state) => state === "granted",
|
|
6254
|
+
() => false
|
|
6255
|
+
);
|
|
6256
|
+
}
|
|
6257
|
+
function removableMedium(onLost, open = (handle) => new OpfsFs(handle)) {
|
|
6258
|
+
let current;
|
|
6259
|
+
const absent = () => fsError2("ENOMEDIUM", "No medium found");
|
|
6260
|
+
function wrap(pick) {
|
|
6261
|
+
return async (...args) => {
|
|
6262
|
+
const medium = current;
|
|
6263
|
+
if (!medium) throw absent();
|
|
6264
|
+
try {
|
|
6265
|
+
return await pick(medium.handlers)(...args);
|
|
6266
|
+
} catch (err) {
|
|
6267
|
+
if (!denied(err) || await granted(medium.handle)) throw err;
|
|
6268
|
+
if (current === medium) {
|
|
6269
|
+
current = void 0;
|
|
6270
|
+
onLost(medium.handle);
|
|
6271
|
+
}
|
|
6272
|
+
throw absent();
|
|
6273
|
+
}
|
|
6274
|
+
};
|
|
6275
|
+
}
|
|
6276
|
+
const getattr = wrap((h) => h.getattr);
|
|
6277
|
+
const readdir = wrap((h) => h.readdir);
|
|
6278
|
+
return {
|
|
6279
|
+
handlers: {
|
|
6280
|
+
getattr: (path) => current || path !== "/" ? getattr(path) : Promise.resolve(EMPTY_ROOT),
|
|
6281
|
+
readdir: (path) => current || path !== "/" ? readdir(path) : Promise.resolve([]),
|
|
6282
|
+
open: wrap((h) => h.open),
|
|
6283
|
+
read: wrap((h) => h.read),
|
|
6284
|
+
write: wrap((h) => h.write),
|
|
6285
|
+
release: wrap((h) => h.release),
|
|
6286
|
+
mkdir: wrap((h) => h.mkdir),
|
|
6287
|
+
rmdir: wrap((h) => h.rmdir),
|
|
6288
|
+
unlink: wrap((h) => h.unlink),
|
|
6289
|
+
rename: wrap((h) => h.rename),
|
|
6290
|
+
symlink: wrap((h) => h.symlink),
|
|
6291
|
+
readlink: wrap((h) => h.readlink),
|
|
6292
|
+
setattr: wrap((h) => h.setattr)
|
|
6293
|
+
},
|
|
6294
|
+
present: () => current !== void 0,
|
|
6295
|
+
insert(handle) {
|
|
6296
|
+
current = { handle, handlers: kernelFsHandlers(open(handle)) };
|
|
6297
|
+
},
|
|
6298
|
+
eject() {
|
|
6299
|
+
current = void 0;
|
|
6300
|
+
}
|
|
6301
|
+
};
|
|
6302
|
+
}
|
|
6303
|
+
|
|
6111
6304
|
// src/mount/connection.ts
|
|
6112
6305
|
var DRIVER_TIMEOUT_MS = 3e4;
|
|
6113
6306
|
function unref(timer) {
|
|
@@ -6251,14 +6444,16 @@ var MountTable = class {
|
|
|
6251
6444
|
this.deps = deps;
|
|
6252
6445
|
}
|
|
6253
6446
|
list() {
|
|
6254
|
-
return [...this.mounts.values()].map(
|
|
6255
|
-
type,
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6447
|
+
return [...this.mounts.values()].map(
|
|
6448
|
+
({ type, source, target, options, state, error, present }) => ({
|
|
6449
|
+
type,
|
|
6450
|
+
source,
|
|
6451
|
+
target,
|
|
6452
|
+
options: { ...options },
|
|
6453
|
+
state: state === "ok" && present?.() === false ? "nomedium" : state,
|
|
6454
|
+
...error ? { error } : {}
|
|
6455
|
+
})
|
|
6456
|
+
);
|
|
6262
6457
|
}
|
|
6263
6458
|
locate(path) {
|
|
6264
6459
|
let best;
|
|
@@ -6329,7 +6524,8 @@ var MountTable = class {
|
|
|
6329
6524
|
maxFile: options.maxfile !== void 0 ? parseSize(options.maxfile) : caps.maxFile ?? 0,
|
|
6330
6525
|
attrs: /* @__PURE__ */ new Map(),
|
|
6331
6526
|
lists: /* @__PURE__ */ new Map(),
|
|
6332
|
-
dispose: () => opened2.dispose()
|
|
6527
|
+
dispose: () => opened2.dispose(),
|
|
6528
|
+
...opened2.present ? { present: opened2.present } : {}
|
|
6333
6529
|
};
|
|
6334
6530
|
mounted = mount;
|
|
6335
6531
|
this.mounts.set(target, mount);
|
|
@@ -6966,6 +7162,7 @@ function foreignImports(bytes) {
|
|
|
6966
7162
|
}
|
|
6967
7163
|
|
|
6968
7164
|
// src/launcher.ts
|
|
7165
|
+
var PNPM_HOME = "/home/.local/share/pnpm";
|
|
6969
7166
|
var COMMAND2 = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
6970
7167
|
var PACKAGE_ROOT = /^(.*\/node_modules\/(?:@[^/]+\/)?[^/]+)\//;
|
|
6971
7168
|
var ENV_REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
@@ -7055,8 +7252,13 @@ var Launcher = class {
|
|
|
7055
7252
|
ca;
|
|
7056
7253
|
transport;
|
|
7057
7254
|
watchers = new FsWatchers();
|
|
7255
|
+
pnpmHome;
|
|
7058
7256
|
mounts;
|
|
7059
7257
|
createDriverWorker;
|
|
7258
|
+
media;
|
|
7259
|
+
onMountPending;
|
|
7260
|
+
removable = /* @__PURE__ */ new Map();
|
|
7261
|
+
inserted = /* @__PURE__ */ new Map();
|
|
7060
7262
|
openFiles = /* @__PURE__ */ new Set();
|
|
7061
7263
|
held = /* @__PURE__ */ new Set();
|
|
7062
7264
|
nextPid = 1e3;
|
|
@@ -7071,6 +7273,9 @@ var Launcher = class {
|
|
|
7071
7273
|
this.base = this.watchers.wrap(this.mounts.wrap(options.fs));
|
|
7072
7274
|
this.createWorker = options.createWorker;
|
|
7073
7275
|
this.createDriverWorker = options.createDriverWorker;
|
|
7276
|
+
this.media = options.media ?? memoryMedia();
|
|
7277
|
+
this.onMountPending = options.onMountPending;
|
|
7278
|
+
this.pnpmHome = options.env?.PNPM_HOME ?? PNPM_HOME;
|
|
7074
7279
|
this.modulesDir = options.modules ?? "/node_modules";
|
|
7075
7280
|
this.env = { ...networkEnv(), ...options.env };
|
|
7076
7281
|
this.ca = kernelCa(options.caStore ?? memoryCaStore());
|
|
@@ -7081,11 +7286,17 @@ var Launcher = class {
|
|
|
7081
7286
|
ca: this.ca
|
|
7082
7287
|
});
|
|
7083
7288
|
this.fs = withCommandDirs(this.base, async () => new Set((await this.commands()).keys()));
|
|
7289
|
+
this.watchers.watch([this.modulesDir, this.pnpmHome], { recursive: true }, () => {
|
|
7290
|
+
this.catalog = void 0;
|
|
7291
|
+
});
|
|
7084
7292
|
}
|
|
7085
7293
|
commands() {
|
|
7086
|
-
this.catalog ??= scanCommands(this.base,
|
|
7294
|
+
this.catalog ??= this.roots().then((roots) => scanCommands(this.base, roots));
|
|
7087
7295
|
return this.catalog;
|
|
7088
7296
|
}
|
|
7297
|
+
async roots() {
|
|
7298
|
+
return [this.modulesDir, ...await pnpmGlobalRoots(this.base, this.pnpmHome)];
|
|
7299
|
+
}
|
|
7089
7300
|
async resolve(file, argv0, cwd) {
|
|
7090
7301
|
const name2 = COMMAND2.exec(file)?.[1] ?? (file.includes("/") ? void 0 : file);
|
|
7091
7302
|
if (name2 !== void 0) {
|
|
@@ -7327,7 +7538,8 @@ var Launcher = class {
|
|
|
7327
7538
|
if (sig !== 0) handle.signal(sig);
|
|
7328
7539
|
return true;
|
|
7329
7540
|
}
|
|
7330
|
-
async driver(type,
|
|
7541
|
+
async driver(type, spec) {
|
|
7542
|
+
if (type === "fsa") return this.fsaDriver(spec);
|
|
7331
7543
|
if (type === "tmpfs") {
|
|
7332
7544
|
const { port1, port2 } = new MessageChannel();
|
|
7333
7545
|
serveFilesystem(port2, tmpfs(), { symlinks: true, chmod: true, attrTtl: 0 });
|
|
@@ -7339,7 +7551,7 @@ var Launcher = class {
|
|
|
7339
7551
|
}
|
|
7340
7552
|
};
|
|
7341
7553
|
}
|
|
7342
|
-
const module = (await scanFilesystems(this.base, this.
|
|
7554
|
+
const module = (await scanFilesystems(this.base, await this.roots())).get(type);
|
|
7343
7555
|
if (!module) throw fsError("ENODEV", `unknown file system type ${type}`);
|
|
7344
7556
|
if (!this.createDriverWorker)
|
|
7345
7557
|
throw fsError("ENODEV", `this kernel cannot start ${type} drivers`);
|
|
@@ -7368,8 +7580,47 @@ var Launcher = class {
|
|
|
7368
7580
|
})
|
|
7369
7581
|
};
|
|
7370
7582
|
}
|
|
7583
|
+
async fsaDriver(spec) {
|
|
7584
|
+
const { target, source } = spec;
|
|
7585
|
+
const ask = (handle) => this.onMountPending?.({ target, source, ...handle ? { handle } : {} });
|
|
7586
|
+
const { port1, port2 } = new MessageChannel();
|
|
7587
|
+
const medium = removableMedium((handle) => {
|
|
7588
|
+
served.invalidate(true);
|
|
7589
|
+
ask(handle);
|
|
7590
|
+
});
|
|
7591
|
+
const served = serveFilesystem(port2, medium.handlers, FSA_CAPABILITIES);
|
|
7592
|
+
const id = source.slice("fsa:".length);
|
|
7593
|
+
this.removable.set(target, { id, medium, served });
|
|
7594
|
+
const stored = this.inserted.get(id) ?? await this.media.get(id);
|
|
7595
|
+
if (stored && await granted(stored)) medium.insert(stored);
|
|
7596
|
+
else ask(stored);
|
|
7597
|
+
return {
|
|
7598
|
+
port: port1,
|
|
7599
|
+
present: () => medium.present(),
|
|
7600
|
+
dispose: () => {
|
|
7601
|
+
this.removable.delete(target);
|
|
7602
|
+
port1.close();
|
|
7603
|
+
port2.close();
|
|
7604
|
+
}
|
|
7605
|
+
};
|
|
7606
|
+
}
|
|
7371
7607
|
mount(spec) {
|
|
7372
|
-
|
|
7608
|
+
if (spec.type !== "fsa" || spec.source.startsWith("fsa:"))
|
|
7609
|
+
return this.mounts.mount(spec, this.fs);
|
|
7610
|
+
return this.mounts.mount({ ...spec, source: `fsa:${crypto.randomUUID()}` }, this.fs);
|
|
7611
|
+
}
|
|
7612
|
+
async insert(target, handle, source) {
|
|
7613
|
+
const at = normalizePath(target);
|
|
7614
|
+
const slot = this.removable.get(at);
|
|
7615
|
+
if (!slot) throw fsError("EINVAL", `${at} is not a removable mount`);
|
|
7616
|
+
if (source !== void 0 && source !== `fsa:${slot.id}`) {
|
|
7617
|
+
throw fsError("EINVAL", `${at} is no longer the drive ${source}`);
|
|
7618
|
+
}
|
|
7619
|
+
if (!await granted(handle)) throw fsError("EACCES", `${at}: no permission for this folder`);
|
|
7620
|
+
this.inserted.set(slot.id, handle);
|
|
7621
|
+
await this.media.put(slot.id, handle);
|
|
7622
|
+
slot.medium.insert(handle);
|
|
7623
|
+
slot.served.invalidate(true);
|
|
7373
7624
|
}
|
|
7374
7625
|
umount(target) {
|
|
7375
7626
|
this.mounts.umount(target);
|
|
@@ -7379,7 +7630,14 @@ var Launcher = class {
|
|
|
7379
7630
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
7380
7631
|
}
|
|
7381
7632
|
environment(cwd, extra) {
|
|
7382
|
-
return {
|
|
7633
|
+
return {
|
|
7634
|
+
PATH: `/usr/bin:/bin:${this.pnpmHome}/bin`,
|
|
7635
|
+
HOME: "/home",
|
|
7636
|
+
PNPM_HOME: this.pnpmHome,
|
|
7637
|
+
...this.env,
|
|
7638
|
+
PWD: cwd,
|
|
7639
|
+
...extra
|
|
7640
|
+
};
|
|
7383
7641
|
}
|
|
7384
7642
|
async starting(argv, dir) {
|
|
7385
7643
|
this.catalog = void 0;
|
|
@@ -7470,6 +7728,10 @@ function act2(session, req) {
|
|
|
7470
7728
|
function dirsChannel(name2) {
|
|
7471
7729
|
return name2 === false ? void 0 : `slicc-kernel-dirs:${name2}`;
|
|
7472
7730
|
}
|
|
7731
|
+
async function stores(deps, name2) {
|
|
7732
|
+
if (name2 === false) return {};
|
|
7733
|
+
return { meta: await deps.metadata?.(name2), media: await deps.media?.(`${name2}:media`) };
|
|
7734
|
+
}
|
|
7473
7735
|
function serveKernel(port, deps) {
|
|
7474
7736
|
let launcher;
|
|
7475
7737
|
let remote;
|
|
@@ -7521,7 +7783,7 @@ function serveKernel(port, deps) {
|
|
|
7521
7783
|
async function init(req) {
|
|
7522
7784
|
launcher = (req.root ? Promise.resolve(req.root) : deps.storage()).then(async (root) => {
|
|
7523
7785
|
const name2 = req.metadata ?? META_DB;
|
|
7524
|
-
const meta
|
|
7786
|
+
const { meta, media } = await stores(deps, name2);
|
|
7525
7787
|
remote = req.transport ? new RemoteTransport(port, req.transport) : void 0;
|
|
7526
7788
|
const fs = new OpfsFs(root, meta, dirsChannel(name2));
|
|
7527
7789
|
await fs.reconcile();
|
|
@@ -7532,6 +7794,8 @@ function serveKernel(port, deps) {
|
|
|
7532
7794
|
...req.modules ? { modules: req.modules } : {},
|
|
7533
7795
|
...req.env ? { env: req.env } : {},
|
|
7534
7796
|
...remote ? { transport: remote } : {},
|
|
7797
|
+
...media ? { media } : {},
|
|
7798
|
+
onMountPending: (medium) => port.postMessage({ medium }),
|
|
7535
7799
|
caStore: caStore(deps.metadata ? name2 : false)
|
|
7536
7800
|
});
|
|
7537
7801
|
await started.prepare();
|
|
@@ -7544,13 +7808,15 @@ function serveKernel(port, deps) {
|
|
|
7544
7808
|
const l = await ready2();
|
|
7545
7809
|
if (req.op === "mount") return l.mount(req.spec);
|
|
7546
7810
|
if (req.op === "umount") return l.umount(req.target);
|
|
7811
|
+
if (req.op === "insert") return l.insert(req.target, req.handle, req.source);
|
|
7547
7812
|
return l.mounts.list();
|
|
7548
7813
|
}
|
|
7549
7814
|
async function handle(req) {
|
|
7550
7815
|
if (req.op === "init") return init(req);
|
|
7551
7816
|
if (req.op === "open-terminal") return terminal(req);
|
|
7552
7817
|
if (req.op === "connect") return connect();
|
|
7553
|
-
if (req.op === "mount" || req.op === "umount" || req.op === "mounts"
|
|
7818
|
+
if (req.op === "mount" || req.op === "umount" || req.op === "mounts" || req.op === "insert")
|
|
7819
|
+
return mountOp(req);
|
|
7554
7820
|
if (req.op === "terminal") {
|
|
7555
7821
|
const session = terminals.get(req.terminal);
|
|
7556
7822
|
if (!session) throw new Error(`no terminal ${req.terminal}`);
|
|
@@ -7583,6 +7849,7 @@ serveKernel(globalThis, {
|
|
|
7583
7849
|
storage: () => navigator.storage.getDirectory(),
|
|
7584
7850
|
createWorker: () => new Worker(processWorker, { type: "module" }),
|
|
7585
7851
|
createDriverWorker: () => new Worker(driverWorker, { type: "module" }),
|
|
7586
|
-
metadata: (name2) => openMeta(name2, indexedDB)
|
|
7852
|
+
metadata: (name2) => openMeta(name2, indexedDB),
|
|
7853
|
+
media: (name2) => openMedia(name2, indexedDB)
|
|
7587
7854
|
});
|
|
7588
7855
|
//# sourceMappingURL=kernel-worker.js.map
|