@open-wxa/wxa-runner-core 0.3.1 → 0.4.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 +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/runtime/host.js +222 -169
- package/dist/runtime/host.js.map +1 -1
- package/package.json +4 -4
package/dist/runtime/host.js
CHANGED
|
@@ -205,6 +205,158 @@
|
|
|
205
205
|
};
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
// src/runtime/host/api/tempFiles.ts
|
|
209
|
+
var TEMP_DIR = "/__wxa__/tmp";
|
|
210
|
+
async function saveTempFile(data, type) {
|
|
211
|
+
const res = await fetch(`${TEMP_DIR}?type=${encodeURIComponent(type)}`, { method: "POST", body: data });
|
|
212
|
+
if (!res.ok) throw new Error(await res.text());
|
|
213
|
+
const { url } = await res.json();
|
|
214
|
+
return url;
|
|
215
|
+
}
|
|
216
|
+
function tempFileRootPath(url) {
|
|
217
|
+
const prefix = `${location.origin}${TEMP_DIR}/`;
|
|
218
|
+
return url.startsWith(prefix) ? url.slice(location.origin.length) : url;
|
|
219
|
+
}
|
|
220
|
+
function tempFileType(name, mimeType, fallback) {
|
|
221
|
+
const fromName = /\.([a-z\d]+)$/i.exec(name)?.[1];
|
|
222
|
+
const fromType = /^[a-z]+\/([a-z\d]+)\s*(;|$)/i.exec(mimeType)?.[1];
|
|
223
|
+
return (fromName || fromType || fallback).toLowerCase();
|
|
224
|
+
}
|
|
225
|
+
function isTempFile(filePath) {
|
|
226
|
+
return typeof filePath === "string" && filePath.startsWith(`${location.origin}${TEMP_DIR}/`);
|
|
227
|
+
}
|
|
228
|
+
async function tempFileSize(url) {
|
|
229
|
+
const res = await fetch(url, { method: "HEAD" });
|
|
230
|
+
return res.ok ? Number(res.headers.get("content-length")) : null;
|
|
231
|
+
}
|
|
232
|
+
async function removeTempFile(url) {
|
|
233
|
+
await fetch(url, { method: "DELETE" });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/runtime/host/api/fs.ts
|
|
237
|
+
var DIR_MODE = 16877;
|
|
238
|
+
var FILE_MODE = 33188;
|
|
239
|
+
var MemoryFileSystem = class {
|
|
240
|
+
constructor() {
|
|
241
|
+
this.nodes = /* @__PURE__ */ new Map([["/", { dir: true, data: "", mtime: Date.now() }]]);
|
|
242
|
+
}
|
|
243
|
+
normalize(filePath) {
|
|
244
|
+
const stripped = String(filePath || "").replace(/^[a-z]+:\/\/[^/]*/i, "");
|
|
245
|
+
const parts = [];
|
|
246
|
+
for (const part of stripped.split("/")) {
|
|
247
|
+
if (!part || part === ".") continue;
|
|
248
|
+
if (part === "..") parts.pop();
|
|
249
|
+
else parts.push(part);
|
|
250
|
+
}
|
|
251
|
+
return "/" + parts.join("/");
|
|
252
|
+
}
|
|
253
|
+
stat(filePath) {
|
|
254
|
+
return this.nodes.get(this.normalize(filePath));
|
|
255
|
+
}
|
|
256
|
+
mkdir(dirPath, recursive = false) {
|
|
257
|
+
const target = this.normalize(dirPath);
|
|
258
|
+
if (this.nodes.has(target)) throw new Error(`file already exists ${dirPath}`);
|
|
259
|
+
const parent = target.slice(0, target.lastIndexOf("/")) || "/";
|
|
260
|
+
if (!this.nodes.get(parent)?.dir) {
|
|
261
|
+
if (!recursive) throw new Error(`no such file or directory ${dirPath}`);
|
|
262
|
+
this.mkdir(parent, true);
|
|
263
|
+
}
|
|
264
|
+
this.nodes.set(target, { dir: true, data: "", mtime: Date.now() });
|
|
265
|
+
}
|
|
266
|
+
write(filePath, data, append = false) {
|
|
267
|
+
const target = this.normalize(filePath);
|
|
268
|
+
const parent = target.slice(0, target.lastIndexOf("/")) || "/";
|
|
269
|
+
if (!this.nodes.get(parent)?.dir) throw new Error(`no such file or directory ${filePath}`);
|
|
270
|
+
const existing = this.nodes.get(target);
|
|
271
|
+
if (existing?.dir) throw new Error(`illegal operation on a directory ${filePath}`);
|
|
272
|
+
this.nodes.set(target, { dir: false, data: append && existing ? existing.data + data : data, mtime: Date.now() });
|
|
273
|
+
}
|
|
274
|
+
read(filePath) {
|
|
275
|
+
const node = this.stat(filePath);
|
|
276
|
+
if (!node) throw new Error(`no such file or directory, open ${filePath}`);
|
|
277
|
+
if (node.dir) throw new Error(`illegal operation on a directory ${filePath}`);
|
|
278
|
+
return node.data;
|
|
279
|
+
}
|
|
280
|
+
readdir(dirPath) {
|
|
281
|
+
const target = this.normalize(dirPath);
|
|
282
|
+
if (!this.nodes.get(target)?.dir) throw new Error(`no such file or directory ${dirPath}`);
|
|
283
|
+
const prefix = target === "/" ? "/" : target + "/";
|
|
284
|
+
return [...this.nodes.keys()].filter((key) => key.startsWith(prefix) && key !== target && !key.slice(prefix.length).includes("/")).map((key) => key.slice(prefix.length));
|
|
285
|
+
}
|
|
286
|
+
remove(filePath, options) {
|
|
287
|
+
const target = this.normalize(filePath);
|
|
288
|
+
const node = this.nodes.get(target);
|
|
289
|
+
if (!node) throw new Error(`no such file or directory ${filePath}`);
|
|
290
|
+
if (node.dir !== options.dir) throw new Error(options.dir ? `not a directory ${filePath}` : `operation not permitted ${filePath}`);
|
|
291
|
+
if (node.dir) {
|
|
292
|
+
const children = this.readdir(target);
|
|
293
|
+
if (children.length && !options.recursive) throw new Error(`directory not empty ${filePath}`);
|
|
294
|
+
for (const key of [...this.nodes.keys()]) if (key.startsWith(target + "/")) this.nodes.delete(key);
|
|
295
|
+
}
|
|
296
|
+
this.nodes.delete(target);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
function createFileSystemApis() {
|
|
300
|
+
const fs = new MemoryFileSystem();
|
|
301
|
+
const guard = (api, action) => {
|
|
302
|
+
try {
|
|
303
|
+
return ok(api, action() || {});
|
|
304
|
+
} catch (error) {
|
|
305
|
+
return fail(api, error.message);
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
const statResult = (node) => {
|
|
309
|
+
const stats = {
|
|
310
|
+
mode: node.dir ? DIR_MODE : FILE_MODE,
|
|
311
|
+
size: node.data.length,
|
|
312
|
+
lastAccessedTime: Math.floor(node.mtime / 1e3),
|
|
313
|
+
lastModifiedTime: Math.floor(node.mtime / 1e3)
|
|
314
|
+
};
|
|
315
|
+
return { stats, ...stats };
|
|
316
|
+
};
|
|
317
|
+
const readMemoryFile = (args, { api }) => guard(api, () => ({ data: fs.read(args.filePath) }));
|
|
318
|
+
const apis = {
|
|
319
|
+
access: (args, { api }) => fs.stat(args.path) ? ok(api) : fail(api, `no such file or directory ${args.path}`),
|
|
320
|
+
stat: (args, { api }) => {
|
|
321
|
+
const node = fs.stat(args.path);
|
|
322
|
+
return node ? ok(api, statResult(node)) : fail(api, `no such file or directory ${args.path}`);
|
|
323
|
+
},
|
|
324
|
+
mkdir: (args, { api }) => guard(api, () => fs.mkdir(args.dirPath, !!args.recursive)),
|
|
325
|
+
writeFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ""))),
|
|
326
|
+
appendFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ""), true)),
|
|
327
|
+
readdir: (args, { api }) => guard(api, () => ({ files: fs.readdir(args.dirPath) })),
|
|
328
|
+
unlink: (args, { api }) => guard(api, () => fs.remove(args.filePath, { dir: false })),
|
|
329
|
+
rmdir: (args, { api }) => guard(api, () => fs.remove(args.dirPath, { dir: true, recursive: !!args.recursive })),
|
|
330
|
+
getFileInfo: (args, { api }) => {
|
|
331
|
+
if (isTempFile(args.filePath)) {
|
|
332
|
+
return tempFileSize(args.filePath).then((size) => size === null ? fail(api, "file not exist") : ok(api, { size }));
|
|
333
|
+
}
|
|
334
|
+
const node = fs.stat(args.filePath);
|
|
335
|
+
return node ? ok(api, { size: node.data.length }) : fail(api, "file not exist");
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
for (const name of Object.keys(apis)) apis[name + "Sync"] = apis[name];
|
|
339
|
+
return {
|
|
340
|
+
...apis,
|
|
341
|
+
fs_appendFile: apis.appendFile,
|
|
342
|
+
// 不带协议的是代码包里的文件,要向开发服务器取;readFileSync 同步返回不了,只读内存文件系统。
|
|
343
|
+
// 内存文件系统的路径去掉了协议,不能先在里面找:用户目录下的同名文件会顶替代码包里的
|
|
344
|
+
readFile: (args, context) => /^[a-z]+:\/\//i.test(String(args.filePath)) ? readMemoryFile(args, context) : readPackageFile(fs.normalize(args.filePath), args.encoding).then(
|
|
345
|
+
(data) => ok(context.api, { data }),
|
|
346
|
+
(error) => fail(context.api, error.message)
|
|
347
|
+
),
|
|
348
|
+
readFileSync: readMemoryFile
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
async function readPackageFile(filePath, encoding) {
|
|
352
|
+
if (encoding !== void 0 && encoding !== "utf8" && encoding !== "utf-8") {
|
|
353
|
+
throw new Error(`\u8BFB\u53D6\u4EE3\u7801\u5305\u91CC\u7684\u6587\u4EF6\u53EA\u652F\u6301 utf8 \u7F16\u7801\uFF0C\u6216\u4E0D\u6307\u5B9A\u7F16\u7801\u5F97\u5230 ArrayBuffer\uFF0C\u4E0D\u652F\u6301 ${encoding}`);
|
|
354
|
+
}
|
|
355
|
+
const response = await fetch(filePath.split("/").map(encodeURIComponent).join("/"));
|
|
356
|
+
if (!response.ok) throw new Error(`no such file or directory, open ${filePath}`);
|
|
357
|
+
return encoding ? response.text() : response.arrayBuffer();
|
|
358
|
+
}
|
|
359
|
+
|
|
208
360
|
// src/runtime/syncScript.ts
|
|
209
361
|
function readSync(url) {
|
|
210
362
|
const xhr = new XMLHttpRequest();
|
|
@@ -277,34 +429,6 @@
|
|
|
277
429
|
}
|
|
278
430
|
};
|
|
279
431
|
|
|
280
|
-
// src/runtime/host/api/tempFiles.ts
|
|
281
|
-
var TEMP_DIR = "/__wxa__/tmp";
|
|
282
|
-
async function saveTempFile(data, type) {
|
|
283
|
-
const res = await fetch(`${TEMP_DIR}?type=${encodeURIComponent(type)}`, { method: "POST", body: data });
|
|
284
|
-
if (!res.ok) throw new Error(await res.text());
|
|
285
|
-
const { url } = await res.json();
|
|
286
|
-
return url;
|
|
287
|
-
}
|
|
288
|
-
function tempFileRootPath(url) {
|
|
289
|
-
const prefix = `${location.origin}${TEMP_DIR}/`;
|
|
290
|
-
return url.startsWith(prefix) ? url.slice(location.origin.length) : url;
|
|
291
|
-
}
|
|
292
|
-
function tempFileType(name, mimeType, fallback) {
|
|
293
|
-
const fromName = /\.([a-z\d]+)$/i.exec(name)?.[1];
|
|
294
|
-
const fromType = /^[a-z]+\/([a-z\d]+)\s*(;|$)/i.exec(mimeType)?.[1];
|
|
295
|
-
return (fromName || fromType || fallback).toLowerCase();
|
|
296
|
-
}
|
|
297
|
-
function isTempFile(filePath) {
|
|
298
|
-
return typeof filePath === "string" && filePath.startsWith(`${location.origin}${TEMP_DIR}/`);
|
|
299
|
-
}
|
|
300
|
-
async function tempFileSize(url) {
|
|
301
|
-
const res = await fetch(url, { method: "HEAD" });
|
|
302
|
-
return res.ok ? Number(res.headers.get("content-length")) : null;
|
|
303
|
-
}
|
|
304
|
-
async function removeTempFile(url) {
|
|
305
|
-
await fetch(url, { method: "DELETE" });
|
|
306
|
-
}
|
|
307
|
-
|
|
308
432
|
// src/runtime/host/api/media.ts
|
|
309
433
|
var SOURCES = ["camera", "album"];
|
|
310
434
|
var SOURCE_LABELS = { camera: "\u62CD\u6444", album: "\u4ECE\u624B\u673A\u76F8\u518C\u9009\u62E9" };
|
|
@@ -380,70 +504,7 @@
|
|
|
380
504
|
}
|
|
381
505
|
|
|
382
506
|
// src/runtime/host/api/misc.ts
|
|
383
|
-
var DIR_MODE = 16877;
|
|
384
|
-
var FILE_MODE = 33188;
|
|
385
|
-
var MemoryFileSystem = class {
|
|
386
|
-
constructor() {
|
|
387
|
-
this.nodes = /* @__PURE__ */ new Map([["/", { dir: true, data: "", mtime: Date.now() }]]);
|
|
388
|
-
}
|
|
389
|
-
normalize(filePath) {
|
|
390
|
-
const stripped = String(filePath || "").replace(/^[a-z]+:\/\/[^/]*/i, "");
|
|
391
|
-
const parts = [];
|
|
392
|
-
for (const part of stripped.split("/")) {
|
|
393
|
-
if (!part || part === ".") continue;
|
|
394
|
-
if (part === "..") parts.pop();
|
|
395
|
-
else parts.push(part);
|
|
396
|
-
}
|
|
397
|
-
return "/" + parts.join("/");
|
|
398
|
-
}
|
|
399
|
-
stat(filePath) {
|
|
400
|
-
return this.nodes.get(this.normalize(filePath));
|
|
401
|
-
}
|
|
402
|
-
mkdir(dirPath, recursive = false) {
|
|
403
|
-
const target = this.normalize(dirPath);
|
|
404
|
-
if (this.nodes.has(target)) throw new Error(`file already exists ${dirPath}`);
|
|
405
|
-
const parent = target.slice(0, target.lastIndexOf("/")) || "/";
|
|
406
|
-
if (!this.nodes.get(parent)?.dir) {
|
|
407
|
-
if (!recursive) throw new Error(`no such file or directory ${dirPath}`);
|
|
408
|
-
this.mkdir(parent, true);
|
|
409
|
-
}
|
|
410
|
-
this.nodes.set(target, { dir: true, data: "", mtime: Date.now() });
|
|
411
|
-
}
|
|
412
|
-
write(filePath, data, append = false) {
|
|
413
|
-
const target = this.normalize(filePath);
|
|
414
|
-
const parent = target.slice(0, target.lastIndexOf("/")) || "/";
|
|
415
|
-
if (!this.nodes.get(parent)?.dir) throw new Error(`no such file or directory ${filePath}`);
|
|
416
|
-
const existing = this.nodes.get(target);
|
|
417
|
-
if (existing?.dir) throw new Error(`illegal operation on a directory ${filePath}`);
|
|
418
|
-
this.nodes.set(target, { dir: false, data: append && existing ? existing.data + data : data, mtime: Date.now() });
|
|
419
|
-
}
|
|
420
|
-
read(filePath) {
|
|
421
|
-
const node = this.stat(filePath);
|
|
422
|
-
if (!node) throw new Error(`no such file or directory, open ${filePath}`);
|
|
423
|
-
if (node.dir) throw new Error(`illegal operation on a directory ${filePath}`);
|
|
424
|
-
return node.data;
|
|
425
|
-
}
|
|
426
|
-
readdir(dirPath) {
|
|
427
|
-
const target = this.normalize(dirPath);
|
|
428
|
-
if (!this.nodes.get(target)?.dir) throw new Error(`no such file or directory ${dirPath}`);
|
|
429
|
-
const prefix = target === "/" ? "/" : target + "/";
|
|
430
|
-
return [...this.nodes.keys()].filter((key) => key.startsWith(prefix) && key !== target && !key.slice(prefix.length).includes("/")).map((key) => key.slice(prefix.length));
|
|
431
|
-
}
|
|
432
|
-
remove(filePath, options) {
|
|
433
|
-
const target = this.normalize(filePath);
|
|
434
|
-
const node = this.nodes.get(target);
|
|
435
|
-
if (!node) throw new Error(`no such file or directory ${filePath}`);
|
|
436
|
-
if (node.dir !== options.dir) throw new Error(options.dir ? `not a directory ${filePath}` : `operation not permitted ${filePath}`);
|
|
437
|
-
if (node.dir) {
|
|
438
|
-
const children = this.readdir(target);
|
|
439
|
-
if (children.length && !options.recursive) throw new Error(`directory not empty ${filePath}`);
|
|
440
|
-
for (const key of [...this.nodes.keys()]) if (key.startsWith(target + "/")) this.nodes.delete(key);
|
|
441
|
-
}
|
|
442
|
-
this.nodes.delete(target);
|
|
443
|
-
}
|
|
444
|
-
};
|
|
445
507
|
function createMiscApis(appid, options) {
|
|
446
|
-
const fs = new MemoryFileSystem();
|
|
447
508
|
const realLogin = async (api, url) => {
|
|
448
509
|
try {
|
|
449
510
|
return await postDevServer(url);
|
|
@@ -452,54 +513,7 @@
|
|
|
452
513
|
throw error;
|
|
453
514
|
}
|
|
454
515
|
};
|
|
455
|
-
const guard = (api, action) => {
|
|
456
|
-
try {
|
|
457
|
-
return ok(api, action() || {});
|
|
458
|
-
} catch (error) {
|
|
459
|
-
return fail(api, error.message);
|
|
460
|
-
}
|
|
461
|
-
};
|
|
462
|
-
const statResult = (node) => {
|
|
463
|
-
const stats = {
|
|
464
|
-
mode: node.dir ? DIR_MODE : FILE_MODE,
|
|
465
|
-
size: node.data.length,
|
|
466
|
-
lastAccessedTime: Math.floor(node.mtime / 1e3),
|
|
467
|
-
lastModifiedTime: Math.floor(node.mtime / 1e3)
|
|
468
|
-
};
|
|
469
|
-
return { stats, ...stats };
|
|
470
|
-
};
|
|
471
|
-
const fileApis = {
|
|
472
|
-
access: (args, { api }) => fs.stat(args.path) ? ok(api) : fail(api, `no such file or directory ${args.path}`),
|
|
473
|
-
stat: (args, { api }) => {
|
|
474
|
-
const node = fs.stat(args.path);
|
|
475
|
-
return node ? ok(api, statResult(node)) : fail(api, `no such file or directory ${args.path}`);
|
|
476
|
-
},
|
|
477
|
-
mkdir: (args, { api }) => guard(api, () => fs.mkdir(args.dirPath, !!args.recursive)),
|
|
478
|
-
writeFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ""))),
|
|
479
|
-
appendFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ""), true)),
|
|
480
|
-
fs_appendFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ""), true)),
|
|
481
|
-
readFile: (args, { api }) => guard(api, () => ({ data: fs.read(args.filePath) })),
|
|
482
|
-
readdir: (args, { api }) => guard(api, () => ({ files: fs.readdir(args.dirPath) })),
|
|
483
|
-
unlink: (args, { api }) => guard(api, () => fs.remove(args.filePath, { dir: false })),
|
|
484
|
-
rmdir: (args, { api }) => guard(api, () => fs.remove(args.dirPath, { dir: true, recursive: !!args.recursive })),
|
|
485
|
-
getFileInfo: (args, { api }) => {
|
|
486
|
-
if (isTempFile(args.filePath)) {
|
|
487
|
-
return tempFileSize(args.filePath).then((size) => size === null ? fail(api, "file not exist") : ok(api, { size }));
|
|
488
|
-
}
|
|
489
|
-
const node = fs.stat(args.filePath);
|
|
490
|
-
return node ? ok(api, { size: node.data.length }) : fail(api, "file not exist");
|
|
491
|
-
}
|
|
492
|
-
};
|
|
493
|
-
for (const name of Object.keys(fileApis)) {
|
|
494
|
-
if (!name.startsWith("fs_")) fileApis[name + "Sync"] = fileApis[name];
|
|
495
|
-
}
|
|
496
|
-
const readMemoryFile = fileApis.readFile;
|
|
497
|
-
fileApis.readFile = (args, context) => /^[a-z]+:\/\//i.test(String(args.filePath)) ? readMemoryFile(args, context) : readPackageFile(fs.normalize(args.filePath), args.encoding).then(
|
|
498
|
-
(data) => ok(context.api, { data }),
|
|
499
|
-
(error) => fail(context.api, error.message)
|
|
500
|
-
);
|
|
501
516
|
return {
|
|
502
|
-
...fileApis,
|
|
503
517
|
// canvas 导出图片、拍照、录像的结果都经过这里
|
|
504
518
|
base64ToTempFilePath: async (args) => {
|
|
505
519
|
const bytes = Uint8Array.from(atob(String(args.base64Data || "")), (char) => char.charCodeAt(0));
|
|
@@ -546,14 +560,6 @@
|
|
|
546
560
|
if (!response.ok || !body) throw new Error(body?.error || `\u5F00\u53D1\u670D\u52A1\u5668\u8FD4\u56DE HTTP ${response.status}`);
|
|
547
561
|
return body;
|
|
548
562
|
}
|
|
549
|
-
async function readPackageFile(filePath, encoding) {
|
|
550
|
-
if (encoding !== void 0 && encoding !== "utf8" && encoding !== "utf-8") {
|
|
551
|
-
throw new Error(`\u8BFB\u53D6\u4EE3\u7801\u5305\u91CC\u7684\u6587\u4EF6\u53EA\u652F\u6301 utf8 \u7F16\u7801\uFF0C\u6216\u4E0D\u6307\u5B9A\u7F16\u7801\u5F97\u5230 ArrayBuffer\uFF0C\u4E0D\u652F\u6301 ${encoding}`);
|
|
552
|
-
}
|
|
553
|
-
const response = await fetch(filePath.split("/").map(encodeURIComponent).join("/"));
|
|
554
|
-
if (!response.ok) throw new Error(`no such file or directory, open ${filePath}`);
|
|
555
|
-
return encoding ? response.text() : response.arrayBuffer();
|
|
556
|
-
}
|
|
557
563
|
function mockUser() {
|
|
558
564
|
return { nickName: "wxa-runner", avatarUrl: "", gender: 0, country: "", province: "", city: "", language: "zh_CN" };
|
|
559
565
|
}
|
|
@@ -1244,6 +1250,46 @@
|
|
|
1244
1250
|
};
|
|
1245
1251
|
}
|
|
1246
1252
|
|
|
1253
|
+
// src/runtime/host/api/subpackages.ts
|
|
1254
|
+
function createSubpackageApis(options) {
|
|
1255
|
+
const names = /* @__PURE__ */ new Set(["__APP__"]);
|
|
1256
|
+
for (const pkg of options.subPackages) {
|
|
1257
|
+
names.add(normalizeName(pkg.root));
|
|
1258
|
+
if (pkg.name) names.add(normalizeName(pkg.name));
|
|
1259
|
+
}
|
|
1260
|
+
let taskSeq2 = 0;
|
|
1261
|
+
const createLoadSubPackageTask = (args, { api }) => {
|
|
1262
|
+
const moduleName = args.moduleName;
|
|
1263
|
+
if (typeof moduleName !== "string" || !moduleName || !names.has(normalizeName(moduleName))) {
|
|
1264
|
+
return fail(api, "module not found");
|
|
1265
|
+
}
|
|
1266
|
+
const loadTaskId = String(++taskSeq2);
|
|
1267
|
+
setTimeout(() => {
|
|
1268
|
+
const event = { taskId: loadTaskId, moduleName };
|
|
1269
|
+
options.emit("onLoadSubPackageTaskStateChange", {
|
|
1270
|
+
...event,
|
|
1271
|
+
state: "progressUpdate",
|
|
1272
|
+
progress: 100,
|
|
1273
|
+
// 没有网络下载,不伪造传输字节数。
|
|
1274
|
+
totalBytesWritten: 0,
|
|
1275
|
+
totalBytesExpectedToWrite: 0
|
|
1276
|
+
});
|
|
1277
|
+
options.emit("onLoadSubPackageTaskStateChange", { ...event, state: "success" });
|
|
1278
|
+
}, 0);
|
|
1279
|
+
return ok(api, { loadTaskId });
|
|
1280
|
+
};
|
|
1281
|
+
return {
|
|
1282
|
+
createLoadSubPackageTask,
|
|
1283
|
+
// 事件已由桥接广播,具体监听与回调由基础库管理,无需另建一套订阅状态。
|
|
1284
|
+
listenLoadSubPackageTaskStateChange: (_args, { api }) => ok(api),
|
|
1285
|
+
// 分包加载完成后渲染层请求注入分包的模板和样式,它们已经打进 page-frame.js,回调后基础库替换占位组件。
|
|
1286
|
+
injectSubPackages: (_args, { api }) => ok(api)
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
function normalizeName(name) {
|
|
1290
|
+
return name.replace(/^\.?\//, "").replace(/\/$/, "");
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1247
1293
|
// src/runtime/host/api/system.ts
|
|
1248
1294
|
var NAVIGATION_BAR_HEIGHT = 44;
|
|
1249
1295
|
var TAB_BAR_HEIGHT = 50;
|
|
@@ -1559,6 +1605,30 @@
|
|
|
1559
1605
|
}
|
|
1560
1606
|
};
|
|
1561
1607
|
|
|
1608
|
+
// src/runtime/host/realm.ts
|
|
1609
|
+
function cloneInto(win, value) {
|
|
1610
|
+
if (value === void 0) return value;
|
|
1611
|
+
return win.JSON.parse(JSON.stringify(value));
|
|
1612
|
+
}
|
|
1613
|
+
var BUFFER_KEY = "__wxa_array_buffer__";
|
|
1614
|
+
function cloneNativeInto(win, value) {
|
|
1615
|
+
if (value === void 0) return value;
|
|
1616
|
+
const buffers = [];
|
|
1617
|
+
const json = JSON.stringify(value, (_key, item) => {
|
|
1618
|
+
if (Object.prototype.toString.call(item) !== "[object ArrayBuffer]") return item;
|
|
1619
|
+
buffers.push(item);
|
|
1620
|
+
return { [BUFFER_KEY]: buffers.length - 1 };
|
|
1621
|
+
});
|
|
1622
|
+
const targetJson = win.JSON;
|
|
1623
|
+
if (!buffers.length) return targetJson.parse(json);
|
|
1624
|
+
return targetJson.parse(json, (_key, item) => item?.[BUFFER_KEY] === void 0 ? item : copyBuffer(win, buffers[item[BUFFER_KEY]]));
|
|
1625
|
+
}
|
|
1626
|
+
function copyBuffer(win, source) {
|
|
1627
|
+
const copy = new win.ArrayBuffer(source.byteLength);
|
|
1628
|
+
new Uint8Array(copy).set(new Uint8Array(source));
|
|
1629
|
+
return copy;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1562
1632
|
// src/runtime/host/ui/fileChooser.ts
|
|
1563
1633
|
function chooseFiles(options) {
|
|
1564
1634
|
return new Promise((resolve) => {
|
|
@@ -2440,7 +2510,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
|
|
|
2440
2510
|
/** 派发给渲染层的原生事件(渲染层里 WeixinJSBridge.on 收到) */
|
|
2441
2511
|
emitToWebview(webviewId, event, data) {
|
|
2442
2512
|
this.pages.get(webviewId)?.dispatch((bridge, target) => {
|
|
2443
|
-
const payload =
|
|
2513
|
+
const payload = cloneNativeInto(target, data);
|
|
2444
2514
|
queueMicrotask(() => bridge.__dispatchOn(event, payload, webviewId));
|
|
2445
2515
|
});
|
|
2446
2516
|
}
|
|
@@ -2465,7 +2535,12 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
|
|
|
2465
2535
|
reLaunch: routeApi((args) => this.reLaunch(args.url)),
|
|
2466
2536
|
switchTab: routeApi((args) => this.switchTab(args.url)),
|
|
2467
2537
|
...createStorageApis(this.storage),
|
|
2538
|
+
...createSubpackageApis({
|
|
2539
|
+
subPackages: this.info.wxConfig.subPackages || [],
|
|
2540
|
+
emit: (event, data) => this.emitToService(event, data)
|
|
2541
|
+
}),
|
|
2468
2542
|
...createSavedFileApis(this.storage),
|
|
2543
|
+
...createFileSystemApis(),
|
|
2469
2544
|
...createSystemApis({
|
|
2470
2545
|
device: this.device,
|
|
2471
2546
|
baseLibVersion: this.info.baseLibVersion,
|
|
@@ -2504,28 +2579,6 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
|
|
|
2504
2579
|
});
|
|
2505
2580
|
}
|
|
2506
2581
|
};
|
|
2507
|
-
function cloneInto(win, value) {
|
|
2508
|
-
if (value === void 0) return value;
|
|
2509
|
-
return win.JSON.parse(JSON.stringify(value));
|
|
2510
|
-
}
|
|
2511
|
-
var BUFFER_KEY = "__wxa_array_buffer__";
|
|
2512
|
-
function cloneNativeInto(win, value) {
|
|
2513
|
-
if (value === void 0) return value;
|
|
2514
|
-
const buffers = [];
|
|
2515
|
-
const json = JSON.stringify(value, (_key, item) => {
|
|
2516
|
-
if (Object.prototype.toString.call(item) !== "[object ArrayBuffer]") return item;
|
|
2517
|
-
buffers.push(item);
|
|
2518
|
-
return { [BUFFER_KEY]: buffers.length - 1 };
|
|
2519
|
-
});
|
|
2520
|
-
const targetJson = win.JSON;
|
|
2521
|
-
if (!buffers.length) return targetJson.parse(json);
|
|
2522
|
-
return targetJson.parse(json, (_key, item) => item?.[BUFFER_KEY] === void 0 ? item : copyBuffer(win, buffers[item[BUFFER_KEY]]));
|
|
2523
|
-
}
|
|
2524
|
-
function copyBuffer(win, source) {
|
|
2525
|
-
const copy = new win.ArrayBuffer(source.byteLength);
|
|
2526
|
-
new Uint8Array(copy).set(new Uint8Array(source));
|
|
2527
|
-
return copy;
|
|
2528
|
-
}
|
|
2529
2582
|
function withDrawableImages(message) {
|
|
2530
2583
|
const actions = message?.data?.actions;
|
|
2531
2584
|
if (!Array.isArray(actions)) return message;
|