@utoo/web 1.2.0-rc.8 → 1.2.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 +14 -12
- package/esm/{8f0451c2e61477918e02.wasm → cb25445c9f3a2acfc918.wasm} +0 -0
- package/esm/index.d.ts +3 -2
- package/esm/index.js +3 -2
- package/esm/loaderWorker.js +1 -1
- package/esm/{forkedProject.d.ts → project/ForkedProject.d.ts} +4 -3
- package/esm/{forkedProject.js → project/ForkedProject.js} +4 -1
- package/esm/{internalProject.d.ts → project/InternalProject.d.ts} +3 -2
- package/esm/{internalProject.js → project/InternalProject.js} +12 -9
- package/esm/{project.d.ts → project/Project.d.ts} +2 -1
- package/esm/{project.js → project/Project.js} +11 -8
- package/esm/serviceWorker.js +2 -2
- package/esm/{type.d.ts → types.d.ts} +5 -0
- package/esm/utoo/index.d.ts +68 -13
- package/esm/utoo/index.js +282 -142
- package/esm/utoo/index_bg.wasm +0 -0
- package/esm/webpackLoaders/cjs.js +4 -32
- package/esm/webpackLoaders/loaderWorkerPool.d.ts +1 -1
- package/esm/webpackLoaders/loaderWorkerPool.js +1 -20
- package/esm/webpackLoaders/polyfills/fsPolyfill.d.ts +1 -1
- package/esm/webpackLoaders/polyfills/fsPolyfill.js +57 -46
- package/esm/webpackLoaders/polyfills/fsPromisesPolyfill.d.ts +1 -1
- package/esm/webpackLoaders/polyfills/fsPromisesPolyfill.js +1 -1
- package/esm/webpackLoaders/{type.d.ts → types.d.ts} +0 -1
- package/esm/webpackLoaders/worker.js +0 -7
- package/esm/worker.js +2 -2
- package/package.json +10 -9
- package/esm/sabcom.d.ts +0 -61
- package/esm/sabcom.js +0 -203
- /package/esm/{type.js → types.js} +0 -0
- /package/esm/{installServiceWorker.d.ts → utils/installServiceWorker.d.ts} +0 -0
- /package/esm/{installServiceWorker.js → utils/installServiceWorker.js} +0 -0
- /package/esm/{message.d.ts → utils/message.d.ts} +0 -0
- /package/esm/{message.js → utils/message.js} +0 -0
- /package/esm/webpackLoaders/{type.js → types.js} +0 -0
|
@@ -7,35 +7,6 @@ const statCache = {};
|
|
|
7
7
|
const pkgJsonCache = {};
|
|
8
8
|
const resolutionCache = {};
|
|
9
9
|
const searchPathsCache = {};
|
|
10
|
-
const statSync = (p) => {
|
|
11
|
-
if (p.includes("node_modules") &&
|
|
12
|
-
Object.prototype.hasOwnProperty.call(statCache, p)) {
|
|
13
|
-
if (statCache[p] === false) {
|
|
14
|
-
throw new Error("ENOENT");
|
|
15
|
-
}
|
|
16
|
-
return statCache[p];
|
|
17
|
-
}
|
|
18
|
-
try {
|
|
19
|
-
const res = fs.statSync(p);
|
|
20
|
-
if (p.includes("node_modules"))
|
|
21
|
-
statCache[p] = res;
|
|
22
|
-
return res;
|
|
23
|
-
}
|
|
24
|
-
catch (e) {
|
|
25
|
-
if (p.includes("node_modules"))
|
|
26
|
-
statCache[p] = false;
|
|
27
|
-
throw e;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
const existsSync = (p) => {
|
|
31
|
-
try {
|
|
32
|
-
statSync(p);
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
catch (e) {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
10
|
const executeModule = (moduleCode, moduleId, id, importMaps, entrypoint) => {
|
|
40
11
|
if (installedModules[moduleId]) {
|
|
41
12
|
return installedModules[moduleId].exports;
|
|
@@ -108,7 +79,7 @@ const loadModule = (id, context, importMaps, entrypoint) => {
|
|
|
108
79
|
// 1. Resolve
|
|
109
80
|
let resolvedId = id;
|
|
110
81
|
if (id.startsWith(".")) {
|
|
111
|
-
resolvedId = path.
|
|
82
|
+
resolvedId = path.join(context, id);
|
|
112
83
|
}
|
|
113
84
|
// 2. Check Cache (SystemJS)
|
|
114
85
|
let dependency = System.get(resolvedId);
|
|
@@ -259,8 +230,9 @@ const loadModule = (id, context, importMaps, entrypoint) => {
|
|
|
259
230
|
resolutionCache[cacheKey] = moduleId;
|
|
260
231
|
return executeModule(moduleCode, moduleId, id, importMaps, entrypoint);
|
|
261
232
|
}
|
|
262
|
-
|
|
263
|
-
|
|
233
|
+
const error = new Error(`Worker: Dependency ${id} (resolved: ${resolvedId}) not found. Context: ${context}`);
|
|
234
|
+
console.error(error);
|
|
235
|
+
throw error;
|
|
264
236
|
};
|
|
265
237
|
export async function cjs(entrypoint, importMaps) {
|
|
266
238
|
// Clear caches to avoid stale data across runs
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Binding } from "../
|
|
1
|
+
import { Binding } from "../types";
|
|
2
2
|
export declare const runLoaderWorkerPool: (binding: Binding, projectCwd: string, loaderWorkerUrl: string, loadersImportMap?: Record<string, string>) => Promise<void>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import initWasm, { Project as ProjectInternal, registerWorkerScheduler, workerCreated, } from "../utoo";
|
|
1
|
+
import initWasm, { registerWorkerScheduler, workerCreated, } from "../utoo";
|
|
3
2
|
let nextWorkerId = 0;
|
|
4
3
|
const loaderWorkers = {};
|
|
5
4
|
export const runLoaderWorkerPool = async (binding, projectCwd, loaderWorkerUrl, loadersImportMap) => {
|
|
@@ -7,24 +6,7 @@ export const runLoaderWorkerPool = async (binding, projectCwd, loaderWorkerUrl,
|
|
|
7
6
|
const { options: { filename, cwd }, } = creation;
|
|
8
7
|
nextWorkerId += 1;
|
|
9
8
|
const workerId = nextWorkerId;
|
|
10
|
-
const sab = new SharedArrayBuffer(1024 * 1024 * 10); // 10MB
|
|
11
|
-
const sabHost = new sabcom.SabComHost(sab);
|
|
12
9
|
const worker = new Worker(loaderWorkerUrl, { name: filename });
|
|
13
|
-
worker.onmessage = async (event) => {
|
|
14
|
-
if (event.data === "sab_request") {
|
|
15
|
-
await sabcom.handleSabRequest(sabHost, {
|
|
16
|
-
read: (path) => ProjectInternal.read(path),
|
|
17
|
-
readDir: (path) => ProjectInternal.readDir(path),
|
|
18
|
-
writeString: (path, content) => ProjectInternal.writeString(path, content),
|
|
19
|
-
createDirAll: (path) => ProjectInternal.createDirAll(path),
|
|
20
|
-
createDir: (path) => ProjectInternal.createDir(path),
|
|
21
|
-
metadata: (path) => ProjectInternal.metadata(path),
|
|
22
|
-
removeFile: (path) => ProjectInternal.removeFile(path),
|
|
23
|
-
removeDir: (path, recursive) => ProjectInternal.removeDir(path, recursive),
|
|
24
|
-
copyFile: (src, dst) => ProjectInternal.copyFile(src, dst),
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
10
|
let finalCwd = cwd;
|
|
29
11
|
let finalFilename = filename;
|
|
30
12
|
if (projectCwd) {
|
|
@@ -69,7 +51,6 @@ export const runLoaderWorkerPool = async (binding, projectCwd, loaderWorkerUrl,
|
|
|
69
51
|
importMaps: { ...loadersImportMap },
|
|
70
52
|
entrypoint: finalFilename,
|
|
71
53
|
},
|
|
72
|
-
sab,
|
|
73
54
|
},
|
|
74
55
|
]);
|
|
75
56
|
const workers = loaderWorkers[filename] || (loaderWorkers[filename] = new Map());
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer } from "buffer";
|
|
2
|
-
import { Stats } from "../../
|
|
2
|
+
import { Stats } from "../../types";
|
|
3
3
|
import { promises } from "./fsPromisesPolyfill";
|
|
4
4
|
export declare function readFileSync(path: string, options: any): string | Buffer<any>;
|
|
5
5
|
export declare function readdirSync(path: string, options?: any): any;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Buffer } from "buffer";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import
|
|
4
|
-
import { Stats } from "../../type";
|
|
3
|
+
import { Stats } from "../../types";
|
|
5
4
|
import { promises } from "./fsPromisesPolyfill";
|
|
6
5
|
function resolvePath(p) {
|
|
7
6
|
var _a, _b, _c;
|
|
@@ -9,14 +8,6 @@ function resolvePath(p) {
|
|
|
9
8
|
const cwd = ((_b = (_a = self.process) === null || _a === void 0 ? void 0 : _a.cwd) === null || _b === void 0 ? void 0 : _b.call(_a)) || ((_c = self.workerData) === null || _c === void 0 ? void 0 : _c.cwd) || "/";
|
|
10
9
|
return path.resolve(cwd, p);
|
|
11
10
|
}
|
|
12
|
-
function getSabClient() {
|
|
13
|
-
// @ts-ignore
|
|
14
|
-
const client = self.workerData.sabClient;
|
|
15
|
-
if (!client) {
|
|
16
|
-
throw new Error("Sync fs not supported (no sabClient)");
|
|
17
|
-
}
|
|
18
|
-
return client;
|
|
19
|
-
}
|
|
20
11
|
function getFs() {
|
|
21
12
|
// @ts-ignore
|
|
22
13
|
const fs = self.workerData.fs;
|
|
@@ -25,22 +16,21 @@ function getFs() {
|
|
|
25
16
|
}
|
|
26
17
|
return fs;
|
|
27
18
|
}
|
|
28
|
-
// --- Synchronous API (via
|
|
19
|
+
// --- Synchronous API (via WASM Project Sync APIs) ---
|
|
20
|
+
const textDecoder = new TextDecoder();
|
|
29
21
|
export function readFileSync(path, options) {
|
|
30
|
-
const
|
|
31
|
-
const result =
|
|
22
|
+
const fs = getFs();
|
|
23
|
+
const result = fs.readSync(resolvePath(path));
|
|
32
24
|
if (options === "utf8" ||
|
|
33
25
|
options === "utf-8" ||
|
|
34
26
|
(options && (options.encoding === "utf8" || options.encoding === "utf-8"))) {
|
|
35
|
-
return
|
|
27
|
+
return textDecoder.decode(result);
|
|
36
28
|
}
|
|
37
29
|
return Buffer.from(result);
|
|
38
30
|
}
|
|
39
31
|
export function readdirSync(path, options) {
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const json = new TextDecoder().decode(result);
|
|
43
|
-
const entries = JSON.parse(json);
|
|
32
|
+
const fs = getFs();
|
|
33
|
+
const entries = fs.readDirSync(resolvePath(path));
|
|
44
34
|
if (options === null || options === void 0 ? void 0 : options.withFileTypes) {
|
|
45
35
|
return entries.map((e) => ({
|
|
46
36
|
name: e.name,
|
|
@@ -52,48 +42,69 @@ export function readdirSync(path, options) {
|
|
|
52
42
|
return entries.map((e) => e.name);
|
|
53
43
|
}
|
|
54
44
|
export function writeFileSync(path, data, options) {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
const fs = getFs();
|
|
46
|
+
let content;
|
|
47
|
+
if (typeof data === "string") {
|
|
48
|
+
content = new TextEncoder().encode(data);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
content = data;
|
|
52
|
+
}
|
|
53
|
+
fs.writeSync(resolvePath(path), content);
|
|
60
54
|
}
|
|
61
55
|
export function mkdirSync(path, options) {
|
|
62
|
-
const
|
|
56
|
+
const fs = getFs();
|
|
63
57
|
const recursive = (options === null || options === void 0 ? void 0 : options.recursive) || false;
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
if (recursive) {
|
|
59
|
+
fs.createDirAllSync(resolvePath(path));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
fs.createDirSync(resolvePath(path));
|
|
63
|
+
}
|
|
66
64
|
}
|
|
67
65
|
export function rmSync(path, options) {
|
|
68
|
-
const
|
|
66
|
+
const fs = getFs();
|
|
69
67
|
const recursive = (options === null || options === void 0 ? void 0 : options.recursive) || false;
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
if (recursive) {
|
|
69
|
+
fs.removeDirSync(resolvePath(path), true);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
fs.removeFileSync(resolvePath(path));
|
|
73
|
+
}
|
|
72
74
|
}
|
|
73
75
|
export function rmdirSync(path, options) {
|
|
74
|
-
const
|
|
76
|
+
const fs = getFs();
|
|
75
77
|
const recursive = (options === null || options === void 0 ? void 0 : options.recursive) || false;
|
|
76
|
-
|
|
77
|
-
client.call(sabcom.SAB_OP_RMDIR, payload);
|
|
78
|
+
fs.removeDirSync(resolvePath(path), recursive);
|
|
78
79
|
}
|
|
79
80
|
export function copyFileSync(src, dst) {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
src: resolvePath(src),
|
|
83
|
-
dst: resolvePath(dst),
|
|
84
|
-
});
|
|
85
|
-
client.call(sabcom.SAB_OP_COPY_FILE, payload);
|
|
81
|
+
const fs = getFs();
|
|
82
|
+
fs.copyFileSync(resolvePath(src), resolvePath(dst));
|
|
86
83
|
}
|
|
87
84
|
export function statSync(p) {
|
|
88
|
-
const
|
|
89
|
-
const
|
|
85
|
+
const fs = getFs();
|
|
86
|
+
const metadata = fs.metadataSync(resolvePath(p));
|
|
87
|
+
let type, size;
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
if (typeof metadata.toJSON === "function") {
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
const json = metadata.toJSON();
|
|
92
|
+
type = json.type;
|
|
93
|
+
size = json.file_size;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// @ts-ignore
|
|
97
|
+
type = metadata.type;
|
|
98
|
+
// @ts-ignore
|
|
99
|
+
size = metadata.file_size;
|
|
100
|
+
}
|
|
90
101
|
return new Stats({
|
|
91
|
-
type:
|
|
92
|
-
size: Number(
|
|
93
|
-
atimeMs:
|
|
94
|
-
mtimeMs:
|
|
95
|
-
ctimeMs:
|
|
96
|
-
birthtimeMs:
|
|
102
|
+
type: type === "directory" ? "directory" : "file",
|
|
103
|
+
size: Number(size || 0),
|
|
104
|
+
atimeMs: Date.now(),
|
|
105
|
+
mtimeMs: Date.now(),
|
|
106
|
+
ctimeMs: Date.now(),
|
|
107
|
+
birthtimeMs: Date.now(),
|
|
97
108
|
});
|
|
98
109
|
}
|
|
99
110
|
export function lstatSync(p) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { SabComClient } from "../sabcom";
|
|
2
1
|
import initWasm, { Project, recvTaskMessageInWorker, sendTaskMessage, workerCreated, } from "../utoo";
|
|
3
2
|
import { cjs } from "./cjs";
|
|
4
3
|
const binding = {
|
|
@@ -13,11 +12,6 @@ export function startLoaderWorker() {
|
|
|
13
12
|
console.log(err);
|
|
14
13
|
throw err;
|
|
15
14
|
});
|
|
16
|
-
const sabClient = meta.sab
|
|
17
|
-
? new SabComClient(meta.sab, () => {
|
|
18
|
-
self.postMessage("sab_request");
|
|
19
|
-
})
|
|
20
|
-
: undefined;
|
|
21
15
|
// Initialize the thread-local state (tokio runtime).
|
|
22
16
|
// We don't need to pass threadWorkerUrl here because it's already stored in a global static in Rust.
|
|
23
17
|
Project.init("");
|
|
@@ -27,7 +21,6 @@ export function startLoaderWorker() {
|
|
|
27
21
|
cwd: meta.workerData.cwd,
|
|
28
22
|
projectRoot: meta.workerData.projectRoot,
|
|
29
23
|
binding,
|
|
30
|
-
sabClient,
|
|
31
24
|
fs: Project,
|
|
32
25
|
};
|
|
33
26
|
self.process = {
|
package/esm/worker.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as comlink from "comlink";
|
|
2
|
-
import { internalEndpoint } from "./
|
|
3
|
-
import { HandShake } from "./message";
|
|
2
|
+
import { internalEndpoint } from "./project/InternalProject";
|
|
3
|
+
import { HandShake } from "./utils/message";
|
|
4
4
|
const ConnectedPorts = new Set();
|
|
5
5
|
self.addEventListener("message", (e) => {
|
|
6
6
|
const port = e.ports[0];
|
package/package.json
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utoo/web",
|
|
3
|
-
"version": "1.2.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"module": "esm/index.js",
|
|
5
5
|
"types": "esm/index.d.ts",
|
|
6
6
|
"files": [
|
|
7
|
-
"esm
|
|
7
|
+
"esm"
|
|
8
8
|
],
|
|
9
9
|
"scripts": {
|
|
10
|
-
"install-toolchain": "cargo install wasm-bindgen-cli@0.2.104 && brew install binaryen",
|
|
10
|
+
"install-toolchain": "cargo install wasm-bindgen-cli@0.2.104 && brew install binaryen llvm",
|
|
11
11
|
"build-wasm": "cargo build -p utoo-wasm --target wasm32-unknown-unknown -Z build-std=panic_abort,std",
|
|
12
12
|
"build-wasm:pm": "cargo build -p utoo-wasm --target wasm32-unknown-unknown --no-default-features -Z build-std=panic_abort,std",
|
|
13
13
|
"bindgen-dev": "wasm-bindgen ../../target/wasm32-unknown-unknown/wasm-dev/utoo_wasm.wasm --out-dir src/utoo --out-name index --target web --debug --keep-debug --no-demangle",
|
|
14
14
|
"bindgen-build": "wasm-bindgen ../../target/wasm32-unknown-unknown/release/utoo_wasm.wasm --out-dir src/utoo --out-name index --target web",
|
|
15
15
|
"bindgen-build:local": "wasm-bindgen ../../target/wasm32-unknown-unknown/release-local/utoo_wasm.wasm --out-dir src/utoo --out-name index --target web",
|
|
16
16
|
"tsc": "rm -rf esm && tsc -p ./tsconfig.build.json",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
17
|
+
"copy-wasm": "cp src/utoo/index_bg.wasm esm/utoo",
|
|
18
|
+
"build:shared": "npx turbo run build --filter=@utoo/pack-shared",
|
|
19
|
+
"dev": "npm run build-wasm -- --profile wasm-dev && npm run bindgen-dev && npx turbo run tsc --filter=@utoo/web && npm run build-loaderWorker && npm run copy-wasm",
|
|
20
|
+
"dev:pm": "npm run build-wasm:pm -- --profile wasm-dev && npm run bindgen-dev && npm run tsc && npm run copy-wasm",
|
|
19
21
|
"wasm-opt": "wasm-opt src/utoo/index_bg.wasm -o esm/utoo/index_bg.wasm --enable-threads --enable-bulk-memory --enable-nontrapping-float-to-int -Oz",
|
|
20
22
|
"build": "npm run build-wasm -- --release && npm run bindgen-build && npm run tsc && npm run build-loaderWorker && npm run wasm-opt",
|
|
21
|
-
"build:local": "npm run build-wasm -- --profile release-local && npm run bindgen-build:local && npm run tsc && npm run build-loaderWorker &&
|
|
23
|
+
"build:local": "CC=$(brew --prefix llvm)/bin/clang CXX=$(brew --prefix llvm)/bin/clang++ npm run build-wasm -- --profile release-local && npm run bindgen-build:local && npm run build:shared && npm run tsc && npm run build-loaderWorker && npm run copy-wasm",
|
|
22
24
|
"build-loaderWorker": "node cli/umd.js -e ./src/webpackLoaders/worker.ts -o ./esm/loaderWorker.js -t webworker",
|
|
25
|
+
"clean": "rm -rf esm src/utoo",
|
|
23
26
|
"prepublishOnly": "turbo run build --filter=@utoo/web"
|
|
24
27
|
},
|
|
25
28
|
"dependencies": {
|
|
26
|
-
"@utoo/pack-shared": "^0.0.
|
|
29
|
+
"@utoo/pack-shared": "^0.0.8",
|
|
27
30
|
"comlink": "^4.4.2",
|
|
28
|
-
"micromatch": "^4.0.8",
|
|
29
31
|
"systemjs": "^6.15.1"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
32
|
-
"@types/micromatch": "^4.0.8",
|
|
33
34
|
"@types/systemjs": "^6.15.1",
|
|
34
35
|
"binaryen": "^125.0.0",
|
|
35
36
|
"node-stdlib-browser": "^1.3.1",
|
package/esm/sabcom.d.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
export declare const SAB_STATE_IDLE = 0;
|
|
2
|
-
export declare const SAB_STATE_REQUEST = 1;
|
|
3
|
-
export declare const SAB_STATE_RESPONSE = 2;
|
|
4
|
-
export declare const SAB_STATE_ERROR = 3;
|
|
5
|
-
export declare const SAB_OP_READ_FILE = 1;
|
|
6
|
-
export declare const SAB_OP_READ_DIR = 2;
|
|
7
|
-
export declare const SAB_OP_WRITE_FILE = 3;
|
|
8
|
-
export declare const SAB_OP_MKDIR = 4;
|
|
9
|
-
export declare const SAB_OP_RM = 5;
|
|
10
|
-
export declare const SAB_OP_RMDIR = 6;
|
|
11
|
-
export declare const SAB_OP_COPY_FILE = 7;
|
|
12
|
-
export declare const SAB_OP_STAT = 8;
|
|
13
|
-
export declare const STAT_TYPE_FILE = 0;
|
|
14
|
-
export declare const STAT_TYPE_DIR = 1;
|
|
15
|
-
export declare const SAB_INDEX_STATE = 0;
|
|
16
|
-
export declare const SAB_INDEX_OP = 1;
|
|
17
|
-
export declare const SAB_INDEX_DATA_LEN = 2;
|
|
18
|
-
export declare const SAB_DATA_OFFSET = 12;
|
|
19
|
-
export declare class SabComHost {
|
|
20
|
-
private sab;
|
|
21
|
-
private int32;
|
|
22
|
-
private uint8;
|
|
23
|
-
private dataView;
|
|
24
|
-
constructor(sab: SharedArrayBuffer);
|
|
25
|
-
readRequest(): {
|
|
26
|
-
op: number;
|
|
27
|
-
data: string;
|
|
28
|
-
};
|
|
29
|
-
writeResponse(data: Uint8Array | string): void;
|
|
30
|
-
writeError(message: string): void;
|
|
31
|
-
writeStat(type: number, size: bigint, atimeMs: number, mtimeMs: number, ctimeMs: number, birthtimeMs: number): void;
|
|
32
|
-
}
|
|
33
|
-
export declare class SabComClient {
|
|
34
|
-
private sab;
|
|
35
|
-
private notifyHost;
|
|
36
|
-
private int32;
|
|
37
|
-
private uint8;
|
|
38
|
-
private dataView;
|
|
39
|
-
constructor(sab: SharedArrayBuffer, notifyHost: () => void);
|
|
40
|
-
call(op: number, data: string): Uint8Array<ArrayBuffer>;
|
|
41
|
-
callStat(path: string): {
|
|
42
|
-
type: number;
|
|
43
|
-
size: bigint;
|
|
44
|
-
atimeMs: number;
|
|
45
|
-
mtimeMs: number;
|
|
46
|
-
ctimeMs: number;
|
|
47
|
-
birthtimeMs: number;
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
export interface SabFileSystem {
|
|
51
|
-
read(path: string): Promise<Uint8Array>;
|
|
52
|
-
readDir(path: string): Promise<any[]>;
|
|
53
|
-
writeString(path: string, content: string): Promise<void>;
|
|
54
|
-
createDirAll(path: string): Promise<void>;
|
|
55
|
-
createDir(path: string): Promise<void>;
|
|
56
|
-
metadata(path: string): Promise<any>;
|
|
57
|
-
removeFile(path: string): Promise<void>;
|
|
58
|
-
removeDir(path: string, recursive: boolean): Promise<void>;
|
|
59
|
-
copyFile(src: string, dst: string): Promise<void>;
|
|
60
|
-
}
|
|
61
|
-
export declare const handleSabRequest: (sabHost: SabComHost, fs: SabFileSystem) => Promise<void>;
|
package/esm/sabcom.js
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
export const SAB_STATE_IDLE = 0;
|
|
2
|
-
export const SAB_STATE_REQUEST = 1;
|
|
3
|
-
export const SAB_STATE_RESPONSE = 2;
|
|
4
|
-
export const SAB_STATE_ERROR = 3;
|
|
5
|
-
export const SAB_OP_READ_FILE = 1;
|
|
6
|
-
export const SAB_OP_READ_DIR = 2;
|
|
7
|
-
export const SAB_OP_WRITE_FILE = 3;
|
|
8
|
-
export const SAB_OP_MKDIR = 4;
|
|
9
|
-
export const SAB_OP_RM = 5;
|
|
10
|
-
export const SAB_OP_RMDIR = 6;
|
|
11
|
-
export const SAB_OP_COPY_FILE = 7;
|
|
12
|
-
export const SAB_OP_STAT = 8;
|
|
13
|
-
export const STAT_TYPE_FILE = 0;
|
|
14
|
-
export const STAT_TYPE_DIR = 1;
|
|
15
|
-
export const SAB_INDEX_STATE = 0;
|
|
16
|
-
export const SAB_INDEX_OP = 1;
|
|
17
|
-
export const SAB_INDEX_DATA_LEN = 2;
|
|
18
|
-
export const SAB_DATA_OFFSET = 12;
|
|
19
|
-
// Stat struct layout (starts at byte 12)
|
|
20
|
-
// type: Uint8 (1 byte) -> offset 0
|
|
21
|
-
// padding: 7 bytes
|
|
22
|
-
// size: BigUint64 (8 bytes) -> offset 8
|
|
23
|
-
// atimeMs: Float64 (8 bytes) -> offset 16
|
|
24
|
-
// mtimeMs: Float64 (8 bytes) -> offset 24
|
|
25
|
-
// ctimeMs: Float64 (8 bytes) -> offset 32
|
|
26
|
-
// birthtimeMs: Float64 (8 bytes) -> offset 40
|
|
27
|
-
const STAT_OFFSET_TYPE = 0;
|
|
28
|
-
const STAT_OFFSET_SIZE = 8;
|
|
29
|
-
const STAT_OFFSET_ATIME = 16;
|
|
30
|
-
const STAT_OFFSET_MTIME = 24;
|
|
31
|
-
const STAT_OFFSET_CTIME = 32;
|
|
32
|
-
const STAT_OFFSET_BIRTHTIME = 40;
|
|
33
|
-
// Layout:
|
|
34
|
-
// 0: State (Int32)
|
|
35
|
-
// 1: Op (Int32)
|
|
36
|
-
// 2: Data Length (Int32)
|
|
37
|
-
// 12...: Data (Uint8) - Start at byte 12 (3 * 4 bytes)
|
|
38
|
-
export class SabComHost {
|
|
39
|
-
constructor(sab) {
|
|
40
|
-
this.sab = sab;
|
|
41
|
-
this.int32 = new Int32Array(sab);
|
|
42
|
-
this.uint8 = new Uint8Array(sab);
|
|
43
|
-
this.dataView = new DataView(sab);
|
|
44
|
-
}
|
|
45
|
-
readRequest() {
|
|
46
|
-
const op = this.int32[SAB_INDEX_OP];
|
|
47
|
-
const len = this.int32[SAB_INDEX_DATA_LEN];
|
|
48
|
-
const data = new TextDecoder().decode(this.uint8.slice(SAB_DATA_OFFSET, SAB_DATA_OFFSET + len));
|
|
49
|
-
return { op, data };
|
|
50
|
-
}
|
|
51
|
-
writeResponse(data) {
|
|
52
|
-
if (typeof data === "string") {
|
|
53
|
-
data = new TextEncoder().encode(data);
|
|
54
|
-
}
|
|
55
|
-
// TODO: Check size overflow
|
|
56
|
-
this.int32[SAB_INDEX_DATA_LEN] = data.length;
|
|
57
|
-
this.uint8.set(data, SAB_DATA_OFFSET);
|
|
58
|
-
Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_RESPONSE);
|
|
59
|
-
Atomics.notify(this.int32, SAB_INDEX_STATE);
|
|
60
|
-
}
|
|
61
|
-
writeError(message) {
|
|
62
|
-
const data = new TextEncoder().encode(message);
|
|
63
|
-
this.int32[SAB_INDEX_DATA_LEN] = data.length;
|
|
64
|
-
this.uint8.set(data, SAB_DATA_OFFSET);
|
|
65
|
-
Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_ERROR);
|
|
66
|
-
Atomics.notify(this.int32, SAB_INDEX_STATE);
|
|
67
|
-
}
|
|
68
|
-
writeStat(type, size, atimeMs, mtimeMs, ctimeMs, birthtimeMs) {
|
|
69
|
-
const base = SAB_DATA_OFFSET;
|
|
70
|
-
this.dataView.setUint8(base + STAT_OFFSET_TYPE, type);
|
|
71
|
-
this.dataView.setBigUint64(base + STAT_OFFSET_SIZE, size, true);
|
|
72
|
-
this.dataView.setFloat64(base + STAT_OFFSET_ATIME, atimeMs, true);
|
|
73
|
-
this.dataView.setFloat64(base + STAT_OFFSET_MTIME, mtimeMs, true);
|
|
74
|
-
this.dataView.setFloat64(base + STAT_OFFSET_CTIME, ctimeMs, true);
|
|
75
|
-
this.dataView.setFloat64(base + STAT_OFFSET_BIRTHTIME, birthtimeMs, true);
|
|
76
|
-
Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_RESPONSE);
|
|
77
|
-
Atomics.notify(this.int32, SAB_INDEX_STATE);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
export class SabComClient {
|
|
81
|
-
constructor(sab, notifyHost) {
|
|
82
|
-
this.sab = sab;
|
|
83
|
-
this.notifyHost = notifyHost;
|
|
84
|
-
this.int32 = new Int32Array(sab);
|
|
85
|
-
this.uint8 = new Uint8Array(sab);
|
|
86
|
-
this.dataView = new DataView(sab);
|
|
87
|
-
}
|
|
88
|
-
call(op, data) {
|
|
89
|
-
const encoded = new TextEncoder().encode(data);
|
|
90
|
-
this.int32[SAB_INDEX_OP] = op;
|
|
91
|
-
this.int32[SAB_INDEX_DATA_LEN] = encoded.length;
|
|
92
|
-
this.uint8.set(encoded, SAB_DATA_OFFSET);
|
|
93
|
-
Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_REQUEST);
|
|
94
|
-
this.notifyHost();
|
|
95
|
-
Atomics.wait(this.int32, SAB_INDEX_STATE, SAB_STATE_REQUEST);
|
|
96
|
-
const state = Atomics.load(this.int32, SAB_INDEX_STATE);
|
|
97
|
-
if (state === SAB_STATE_ERROR) {
|
|
98
|
-
const len = this.int32[SAB_INDEX_DATA_LEN];
|
|
99
|
-
const msg = new TextDecoder().decode(this.uint8.slice(SAB_DATA_OFFSET, SAB_DATA_OFFSET + len));
|
|
100
|
-
throw new Error(msg);
|
|
101
|
-
}
|
|
102
|
-
const len = this.int32[SAB_INDEX_DATA_LEN];
|
|
103
|
-
return this.uint8.slice(SAB_DATA_OFFSET, SAB_DATA_OFFSET + len);
|
|
104
|
-
}
|
|
105
|
-
callStat(path) {
|
|
106
|
-
const encoded = new TextEncoder().encode(path);
|
|
107
|
-
this.int32[SAB_INDEX_OP] = SAB_OP_STAT;
|
|
108
|
-
this.int32[SAB_INDEX_DATA_LEN] = encoded.length;
|
|
109
|
-
this.uint8.set(encoded, SAB_DATA_OFFSET);
|
|
110
|
-
Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_REQUEST);
|
|
111
|
-
this.notifyHost();
|
|
112
|
-
Atomics.wait(this.int32, SAB_INDEX_STATE, SAB_STATE_REQUEST);
|
|
113
|
-
const state = Atomics.load(this.int32, SAB_INDEX_STATE);
|
|
114
|
-
if (state === SAB_STATE_ERROR) {
|
|
115
|
-
const len = this.int32[SAB_INDEX_DATA_LEN];
|
|
116
|
-
const msg = new TextDecoder().decode(this.uint8.slice(SAB_DATA_OFFSET, SAB_DATA_OFFSET + len));
|
|
117
|
-
throw new Error(msg);
|
|
118
|
-
}
|
|
119
|
-
const base = SAB_DATA_OFFSET;
|
|
120
|
-
return {
|
|
121
|
-
type: this.dataView.getUint8(base + STAT_OFFSET_TYPE),
|
|
122
|
-
size: this.dataView.getBigUint64(base + STAT_OFFSET_SIZE, true),
|
|
123
|
-
atimeMs: this.dataView.getFloat64(base + STAT_OFFSET_ATIME, true),
|
|
124
|
-
mtimeMs: this.dataView.getFloat64(base + STAT_OFFSET_MTIME, true),
|
|
125
|
-
ctimeMs: this.dataView.getFloat64(base + STAT_OFFSET_CTIME, true),
|
|
126
|
-
birthtimeMs: this.dataView.getFloat64(base + STAT_OFFSET_BIRTHTIME, true),
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
export const handleSabRequest = async (sabHost, fs) => {
|
|
131
|
-
const { op, data: path } = sabHost.readRequest();
|
|
132
|
-
try {
|
|
133
|
-
if (op === SAB_OP_READ_FILE) {
|
|
134
|
-
const bytes = await fs.read(path);
|
|
135
|
-
sabHost.writeResponse(bytes);
|
|
136
|
-
}
|
|
137
|
-
else if (op === SAB_OP_READ_DIR) {
|
|
138
|
-
const entries = await fs.readDir(path);
|
|
139
|
-
sabHost.writeResponse(JSON.stringify(entries.map((e) => e.toJSON())));
|
|
140
|
-
}
|
|
141
|
-
else if (op === SAB_OP_WRITE_FILE) {
|
|
142
|
-
const { path: filePath, data: fileContent } = JSON.parse(path);
|
|
143
|
-
// TODO: handle binary content (base64?)
|
|
144
|
-
await fs.writeString(filePath, fileContent);
|
|
145
|
-
sabHost.writeResponse("ok");
|
|
146
|
-
}
|
|
147
|
-
else if (op === SAB_OP_MKDIR) {
|
|
148
|
-
const { path: dirPath, recursive } = JSON.parse(path);
|
|
149
|
-
if (recursive) {
|
|
150
|
-
await fs.createDirAll(dirPath);
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
await fs.createDir(dirPath);
|
|
154
|
-
}
|
|
155
|
-
sabHost.writeResponse("ok");
|
|
156
|
-
}
|
|
157
|
-
else if (op === SAB_OP_RM) {
|
|
158
|
-
const { path: rmPath, recursive } = JSON.parse(path);
|
|
159
|
-
// Mimic internalProject.rm logic
|
|
160
|
-
const metadata = await fs.metadata(rmPath);
|
|
161
|
-
const json = metadata.toJSON
|
|
162
|
-
? metadata.toJSON()
|
|
163
|
-
: metadata;
|
|
164
|
-
const type = json.type;
|
|
165
|
-
if (type === "file") {
|
|
166
|
-
await fs.removeFile(rmPath);
|
|
167
|
-
}
|
|
168
|
-
else if (type === "directory") {
|
|
169
|
-
await fs.removeDir(rmPath, !!recursive);
|
|
170
|
-
}
|
|
171
|
-
sabHost.writeResponse("ok");
|
|
172
|
-
}
|
|
173
|
-
else if (op === SAB_OP_RMDIR) {
|
|
174
|
-
const { path: rmPath, recursive } = JSON.parse(path);
|
|
175
|
-
await fs.removeDir(rmPath, !!recursive);
|
|
176
|
-
sabHost.writeResponse("ok");
|
|
177
|
-
}
|
|
178
|
-
else if (op === SAB_OP_COPY_FILE) {
|
|
179
|
-
const { src, dst } = JSON.parse(path);
|
|
180
|
-
await fs.copyFile(src, dst);
|
|
181
|
-
sabHost.writeResponse("ok");
|
|
182
|
-
}
|
|
183
|
-
else if (op === SAB_OP_STAT) {
|
|
184
|
-
const metadata = await fs.metadata(path);
|
|
185
|
-
const json = metadata.toJSON
|
|
186
|
-
? metadata.toJSON()
|
|
187
|
-
: metadata;
|
|
188
|
-
const type = json.type === "directory" ? STAT_TYPE_DIR : STAT_TYPE_FILE;
|
|
189
|
-
const size = BigInt(json.file_size || 0);
|
|
190
|
-
const atimeMs = Number(json.atimeMs || 0);
|
|
191
|
-
const mtimeMs = Number(json.mtimeMs || 0);
|
|
192
|
-
const ctimeMs = Number(json.ctimeMs || 0);
|
|
193
|
-
const birthtimeMs = Number(json.birthtimeMs || 0);
|
|
194
|
-
sabHost.writeStat(type, size, atimeMs, mtimeMs, ctimeMs, birthtimeMs);
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
sabHost.writeError("Unknown op");
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
catch (e) {
|
|
201
|
-
sabHost.writeError(e.message);
|
|
202
|
-
}
|
|
203
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|