@utoo/web 1.0.0 → 1.0.2
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/esm/internalProject.d.ts +29 -0
- package/esm/internalProject.js +185 -0
- package/esm/project.d.ts +3 -2
- package/esm/project.js +4 -4
- package/esm/threadWorker.js +0 -6
- package/esm/type.d.ts +4 -2
- package/esm/utoo/index.d.ts +78 -0
- package/esm/utoo/index.js +248 -83
- package/esm/utoo/index_bg.wasm +0 -0
- package/esm/webpackLoaders/loaders/lessLoader/index.d.ts +3 -0
- package/esm/webpackLoaders/loaders/lessLoader/index.js +103 -0
- package/esm/webpackLoaders/loaders/lessLoader/options.json +67 -0
- package/esm/webpackLoaders/loaders/lessLoader/utils.d.ts +14 -0
- package/esm/webpackLoaders/loaders/lessLoader/utils.js +217 -0
- package/esm/webpackLoaders/worker/cjs.d.ts +2 -0
- package/esm/webpackLoaders/worker/cjs.js +77 -0
- package/esm/webpackLoaders/worker/index.d.ts +2 -0
- package/esm/webpackLoaders/worker/index.js +31 -0
- package/esm/webpackLoaders/worker/nodePolyFills.d.ts +14 -0
- package/esm/webpackLoaders/worker/nodePolyFills.js +24 -0
- package/esm/webpackLoaders/worker/type.d.ts +11 -0
- package/esm/webpackLoaders/worker/type.js +1 -0
- package/esm/webpackLoaders/workerContent.d.ts +2 -0
- package/esm/webpackLoaders/workerContent.js +1 -0
- package/esm/worker.js +2 -109
- package/package.json +15 -5
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { PackFile, ProjectEndpoint, ProjectOptions } from "./type";
|
|
2
|
+
import initWasm, { Project as ProjectInternal } from "./utoo";
|
|
3
|
+
declare class InternalEndpoint implements ProjectEndpoint {
|
|
4
|
+
projectInternal?: ProjectInternal;
|
|
5
|
+
wasmInit?: ReturnType<typeof initWasm>;
|
|
6
|
+
options?: Omit<ProjectOptions, "workerUrl" | "serviceWorker">;
|
|
7
|
+
mount(opt: Omit<ProjectOptions, "workerUrl" | "serviceWorker">): Promise<void>;
|
|
8
|
+
install(packageLock: string, maxConcurrentDownloads?: number): Promise<void>;
|
|
9
|
+
build(): Promise<any>;
|
|
10
|
+
readFile(path: string, encoding?: "utf8"): Promise<any>;
|
|
11
|
+
writeFile(path: string, content: string | Uint8Array, _encoding?: "utf8"): Promise<void>;
|
|
12
|
+
copyFile(src: string, dst: string): Promise<void>;
|
|
13
|
+
readdir(path: string, options?: {
|
|
14
|
+
recursive?: boolean;
|
|
15
|
+
}): Promise<any>;
|
|
16
|
+
mkdir(path: string, options?: {
|
|
17
|
+
recursive?: boolean;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
rm(path: string, options?: {
|
|
20
|
+
recursive?: boolean;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
rmdir(path: string, options?: {
|
|
23
|
+
recursive?: boolean;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
gzip(files: PackFile[]): Promise<Uint8Array<ArrayBufferLike>>;
|
|
26
|
+
sigMd5(content: Uint8Array): Promise<string>;
|
|
27
|
+
}
|
|
28
|
+
declare const internalEndpoint: InternalEndpoint;
|
|
29
|
+
export { internalEndpoint };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import initWasm, { init_log_filter, Project as ProjectInternal, recvPoolRequest, recvWorkerTermination, } from "./utoo";
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
import webpackLoadersCode from "./webpackLoaders/workerContent";
|
|
4
|
+
let nextWorkerId = 0;
|
|
5
|
+
const loaderWorkers = {};
|
|
6
|
+
async function getTurbopackLoaderAssets() {
|
|
7
|
+
const turbopackLoaderAssets = {};
|
|
8
|
+
const dirEntries = await internalEndpoint.projectInternal.readDir(".turbopack");
|
|
9
|
+
await Promise.all(dirEntries.map(async (entry) => {
|
|
10
|
+
// only collect .js files
|
|
11
|
+
if (entry.type === "file" && entry.name.endsWith(".js")) {
|
|
12
|
+
turbopackLoaderAssets[`./${entry.name}`] =
|
|
13
|
+
await internalEndpoint.projectInternal.readToString(`.turbopack/${entry.name}`);
|
|
14
|
+
}
|
|
15
|
+
}));
|
|
16
|
+
return turbopackLoaderAssets;
|
|
17
|
+
}
|
|
18
|
+
const createOrScalePool = async (binding, loadersImportMap) => {
|
|
19
|
+
while (true) {
|
|
20
|
+
try {
|
|
21
|
+
let poolOptions = await recvPoolRequest();
|
|
22
|
+
const { filename: entrypoint, maxConcurrency } = poolOptions;
|
|
23
|
+
const concurrency = Math.max(maxConcurrency, navigator.hardwareConcurrency);
|
|
24
|
+
const workers = loaderWorkers[entrypoint] || (loaderWorkers[entrypoint] = []);
|
|
25
|
+
if (workers.length < concurrency) {
|
|
26
|
+
for (let i = workers.length; i < concurrency; i++) {
|
|
27
|
+
nextWorkerId += 1;
|
|
28
|
+
const turbopackLoaderAssets = await getTurbopackLoaderAssets();
|
|
29
|
+
const blob = new Blob([webpackLoadersCode], {
|
|
30
|
+
type: "text/javascript",
|
|
31
|
+
});
|
|
32
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
33
|
+
const worker = new Worker(workerUrl);
|
|
34
|
+
worker.postMessage([
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
initWasm.__wbindgen_wasm_module,
|
|
37
|
+
binding.memory,
|
|
38
|
+
{
|
|
39
|
+
workerData: {
|
|
40
|
+
poolId: entrypoint,
|
|
41
|
+
workerId: nextWorkerId,
|
|
42
|
+
},
|
|
43
|
+
loaderAssets: {
|
|
44
|
+
importMaps: { ...turbopackLoaderAssets, ...loadersImportMap },
|
|
45
|
+
entrypoint: entrypoint.replace(".turbopack/", ""),
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
]);
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
worker.workerId = nextWorkerId;
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
workers.push(worker);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (workers.length > concurrency) {
|
|
56
|
+
const workersToStop = workers.splice(0, workers.length - concurrency);
|
|
57
|
+
workersToStop.forEach((worker) => worker.terminate());
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (_e) {
|
|
61
|
+
// rust channel closed. do nothing
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const waitingForWorkerTermination = async () => {
|
|
67
|
+
while (true) {
|
|
68
|
+
try {
|
|
69
|
+
const { filename, workerId } = await recvWorkerTermination();
|
|
70
|
+
const workers = loaderWorkers[filename];
|
|
71
|
+
const workerIdx = workers.findIndex((worker) => worker.workerId === workerId);
|
|
72
|
+
if (workerIdx > -1) {
|
|
73
|
+
const worker = workers.splice(workerIdx, 1);
|
|
74
|
+
worker[0].terminate();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (_e) {
|
|
78
|
+
// rust channel closed. do nothing
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
class InternalEndpoint {
|
|
84
|
+
// This should be called only once
|
|
85
|
+
async mount(opt) {
|
|
86
|
+
var _a;
|
|
87
|
+
this.options = opt;
|
|
88
|
+
const { cwd, wasmUrl, threadWorkerUrl, logFilter } = opt;
|
|
89
|
+
(_a = this.wasmInit) !== null && _a !== void 0 ? _a : (this.wasmInit = initWasm(wasmUrl));
|
|
90
|
+
await this.wasmInit;
|
|
91
|
+
// Initialize log filter after wasm init
|
|
92
|
+
const filter = logFilter || "pack_core=info,pack_api=info,utoo_wasm=info";
|
|
93
|
+
init_log_filter(filter);
|
|
94
|
+
this.projectInternal = new ProjectInternal(cwd, threadWorkerUrl);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
async install(packageLock, maxConcurrentDownloads) {
|
|
98
|
+
await this.wasmInit;
|
|
99
|
+
await this.projectInternal.install(packageLock, maxConcurrentDownloads);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
async build() {
|
|
103
|
+
var _a;
|
|
104
|
+
const binding = await this.wasmInit;
|
|
105
|
+
createOrScalePool(binding, (_a = this.options) === null || _a === void 0 ? void 0 : _a.loadersImportMap);
|
|
106
|
+
waitingForWorkerTermination();
|
|
107
|
+
return await this.projectInternal.build();
|
|
108
|
+
}
|
|
109
|
+
async readFile(path, encoding) {
|
|
110
|
+
await this.wasmInit;
|
|
111
|
+
let ret;
|
|
112
|
+
if (encoding === "utf8") {
|
|
113
|
+
ret = await this.projectInternal.readToString(path);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
ret = await this.projectInternal.read(path);
|
|
117
|
+
}
|
|
118
|
+
return ret;
|
|
119
|
+
}
|
|
120
|
+
async writeFile(path, content, _encoding) {
|
|
121
|
+
await this.wasmInit;
|
|
122
|
+
if (typeof content === "string") {
|
|
123
|
+
return await this.projectInternal.writeString(path, content);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
return await this.projectInternal.write(path, content);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async copyFile(src, dst) {
|
|
130
|
+
await this.wasmInit;
|
|
131
|
+
return await this.projectInternal.copyFile(src, dst);
|
|
132
|
+
}
|
|
133
|
+
async readdir(path, options) {
|
|
134
|
+
await this.wasmInit;
|
|
135
|
+
const dirEntries = (options === null || options === void 0 ? void 0 : options.recursive)
|
|
136
|
+
? await this.projectInternal.readDir(path)
|
|
137
|
+
: // TODO: support recursive readDirAll
|
|
138
|
+
await this.projectInternal.readDir(path);
|
|
139
|
+
const rawDirents = dirEntries.map((e) => {
|
|
140
|
+
const dir = e.toJSON();
|
|
141
|
+
return {
|
|
142
|
+
name: dir.name,
|
|
143
|
+
type: dir.type,
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
// WARN: This is a hack, functions can not be structurally cloned
|
|
147
|
+
return rawDirents;
|
|
148
|
+
}
|
|
149
|
+
async mkdir(path, options) {
|
|
150
|
+
await this.wasmInit;
|
|
151
|
+
if (options === null || options === void 0 ? void 0 : options.recursive) {
|
|
152
|
+
return await this.projectInternal.createDirAll(path);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
return await this.projectInternal.createDir(path);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async rm(path, options) {
|
|
159
|
+
await this.wasmInit;
|
|
160
|
+
let metadata = (await this.projectInternal.metadata(path)).toJSON();
|
|
161
|
+
switch (metadata.type) {
|
|
162
|
+
case "file":
|
|
163
|
+
return await this.projectInternal.removeFile(path);
|
|
164
|
+
case "directory":
|
|
165
|
+
return await this.projectInternal.removeDir(path, !!(options === null || options === void 0 ? void 0 : options.recursive));
|
|
166
|
+
default:
|
|
167
|
+
// nothing to remove now
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async rmdir(path, options) {
|
|
172
|
+
await this.wasmInit;
|
|
173
|
+
return await this.projectInternal.removeDir(path, !!(options === null || options === void 0 ? void 0 : options.recursive));
|
|
174
|
+
}
|
|
175
|
+
async gzip(files) {
|
|
176
|
+
await this.wasmInit;
|
|
177
|
+
return await this.projectInternal.gzip(files);
|
|
178
|
+
}
|
|
179
|
+
async sigMd5(content) {
|
|
180
|
+
await this.wasmInit;
|
|
181
|
+
return await this.projectInternal.sigMd5(content);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const internalEndpoint = new InternalEndpoint();
|
|
185
|
+
export { internalEndpoint };
|
package/esm/project.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { BuildOutput, Dirent, PackFile, ProjectEndpoint, ProjectOptions } from "./type";
|
|
1
|
+
import { BuildOutput, Dirent, PackFile, ProjectEndpoint, ProjectOptions, ServiceWorkerOptions } from "./type";
|
|
2
2
|
export declare class Project implements ProjectEndpoint {
|
|
3
3
|
#private;
|
|
4
|
-
|
|
4
|
+
readonly cwd: string;
|
|
5
|
+
readonly serviceWorkerOptions?: ServiceWorkerOptions;
|
|
5
6
|
private remote;
|
|
6
7
|
constructor(options: ProjectOptions);
|
|
7
8
|
private connectWorker;
|
package/esm/project.js
CHANGED
|
@@ -22,14 +22,13 @@ export class Project {
|
|
|
22
22
|
constructor(options) {
|
|
23
23
|
var _a, _b;
|
|
24
24
|
_Project_mount.set(this, void 0);
|
|
25
|
-
const { cwd, workerUrl, wasmUrl, threadWorkerUrl, serviceWorker, logFilter, } = options;
|
|
25
|
+
const { cwd, workerUrl, wasmUrl, threadWorkerUrl, serviceWorker, logFilter, loadersImportMap, } = options;
|
|
26
|
+
this.cwd = cwd;
|
|
26
27
|
this.serviceWorkerOptions = serviceWorker;
|
|
27
28
|
const { port1, port2 } = new MessageChannel();
|
|
28
29
|
(_a = this.remote) !== null && _a !== void 0 ? _a : (this.remote = comlink.wrap(port1));
|
|
29
30
|
if (!ProjectWorker) {
|
|
30
|
-
ProjectWorker = workerUrl
|
|
31
|
-
? new Worker(workerUrl)
|
|
32
|
-
: new Worker(new URL("./worker", import.meta.url));
|
|
31
|
+
ProjectWorker = new Worker(workerUrl);
|
|
33
32
|
window.addEventListener("message", (e) => {
|
|
34
33
|
this.connectWorker(e);
|
|
35
34
|
});
|
|
@@ -44,6 +43,7 @@ export class Project {
|
|
|
44
43
|
cwd,
|
|
45
44
|
wasmUrl,
|
|
46
45
|
threadWorkerUrl,
|
|
46
|
+
loadersImportMap,
|
|
47
47
|
logFilter,
|
|
48
48
|
}), "f");
|
|
49
49
|
}
|
package/esm/threadWorker.js
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import initWasm from "./utoo";
|
|
2
|
-
// Read logFilter from URL query string and set to globalThis
|
|
3
|
-
const urlParams = new URLSearchParams(self.location.search);
|
|
4
|
-
const logFilter = urlParams.get("logFilter");
|
|
5
|
-
if (logFilter) {
|
|
6
|
-
globalThis.__UTOO_LOG_FILTER__ = logFilter;
|
|
7
|
-
}
|
|
8
2
|
// this is for wasm_thread to spawn new worker thread.
|
|
9
3
|
// see: https://github.com/utooland/wasm_thread/blob/94438ff771ee0a6a55d79e49a655707970acb615/src/wasm32/js/web_worker.js#L10
|
|
10
4
|
self.wasm_bindgen = initWasm;
|
package/esm/type.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Issue } from "@utoo/pack-shared";
|
|
2
|
-
import { DirEntryType } from "./utoo";
|
|
2
|
+
import initWasm, { DirEntryType } from "./utoo";
|
|
3
3
|
export interface RawDirent {
|
|
4
4
|
name: string;
|
|
5
5
|
type: DirEntryType;
|
|
@@ -42,13 +42,15 @@ export interface ProjectEndpoint {
|
|
|
42
42
|
}
|
|
43
43
|
export interface ProjectOptions {
|
|
44
44
|
cwd: string;
|
|
45
|
-
workerUrl
|
|
45
|
+
workerUrl: string;
|
|
46
46
|
threadWorkerUrl: string;
|
|
47
47
|
wasmUrl?: string;
|
|
48
48
|
serviceWorker?: ServiceWorkerOptions;
|
|
49
49
|
logFilter?: string;
|
|
50
|
+
loadersImportMap?: Record<string, string>;
|
|
50
51
|
}
|
|
51
52
|
export interface ServiceWorkerOptions {
|
|
52
53
|
url: string;
|
|
53
54
|
scope: string;
|
|
54
55
|
}
|
|
56
|
+
export type Binding = Awaited<ReturnType<typeof initWasm>>;
|
package/esm/utoo/index.d.ts
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @returns {Promise<WorkerTermination>}
|
|
3
|
+
*/
|
|
4
|
+
export function recvWorkerTermination(): Promise<WorkerTermination>;
|
|
5
|
+
/**
|
|
6
|
+
* @param {number} task_id
|
|
7
|
+
* @param {number} worker_id
|
|
8
|
+
* @returns {Promise<void>}
|
|
9
|
+
*/
|
|
10
|
+
export function notifyWorkerAck(task_id: number, worker_id: number): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* @param {number} task_id
|
|
13
|
+
* @param {string} message
|
|
14
|
+
* @returns {Promise<void>}
|
|
15
|
+
*/
|
|
16
|
+
export function sendTaskMessage(task_id: number, message: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* @param {number} worker_id
|
|
19
|
+
* @returns {Promise<string>}
|
|
20
|
+
*/
|
|
21
|
+
export function recvMessageInWorker(worker_id: number): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} pool_id
|
|
24
|
+
* @returns {Promise<number>}
|
|
25
|
+
*/
|
|
26
|
+
export function recvWorkerRequest(pool_id: string): Promise<number>;
|
|
27
|
+
/**
|
|
28
|
+
* @returns {Promise<PoolOptions>}
|
|
29
|
+
*/
|
|
30
|
+
export function recvPoolRequest(): Promise<PoolOptions>;
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} filter
|
|
33
|
+
*/
|
|
34
|
+
export function init_log_filter(filter: string): void;
|
|
1
35
|
export function init_pack(): void;
|
|
2
36
|
/**
|
|
3
37
|
* Entry point for web workers
|
|
@@ -45,6 +79,28 @@ export class Metadata {
|
|
|
45
79
|
__wbg_ptr: number | undefined;
|
|
46
80
|
free(): void;
|
|
47
81
|
}
|
|
82
|
+
export class PoolOptions {
|
|
83
|
+
static __wrap(ptr: any): any;
|
|
84
|
+
__destroy_into_raw(): number | undefined;
|
|
85
|
+
__wbg_ptr: number | undefined;
|
|
86
|
+
free(): void;
|
|
87
|
+
/**
|
|
88
|
+
* @param {string} arg0
|
|
89
|
+
*/
|
|
90
|
+
set filename(arg0: string);
|
|
91
|
+
/**
|
|
92
|
+
* @returns {string}
|
|
93
|
+
*/
|
|
94
|
+
get filename(): string;
|
|
95
|
+
/**
|
|
96
|
+
* @param {number} arg0
|
|
97
|
+
*/
|
|
98
|
+
set maxConcurrency(arg0: number);
|
|
99
|
+
/**
|
|
100
|
+
* @returns {number}
|
|
101
|
+
*/
|
|
102
|
+
get maxConcurrency(): number;
|
|
103
|
+
}
|
|
48
104
|
export class Project {
|
|
49
105
|
/**
|
|
50
106
|
* @param {string} cwd
|
|
@@ -141,6 +197,28 @@ export class Project {
|
|
|
141
197
|
*/
|
|
142
198
|
copyFile(src: string, dst: string): Promise<void>;
|
|
143
199
|
}
|
|
200
|
+
export class WorkerTermination {
|
|
201
|
+
static __wrap(ptr: any): any;
|
|
202
|
+
__destroy_into_raw(): number | undefined;
|
|
203
|
+
__wbg_ptr: number | undefined;
|
|
204
|
+
free(): void;
|
|
205
|
+
/**
|
|
206
|
+
* @param {string} arg0
|
|
207
|
+
*/
|
|
208
|
+
set filename(arg0: string);
|
|
209
|
+
/**
|
|
210
|
+
* @returns {string}
|
|
211
|
+
*/
|
|
212
|
+
get filename(): string;
|
|
213
|
+
/**
|
|
214
|
+
* @param {number} arg0
|
|
215
|
+
*/
|
|
216
|
+
set workerId(arg0: number);
|
|
217
|
+
/**
|
|
218
|
+
* @returns {number}
|
|
219
|
+
*/
|
|
220
|
+
get workerId(): number;
|
|
221
|
+
}
|
|
144
222
|
export default __wbg_init;
|
|
145
223
|
export function initSync(module: any, memory: any): any;
|
|
146
224
|
declare function __wbg_init(module_or_path: any, memory: any): Promise<any>;
|