@open-wxa/wxa-runner-core 0.2.4 → 0.2.5

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/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ResolvedBaseLib } from '@open-wxa/wxa-runner-extractor';
2
2
  import { D as DeviceProfile } from './setup-COzZ6vzS.mjs';
3
3
  export { A as ApiContext, a as ApiHandler, b as ApiResult, c as AppInfo, M as MockConfig, d as MockRequest, e as MockResponse, f as MockValue, N as NetworkConfig, R as RouteHandler, S as SetupApi, g as SetupConfig, h as SetupContext, i as SetupDefinition } from './setup-COzZ6vzS.mjs';
4
- export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-D5o7hK-Z.mjs';
4
+ export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-CbBoHXdN.mjs';
5
5
 
6
6
  /**
7
7
  * 小程序项目结构解析
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ResolvedBaseLib } from '@open-wxa/wxa-runner-extractor';
2
2
  import { D as DeviceProfile } from './setup-COzZ6vzS.js';
3
3
  export { A as ApiContext, a as ApiHandler, b as ApiResult, c as AppInfo, M as MockConfig, d as MockRequest, e as MockResponse, f as MockValue, N as NetworkConfig, R as RouteHandler, S as SetupApi, g as SetupConfig, h as SetupContext, i as SetupDefinition } from './setup-COzZ6vzS.js';
4
- export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-BTPLQvFs.js';
4
+ export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-DRZ-hXpC.js';
5
5
 
6
6
  /**
7
7
  * 小程序项目结构解析
@@ -1,5 +1,23 @@
1
1
  "use strict";
2
2
  (() => {
3
+ // src/runtime/syncScript.ts
4
+ function readSync(url) {
5
+ const xhr = new XMLHttpRequest();
6
+ xhr.open("GET", url, false);
7
+ xhr.send();
8
+ if (xhr.status !== 200) throw new Error(`[wxa-runner] \u52A0\u8F7D ${url} \u5931\u8D25\uFF1A${xhr.status}`);
9
+ return xhr.responseText;
10
+ }
11
+ function runScript(win, url, code) {
12
+ const href = new URL(url, location.href).href;
13
+ const sourceMap = url.startsWith("/__baselib__/") ? `
14
+ //# sourceMappingURL=${href}.map` : "";
15
+ const script2 = win.document.createElement("script");
16
+ script2.text = `${code}
17
+ //# sourceURL=${href}${sourceMap}`;
18
+ win.document.head.appendChild(script2);
19
+ }
20
+
3
21
  // src/runtime/context.ts
4
22
  var MAIN_CONTEXT_ID = 1;
5
23
  var APP_CONTEXT_NAME = "app";
@@ -131,7 +149,7 @@
131
149
  }
132
150
  runSync(urls) {
133
151
  if (this.pending) throw new Error(`[wxa-runner] JS \u4E0A\u4E0B\u6587 ${this.id} \u5C1A\u672A\u52A0\u8F7D\u5B8C\uFF0C\u4E0D\u80FD\u540C\u6B65\u6267\u884C\u811A\u672C`);
134
- for (const url of urls) evalSync(this.win, url);
152
+ for (const url of urls) runScript(this.win, url, readSync(url));
135
153
  }
136
154
  destroy() {
137
155
  this.pending = [];
@@ -175,19 +193,6 @@
175
193
  this.host.frameLoaded("service", 0);
176
194
  }
177
195
  };
178
- function evalSync(win, url) {
179
- const xhr = new XMLHttpRequest();
180
- xhr.open("GET", url, false);
181
- xhr.send();
182
- if (xhr.status !== 200) throw new Error(`[wxa-runner] \u52A0\u8F7D ${url} \u5931\u8D25\uFF1A${xhr.status}`);
183
- const href = new URL(url, location.href).href;
184
- const sourceMap = url.startsWith("/__baselib__/") ? `
185
- //# sourceMappingURL=${href}.map` : "";
186
- const script2 = win.document.createElement("script");
187
- script2.text = `${xhr.responseText}
188
- //# sourceURL=${href}${sourceMap}`;
189
- win.document.head.appendChild(script2);
190
- }
191
196
  function loadScripts(win, urls, done) {
192
197
  let remaining = urls.length;
193
198
  if (remaining === 0) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/context.ts","../../src/runtime/sdkStubs.ts","../../src/runtime/frame.ts"],"sourcesContent":["/**\n * 模拟原生 WeixinJSContext(3.7.1 起的基础库需要)\n *\n * 新版基础库把逻辑层分成主上下文和子上下文:逻辑层 iframe 是主上下文,运行 WAServiceMainContext.js,\n * 持有 WeixinJSBridge;App / Page / wx 和业务代码在子上下文里,子上下文由主上下文通过这个接口创建。\n * 与开发者工具一样,每个子上下文是逻辑层 iframe 里的一个同源 iframe(subcontext.html)。\n *\n * 两边的消息不经过这里:子上下文拿到同一个 WeixinJSContext 对象,主上下文初始化时在上面挂了\n * register / subscribeHandler,双方直接互相调用。\n *\n * 交给基础库的 WeixinJSContext 是一次性的门面:基础库初始化时取走上面的方法、再把它们删掉,\n * 所以这里的逻辑都不经过它。\n */\n\nimport type { HostApi } from './types';\n\nconst MAIN_CONTEXT_ID = 1;\n/** 业务代码所在的子上下文 */\nconst APP_CONTEXT_NAME = 'app';\n/** 基础库要执行的业务代码入口,对应构建出的 define 脚本和 bootstrap */\nconst APP_SERVICE_ENTRY = 'app-service.js';\n/** 从基础库开始执行到业务代码执行完的最长时间 */\nconst BOOT_TIMEOUT = 10000;\n\ntype Callback = () => void;\n\nexport interface WeixinJSContextOptions {\n /** 向主上下文派发原生事件(WeixinJSBridge.on) */\n dispatchNative: (event: string, data: unknown) => void;\n /** 业务代码的脚本地址,基础库执行 app-service.js 时按顺序加载 */\n appServiceScripts: string[];\n /** 打开基础库的热更新开关(见 server/html.ts 的 enableHotUpdate) */\n hot: boolean;\n}\n\n/** 在逻辑层主上下文里提供 window.WeixinJSContext,必须在基础库之前调用 */\nexport function installWeixinJSContext(main: Window, host: HostApi, options: WeixinJSContextOptions) {\n const boot = new AppBoot(host);\n const mainContext = new JsContext(MAIN_CONTEXT_ID, 'main', main);\n const contexts = new Map<number, JsContext>([[MAIN_CONTEXT_ID, mainContext]]);\n let nextId = MAIN_CONTEXT_ID + 1;\n\n const open = (name: string | undefined, empty: boolean): JsContext => {\n const context = openSubContext(main, nextId++, name, empty);\n contexts.set(context.id, context);\n if (context.isApp) boot.reach('load');\n return context;\n };\n\n /** 原生接口的结果码:1 成功,0 失败 */\n const withContext = (id: number, action: (context: JsContext) => number): number => {\n const context = contexts.get(Number(id));\n if (context) return action(context);\n console.warn(`[wxa-runner] 找不到 JS 上下文 ${id}`);\n return 0;\n };\n\n /** 执行基础库要求的脚本文件:带回调时等上下文加载完再异步执行,否则同步执行 */\n const evaluate = (context: JsContext, file: string, done?: Callback): number => {\n const isEntry = context.isApp && file.replace(/^\\/+/, '') === APP_SERVICE_ENTRY;\n const urls = isEntry ? options.appServiceScripts : null;\n if (!urls) {\n console.warn(`[wxa-runner] 基础库要求执行未知脚本 ${file}`);\n return 0;\n }\n const start = () => {\n boot.reach('run');\n // 与旧版基础库一样,必须在业务代码注册 Page / Component 之前打开\n if (options.hot) (context.win as any).__virtualDOM__?.enableUpdateWxAppCode?.();\n };\n if (done) {\n context.whenReady(() => {\n start();\n loadScripts(context.win!, urls, () => {\n done();\n boot.finish();\n });\n });\n } else {\n start();\n context.runSync(urls);\n boot.finish();\n }\n return 1;\n };\n\n const evaluateAll = (context: JsContext, files: string[], done?: Callback): number => {\n if (!done) return files.every(file => evaluate(context, file) === 1) ? 1 : 0;\n let remaining = files.length;\n if (remaining === 0) done();\n for (const file of files) {\n if (evaluate(context, file, () => --remaining === 0 && done()) === 0) return 0;\n }\n return 1;\n };\n\n const nativeInterface = {\n mainContextId: MAIN_CONTEXT_ID,\n alloc: (name?: string, callback?: Callback) => open(name, false).whenReady(callback).id,\n allocEmpty: (name?: string, callback?: Callback) => open(name, true).whenReady(callback).id,\n create(entry: string | undefined, name?: string, callback?: Callback) {\n const context = open(name, false);\n if (entry) context.whenReady(() => evaluate(context, entry, callback));\n else context.whenReady(callback);\n return context.id;\n },\n evaluateScriptFile: (id: number, file: string, callback?: Callback) =>\n withContext(id, context => evaluate(context, file, callback)),\n loadJsFiles: (id: number, files: string, callback?: Callback) =>\n withContext(id, context => evaluateAll(context, JSON.parse(files), callback)),\n /** 基础库自己的文件(如 WARenderContext.js),同步执行 */\n loadLibFiles: (id: number, files: string) =>\n withContext(id, context => {\n context.runSync((JSON.parse(files) as string[]).map(file => `/__baselib__/${file}`));\n return 1;\n }),\n destroy(id: number, callback?: Callback) {\n const context = contexts.get(Number(id));\n if (!context || context === mainContext) return;\n contexts.delete(context.id);\n context.destroy();\n if (context.isApp) host.registerAppContext(null);\n callback?.();\n }\n };\n\n (main as any).WeixinJSContext = nativeInterface;\n\n // subcontext.html 通过 parent.__wxaContexts 回调这两个入口\n (main as any).__wxaContexts = {\n /** 子上下文页面开始执行,基础库之前:交给它基础库需要的全局变量 */\n prepare(id: number, win: Window) {\n const context = contexts.get(id);\n if (!context || context === mainContext) throw new Error(`[wxa-runner] 未知的子上下文 ${id}`);\n context.win = win;\n Object.assign(win, { WeixinJSContext: nativeInterface, WeixinJSContextId: id, __wxConfig: (main as any).__wxConfig });\n if (context.isApp) host.registerAppContext(win);\n },\n /** 子上下文页面执行完(基础库已初始化) */\n loaded(id: number) {\n const context = contexts.get(id);\n if (!context) return;\n context.markReady();\n if (context.isApp) {\n boot.reach('entry');\n // 真机上由客户端在主包就绪后派发,基础库收到后才执行业务入口\n options.dispatchNative('onSubPackageReady', { moduleName: '__APP__' });\n }\n }\n };\n}\n\n/** 一个 JS 上下文:主上下文是逻辑层 iframe 本身,子上下文是其中的一个同源 iframe */\nclass JsContext {\n /** 页面加载完之前收到的任务;加载完后为 null */\n private pending: Callback[] | null;\n\n constructor(readonly id: number, readonly name: string, public win: Window | null, private readonly iframe?: HTMLIFrameElement) {\n this.pending = win ? null : [];\n }\n\n get isApp(): boolean {\n return this.name === APP_CONTEXT_NAME;\n }\n\n /** 加载完后执行,已加载完时立即执行 */\n whenReady(task?: Callback): this {\n if (task) {\n if (this.pending) this.pending.push(task);\n else task();\n }\n return this;\n }\n\n markReady() {\n const tasks = this.pending || [];\n this.pending = null;\n tasks.forEach(task => task());\n }\n\n runSync(urls: string[]) {\n if (this.pending) throw new Error(`[wxa-runner] JS 上下文 ${this.id} 尚未加载完,不能同步执行脚本`);\n for (const url of urls) evalSync(this.win!, url);\n }\n\n destroy() {\n this.pending = [];\n this.iframe?.remove();\n }\n}\n\nfunction openSubContext(main: Window, id: number, name: string | undefined, empty: boolean): JsContext {\n const iframe = main.document.createElement('iframe');\n iframe.style.display = 'none';\n iframe.src = `/__wxa__/subcontext.html?id=${id}${empty ? '&empty=1' : ''}`;\n // 基础库在逻辑层页面的 <head> 里执行时就会创建子上下文,那时还没有 body\n main.document.documentElement.appendChild(iframe);\n return new JsContext(id, name || `context${id}`, null, iframe);\n}\n\nconst BOOT_STAGES = {\n alloc: `基础库没有创建业务子上下文(名为 ${APP_CONTEXT_NAME} 的子上下文)`,\n load: '业务子上下文没有加载完(WASubContext.js 加载或执行出错)',\n entry: `基础库没有执行业务代码入口 ${APP_SERVICE_ENTRY}`,\n run: '业务代码没有加载完'\n};\n\ntype BootStage = keyof typeof BOOT_STAGES;\n\n/**\n * 业务代码的启动过程,每一步都依赖基础库的内部行为:\n * 创建业务子上下文 → 子上下文加载完 → 派发 onSubPackageReady → 基础库执行业务入口 → 业务代码执行完。\n * 任何一步没发生,宿主都会一直等逻辑层就绪,所以超时后报告停在哪一步,照常结束启动\n */\nclass AppBoot {\n private stage: BootStage = 'alloc';\n private finished = false;\n private readonly timer: ReturnType<typeof setTimeout>;\n\n constructor(private readonly host: HostApi) {\n this.timer = setTimeout(() => {\n this.finish(new Error(`[wxa-runner] 逻辑层 ${BOOT_TIMEOUT}ms 内没有就绪:${BOOT_STAGES[this.stage]}`));\n }, BOOT_TIMEOUT);\n }\n\n reach(stage: BootStage) {\n this.stage = stage;\n }\n\n /** 通知宿主逻辑层就绪,只通知一次;出错时先报告错误 */\n finish(error?: Error) {\n if (this.finished) return;\n this.finished = true;\n clearTimeout(this.timer);\n if (error) {\n console.error(error.message);\n this.host.reportError('service', 0, error);\n }\n this.host.frameLoaded('service', 0);\n }\n}\n\n/** 与开发者工具的 loadLibFiles 一致:同步请求脚本内容,以内联脚本执行 */\nfunction evalSync(win: Window, url: string) {\n const xhr = new XMLHttpRequest();\n xhr.open('GET', url, false);\n xhr.send();\n if (xhr.status !== 200) throw new Error(`[wxa-runner] 加载 ${url} 失败:${xhr.status}`);\n const href = new URL(url, location.href).href;\n // 基础库文件同样加入 DevTools 的忽略列表(见 server/ignoreList.ts)\n const sourceMap = url.startsWith('/__baselib__/') ? `\\n//# sourceMappingURL=${href}.map` : '';\n const script = win.document.createElement('script');\n script.text = `${xhr.responseText}\\n//# sourceURL=${href}${sourceMap}`;\n win.document.head.appendChild(script);\n}\n\n/** 按顺序加载外部脚本(保留文件名和行号,便于在 DevTools 里调试),全部执行完后回调 */\nfunction loadScripts(win: Window, urls: string[], done: Callback) {\n let remaining = urls.length;\n if (remaining === 0) {\n done();\n return;\n }\n for (const url of urls) {\n const script = win.document.createElement('script');\n script.async = false;\n script.src = url;\n const settle = () => {\n if (--remaining === 0) done();\n };\n script.onload = settle;\n script.onerror = () => {\n console.error(`[wxa-runner] 加载 ${url} 失败`);\n settle();\n };\n win.document.head.appendChild(script);\n }\n}\n","/**\n * 基础库伴生 SDK 子包能力的占位实现\n *\n * WAService.js 不是自包含的。广告、云开发、米大师支付等能力放在一组伴生文件里\n * (WAAppAd.js / WACloud.js / WAMidasSDK.js 等),真机和开发者工具由原生层调用\n * loadMainContextLibFile 把它们同步加载进同一个上下文,再把导出挂到约定的全局名上\n * (WAAppAd.js → globalThis.AD → 基础库读作 ADSDK)。运行时没有这套加载机制。\n *\n * 缺失不会直接抛到业务代码:基础库把内部异常包成 appServiceSDKScriptError 自己吞掉,\n * 于是 wx.createRewardedVideoAd() 返回 undefined。真正崩的是下一行业务代码\n * ——`ad.onError(...)`,Cannot read properties of undefined。所以占位放在 wx 这一层,\n * 不管基础库内部走的是哪条失败路径(3.7.0 上 createRewardedVideoAd 栽在\n * loadSdkSubPackage,createInterstitialAd 栽在 ADSDK 未定义)都能接住。\n *\n * 不在 ADSDK / __cloudSDKMain__ 这些全局上打桩:基础库 init 时会按子包注册表回写\n * 这些全局,占位会被覆盖掉;而 SkylineGlobal / NativeGlobal / xrFrame 等是基础库会\n * typeof 检测的能力开关,补上反而会让它走进依赖更多的分支,比缺失更糟。\n */\n\nconst UNSUPPORTED = '浏览器运行时不支持广告';\n\ntype Listener = (...args: unknown[]) => void;\n\n/** 没人接的占位调用不该变成 unhandledrejection,但返回的 promise 仍然可以被 catch */\nfunction rejected(reason: unknown): Promise<never> {\n const promise = Promise.reject(reason);\n promise.catch(() => undefined);\n return promise;\n}\n\nclass StubAd {\n private listeners: Record<string, Listener[]> = {};\n\n constructor(private readonly hideable: boolean) {}\n\n load() { return this.fail(); }\n show() { return this.fail(); }\n destroy() { this.listeners = {}; }\n\n onLoad(callback: Listener) { this.add('load', callback); }\n offLoad(callback?: Listener) { this.remove('load', callback); }\n onError(callback: Listener) { this.add('error', callback); }\n offError(callback?: Listener) { this.remove('error', callback); }\n onClose(callback: Listener) { this.add('close', callback); }\n offClose(callback?: Listener) { this.remove('close', callback); }\n\n /** 只有原生模板广告(createCustomAd)有这组接口 */\n hide() { return this.hideable ? Promise.resolve() : undefined; }\n isShow() { return this.hideable ? false : undefined; }\n onHide(callback: Listener) { if (this.hideable) this.add('hide', callback); }\n offHide(callback?: Listener) { if (this.hideable) this.remove('hide', callback); }\n\n private add(event: string, callback: Listener) {\n (this.listeners[event] = this.listeners[event] || []).push(callback);\n }\n\n private remove(event: string, callback?: Listener) {\n if (!this.listeners[event]) return;\n this.listeners[event] = callback ? this.listeners[event].filter(l => l !== callback) : [];\n }\n\n /** 真机上拉取失败也是先回调 onError 再 reject,这里保持一致 */\n private fail() {\n const error = { errCode: 1000, errMsg: UNSUPPORTED };\n queueMicrotask(() => {\n for (const listener of (this.listeners.error || []).slice()) listener({ ...error });\n });\n return rejected(error);\n }\n}\n\n/** 基础库缺少伴生子包时会返回 undefined 的广告接口 */\nexport const UNSUPPORTED_AD_APIS = [\n 'createRewardedVideoAd',\n 'createInterstitialAd',\n 'createCustomAd',\n 'createSkitAd'\n] as const;\n\nexport interface ApiStubOptions {\n /** 默认 console.warn,测试里可以注入收集 */\n warn?: (message: string) => void;\n}\n\n/** 标在占位函数上,重复调用 installApiStubs 时据此跳过 */\nconst STUB = Symbol.for('wxa-runner.apiStub') as unknown as string;\n\n/** 每次 require 都会重装一遍,提示挂在 wx 上,第一次用到广告时出一次 */\nconst WARNED = Symbol.for('wxa-runner.apiStubWarned') as unknown as string;\n\n/**\n * 替换掉基础库里这些返回 undefined 的接口。\n * 幂等:装过的不再重装,可以在每次 require 前安全调用。\n * 返回这次实际替换的名字;wx 上的属性个别基础库版本可能不可配置,那种就跳过。\n */\nexport function installApiStubs(wx: Record<string, any>, options: ApiStubOptions = {}): string[] {\n const warn = options.warn || ((message: string) => console.warn(message));\n const replaced: string[] = [];\n\n for (const name of UNSUPPORTED_AD_APIS) {\n if (wx[name]?.[STUB]) continue;\n\n const stub = () => {\n if (!wx[WARNED]) {\n wx[WARNED] = true;\n warn('[wxa-runner] 广告(WAAppAd.js)在浏览器运行时不可用,广告对象的 load/show 会失败,但不会中断页面');\n }\n return new StubAd(name === 'createCustomAd');\n };\n (stub as any)[STUB] = true;\n\n try {\n Object.defineProperty(wx, name, { value: stub, writable: true, configurable: true, enumerable: true });\n replaced.push(name);\n } catch {\n // 属性不可配置,保持基础库原样(仍会返回 undefined)\n }\n }\n\n return replaced;\n}\n","/**\n * 注入到逻辑层/渲染层 iframe 的脚本,必须在基础库之前执行\n *\n * 1. 准备开发者工具会预置的全局变量(基础库依赖它们)\n * 2. 提供 WeixinJSBridge,把调用转发给宿主\n * 3. 渲染层:模拟手机屏幕尺寸,处理鼠标输入(见 installInput)\n *\n * 新版基础库的逻辑层分主上下文和子上下文(见 context.ts)。逻辑层 iframe 是主上下文;\n * 子上下文页面也加载这个脚本(data-context-id),只准备全局变量,桥由主上下文的基础库交给它。\n */\n\nimport { installWeixinJSContext } from './context';\nimport { installApiStubs } from './sdkStubs';\nimport type { FrameBridge, FrameKind, HostApi } from './types';\n\ntype Listener = (data: unknown, webviewId?: number) => void;\n\nconst script = document.currentScript as HTMLScriptElement;\nconst kind = (script.dataset.kind || 'webview') as FrameKind;\nconst webviewId = Number(script.dataset.webviewId || 0);\nconst subContextId = Number(script.dataset.contextId || 0);\nconst host = ((subContextId ? window.parent.parent : window.parent) as any).__wxaHost as HostApi;\nconst g = window as any;\n\ng.__global = g;\n\nif (kind === 'service') {\n Object.assign(g, {\n __wxAppData: {},\n __wxRoute: undefined,\n __wxRouteBegin: undefined,\n __wxAppCode__: {},\n __wxAppCurrentFile__: undefined,\n __vd_version_info__: {},\n global: {},\n __workerVendorCode__: {},\n __workersCode__: {},\n WeixinWorker: {},\n $gwx: undefined\n });\n g.__WeixinWorker = g.WeixinWorker;\n // 基础库初始化完成后通过它交出 App/Page/Component/wx/define/require 等全局对象\n g.__passWAServiceGlobal__ = (globals: Record<string, unknown>) => {\n for (const key of Object.keys(globals)) {\n if (key !== 'Protect') g[key] = globals[key];\n }\n };\n hookRequire();\n} else {\n emulateDeviceScreen(host.device);\n installInput();\n runLoadCallbacksEarly();\n}\n\noverrideUserAgent();\n\nwindow.addEventListener('error', event => host.reportError(kind, webviewId, event.error || event.message));\nwindow.addEventListener('unhandledrejection', event => host.reportError(kind, webviewId, event.reason));\n\nif (subContextId) {\n (window.parent as any).__wxaContexts.prepare(subContextId, window);\n} else {\n const bridge = createBridge();\n g.WeixinJSBridge = bridge;\n // 基础库会用自己的包装替换 WeixinJSBridge,宿主始终通过这个引用回调\n g.__wxaBridge = bridge;\n if (script.dataset.appService) {\n installWeixinJSContext(window, host, {\n dispatchNative: bridge.__dispatchOn,\n appServiceScripts: JSON.parse(script.dataset.appService),\n hot: script.dataset.hot === '1'\n });\n }\n host.registerFrame(kind, window, bridge, webviewId);\n}\n\n/**\n * 基础库初始化完会把广告等缺伴生子包的接口改成「返回 undefined」的函数,占位只有在\n * 业务代码执行前装才留得住 —— bootstrap 里 require 第一个业务模块就是那个时机。\n *\n * 这里用存取器占住 require 再等基础库赋值,而不是事后包装:基础库交出全局的方式按版本\n * 而异(3.7.0 直接写 globalThis,并不调 __passWAServiceGlobal__),事后包装没有可靠的时机。\n * installApiStubs 幂等,每次 require 都查一遍,不赌某一次调用的先后。\n */\nfunction hookRequire() {\n let real: unknown;\n const wrapper = function (this: unknown, ...args: unknown[]) {\n if (g.wx) installApiStubs(g.wx);\n return (real as (...a: unknown[]) => unknown).apply(this, args);\n };\n try {\n Object.defineProperty(g, 'require', {\n configurable: true,\n enumerable: true,\n get: () => (typeof real === 'function' ? wrapper : real),\n set: value => { real = value; }\n });\n } catch {\n // 定义不了就算了,广告接口退回基础库原样(返回 undefined)\n }\n}\n\nfunction createBridge(): FrameBridge & Record<string, unknown> {\n const onListeners: Record<string, Listener[]> = {};\n const subListeners: Record<string, Listener[]> = {};\n\n const add = (map: Record<string, Listener[]>, event: string, listener: Listener) => {\n (map[event] = map[event] || []).push(listener);\n };\n const remove = (map: Record<string, Listener[]>, event: string, listener?: Listener) => {\n if (!map[event]) return;\n map[event] = listener ? map[event].filter(l => l !== listener) : [];\n };\n const emit = (map: Record<string, Listener[]>, event: string, data: unknown, id?: number) => {\n for (const listener of (map[event] || []).slice()) {\n try {\n listener(data, id);\n } catch (error) {\n console.error(`[wxa-runner] ${event} 处理出错`, error);\n }\n }\n };\n\n return {\n invoke(api: string, args: unknown, callback?: (res: any) => void) {\n host.invoke(kind, window, api, args, callback);\n },\n publish(event: string, data: unknown, webviewIds?: number[]) {\n host.publish(kind, window, event, data, webviewIds);\n },\n subscribe(event: string, listener: Listener) {\n add(subListeners, event, listener);\n },\n on(event: string, listener: Listener) {\n add(onListeners, event, listener);\n },\n addEventListener(event: string, listener: Listener) {\n add(onListeners, event, listener);\n },\n removeEventListener(event: string, listener?: Listener) {\n remove(onListeners, event, listener);\n },\n addSubscribeListener(event: string, listener: Listener) {\n add(subListeners, event, listener);\n },\n removeSubscribeListener(event: string, listener?: Listener) {\n remove(subListeners, event, listener);\n },\n __dispatchOn(event: string, data: unknown, id?: number) {\n emit(onListeners, event, data, id);\n },\n __dispatchSub(event: string, data: unknown, id?: number) {\n emit(subListeners, event, data, id);\n }\n };\n}\n\n/**\n * wcsc 生成的 rpx 换算读取 window.screen.width,桌面浏览器里那是显示器宽度,\n * 这里改成模拟设备的尺寸。\n */\nfunction emulateDeviceScreen(device: HostApi['device']) {\n const values: Record<string, number> = {\n width: device.screenWidth,\n height: device.screenHeight,\n availWidth: device.screenWidth,\n availHeight: device.screenHeight\n };\n for (const key of Object.keys(values)) {\n try {\n Object.defineProperty(window.screen, key, { get: () => values[key], configurable: true });\n } catch {\n // 个别浏览器不允许重定义,退回到真实值\n }\n }\n // 桌面浏览器报告横屏,基础库会因此改用 screen.height 作为设备宽度换算 rpx\n const portrait = {\n type: 'portrait-primary',\n angle: 0,\n onchange: null,\n addEventListener() {},\n removeEventListener() {},\n dispatchEvent: () => false,\n lock: () => Promise.reject(new Error('not supported')),\n unlock() {}\n };\n try {\n Object.defineProperty(window.screen, 'orientation', { get: () => portrait, configurable: true });\n } catch {\n // 同上\n }\n try {\n Object.defineProperty(window, 'devicePixelRatio', { get: () => device.pixelRatio, configurable: true });\n } catch {\n // 同上\n }\n}\n\n/**\n * 基础库在文档没加载完时,把内置组件样式(wx-view 的 display、wx-canvas 的默认尺寸等)推迟到\n * window.onload 再注入。开发者工具在文档加载完后才注入基础库,那边是立即注入;这里基础库随页面\n * 同步加载,首屏渲染早于 onload,canvas 这类挂载时测量尺寸的组件会量到没有样式时的大小。\n * 所以加载完成前赋给 window.onload 的回调改为在当前脚本执行完后立即运行,仍早于首屏渲染。\n * 效果与开发者工具一致:那边每处都直接调用回调,多次赋值各自执行,window.onload 本身始终为空。\n */\nfunction runLoadCallbacksEarly() {\n let owner: object | null = window;\n while (owner && !Object.getOwnPropertyDescriptor(owner, 'onload')) owner = Object.getPrototypeOf(owner);\n const native = owner && Object.getOwnPropertyDescriptor(owner, 'onload');\n if (!native?.get || !native.set) return;\n Object.defineProperty(window, 'onload', {\n configurable: true,\n get: () => native.get!.call(window),\n set(handler: unknown) {\n if (typeof handler === 'function' && document.readyState !== 'complete') {\n queueMicrotask(() => handler.call(window, new Event('load')));\n } else {\n native.set!.call(window, handler);\n }\n }\n });\n}\n\nfunction overrideUserAgent() {\n const ua = `${navigator.userAgent} (iPhone; wxa-runner) MicroMessenger/8.0.50 miniProgram`;\n try {\n Object.defineProperty(navigator, 'userAgent', { get: () => ua, configurable: true });\n } catch {\n // 只影响基础库对平台的判断,失败可以忽略\n }\n}\n\n/**\n * 鼠标输入 → 触摸事件\n *\n * 模拟的是手机,页面只应收到触摸事件。基础库在部分版本/平台上会自己把鼠标或 pointer 事件\n * 转换为触摸,和这里的转换叠加会导致一次点击触发两次 tap,所以在 window 捕获阶段\n * (先于基础库注册的任何监听)拦下鼠标类事件。不调用 preventDefault,输入框聚焦等默认行为不受影响。\n *\n * 另外,基础库在元素滚动后 50ms 内会把触摸当作滑动、取消 tap。自动化测试常常是\n * 「滚动到元素 → 立刻点击」,而 scroll 事件要到下一帧才派发,所以按下时先等两帧\n * 让挂起的 scroll 事件派发完,刚滚动过的话再顺延到窗口之后。同一次按压的事件按原顺序派发。\n */\nfunction installInput() {\n const SCROLL_TAP_GUARD = 80;\n let lastScroll = 0;\n let queue: Promise<void> = Promise.resolve();\n let target: EventTarget | null = null;\n\n document.addEventListener('scroll', () => {\n lastScroll = Date.now();\n }, true);\n\n const nextFrame = () => new Promise<void>(resolve => requestAnimationFrame(() => resolve()));\n const sleep = (ms: number) => new Promise<void>(resolve => setTimeout(resolve, ms));\n\n const fire = (type: 'touchstart' | 'touchmove' | 'touchend', event: MouseEvent, eventTarget: EventTarget) => {\n const point = {\n clientX: event.clientX,\n clientY: event.clientY,\n pageX: event.pageX,\n pageY: event.pageY,\n screenX: event.screenX,\n screenY: event.screenY\n };\n queue = queue.then(async () => {\n if (type === 'touchstart') {\n await nextFrame();\n await nextFrame();\n const wait = lastScroll + SCROLL_TAP_GUARD - Date.now();\n if (wait > 0) await sleep(wait);\n }\n const touch = new Touch({ identifier: 1, target: eventTarget, ...point });\n const active = type === 'touchend' ? [] : [touch];\n eventTarget.dispatchEvent(new TouchEvent(type, {\n bubbles: true,\n cancelable: true,\n composed: true,\n touches: active,\n targetTouches: active,\n changedTouches: [touch]\n }));\n });\n };\n\n window.addEventListener('mousedown', event => {\n event.stopImmediatePropagation();\n if (event.button !== 0 || !event.target) return;\n target = event.target;\n fire('touchstart', event, target);\n }, true);\n window.addEventListener('mousemove', event => {\n event.stopImmediatePropagation();\n if (target) fire('touchmove', event, target);\n }, true);\n window.addEventListener('mouseup', event => {\n event.stopImmediatePropagation();\n if (!target) return;\n fire('touchend', event, target);\n target = null;\n }, true);\n for (const type of ['pointerdown', 'pointermove', 'pointerup', 'pointercancel']) {\n window.addEventListener(type, event => {\n if ((event as PointerEvent).pointerType !== 'touch') event.stopImmediatePropagation();\n }, true);\n }\n}\n"],"mappings":"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","names":["host","script"]}
1
+ {"version":3,"sources":["../../src/runtime/syncScript.ts","../../src/runtime/context.ts","../../src/runtime/sdkStubs.ts","../../src/runtime/frame.ts"],"sourcesContent":["/**\n * 同步执行脚本:与开发者工具的 loadLibFiles 一致,同步请求脚本内容,以内联脚本执行\n */\n\n/** @throws 状态码不是 200 */\nexport function readSync(url: string): string {\n const xhr = new XMLHttpRequest();\n xhr.open('GET', url, false);\n xhr.send();\n if (xhr.status !== 200) throw new Error(`[wxa-runner] 加载 ${url} 失败:${xhr.status}`);\n return xhr.responseText;\n}\n\n/** 在 win 里执行完才返回;DevTools 里显示为 url 这个文件 */\nexport function runScript(win: Window, url: string, code: string) {\n const href = new URL(url, location.href).href;\n // 基础库文件同样加入 DevTools 的忽略列表(见 server/ignoreList.ts)\n const sourceMap = url.startsWith('/__baselib__/') ? `\\n//# sourceMappingURL=${href}.map` : '';\n const script = win.document.createElement('script');\n script.text = `${code}\\n//# sourceURL=${href}${sourceMap}`;\n win.document.head.appendChild(script);\n}\n","/**\n * 模拟原生 WeixinJSContext(3.7.1 起的基础库需要)\n *\n * 新版基础库把逻辑层分成主上下文和子上下文:逻辑层 iframe 是主上下文,运行 WAServiceMainContext.js,\n * 持有 WeixinJSBridge;App / Page / wx 和业务代码在子上下文里,子上下文由主上下文通过这个接口创建。\n * 与开发者工具一样,每个子上下文是逻辑层 iframe 里的一个同源 iframe(subcontext.html)。\n *\n * 两边的消息不经过这里:子上下文拿到同一个 WeixinJSContext 对象,主上下文初始化时在上面挂了\n * register / subscribeHandler,双方直接互相调用。\n *\n * 交给基础库的 WeixinJSContext 是一次性的门面:基础库初始化时取走上面的方法、再把它们删掉,\n * 所以这里的逻辑都不经过它。\n */\n\nimport { readSync, runScript } from './syncScript';\nimport type { HostApi } from './types';\n\nconst MAIN_CONTEXT_ID = 1;\n/** 业务代码所在的子上下文 */\nconst APP_CONTEXT_NAME = 'app';\n/** 基础库要执行的业务代码入口,对应构建出的 define 脚本和 bootstrap */\nconst APP_SERVICE_ENTRY = 'app-service.js';\n/** 从基础库开始执行到业务代码执行完的最长时间 */\nconst BOOT_TIMEOUT = 10000;\n\ntype Callback = () => void;\n\nexport interface WeixinJSContextOptions {\n /** 向主上下文派发原生事件(WeixinJSBridge.on) */\n dispatchNative: (event: string, data: unknown) => void;\n /** 业务代码的脚本地址,基础库执行 app-service.js 时按顺序加载 */\n appServiceScripts: string[];\n /** 打开基础库的热更新开关(见 server/html.ts 的 enableHotUpdate) */\n hot: boolean;\n}\n\n/** 在逻辑层主上下文里提供 window.WeixinJSContext,必须在基础库之前调用 */\nexport function installWeixinJSContext(main: Window, host: HostApi, options: WeixinJSContextOptions) {\n const boot = new AppBoot(host);\n const mainContext = new JsContext(MAIN_CONTEXT_ID, 'main', main);\n const contexts = new Map<number, JsContext>([[MAIN_CONTEXT_ID, mainContext]]);\n let nextId = MAIN_CONTEXT_ID + 1;\n\n const open = (name: string | undefined, empty: boolean): JsContext => {\n const context = openSubContext(main, nextId++, name, empty);\n contexts.set(context.id, context);\n if (context.isApp) boot.reach('load');\n return context;\n };\n\n /** 原生接口的结果码:1 成功,0 失败 */\n const withContext = (id: number, action: (context: JsContext) => number): number => {\n const context = contexts.get(Number(id));\n if (context) return action(context);\n console.warn(`[wxa-runner] 找不到 JS 上下文 ${id}`);\n return 0;\n };\n\n /** 执行基础库要求的脚本文件:带回调时等上下文加载完再异步执行,否则同步执行 */\n const evaluate = (context: JsContext, file: string, done?: Callback): number => {\n const isEntry = context.isApp && file.replace(/^\\/+/, '') === APP_SERVICE_ENTRY;\n const urls = isEntry ? options.appServiceScripts : null;\n if (!urls) {\n console.warn(`[wxa-runner] 基础库要求执行未知脚本 ${file}`);\n return 0;\n }\n const start = () => {\n boot.reach('run');\n // 与旧版基础库一样,必须在业务代码注册 Page / Component 之前打开\n if (options.hot) (context.win as any).__virtualDOM__?.enableUpdateWxAppCode?.();\n };\n if (done) {\n context.whenReady(() => {\n start();\n loadScripts(context.win!, urls, () => {\n done();\n boot.finish();\n });\n });\n } else {\n start();\n context.runSync(urls);\n boot.finish();\n }\n return 1;\n };\n\n const evaluateAll = (context: JsContext, files: string[], done?: Callback): number => {\n if (!done) return files.every(file => evaluate(context, file) === 1) ? 1 : 0;\n let remaining = files.length;\n if (remaining === 0) done();\n for (const file of files) {\n if (evaluate(context, file, () => --remaining === 0 && done()) === 0) return 0;\n }\n return 1;\n };\n\n const nativeInterface = {\n mainContextId: MAIN_CONTEXT_ID,\n alloc: (name?: string, callback?: Callback) => open(name, false).whenReady(callback).id,\n allocEmpty: (name?: string, callback?: Callback) => open(name, true).whenReady(callback).id,\n create(entry: string | undefined, name?: string, callback?: Callback) {\n const context = open(name, false);\n if (entry) context.whenReady(() => evaluate(context, entry, callback));\n else context.whenReady(callback);\n return context.id;\n },\n evaluateScriptFile: (id: number, file: string, callback?: Callback) =>\n withContext(id, context => evaluate(context, file, callback)),\n loadJsFiles: (id: number, files: string, callback?: Callback) =>\n withContext(id, context => evaluateAll(context, JSON.parse(files), callback)),\n /** 基础库自己的文件(如 WARenderContext.js),同步执行 */\n loadLibFiles: (id: number, files: string) =>\n withContext(id, context => {\n context.runSync((JSON.parse(files) as string[]).map(file => `/__baselib__/${file}`));\n return 1;\n }),\n destroy(id: number, callback?: Callback) {\n const context = contexts.get(Number(id));\n if (!context || context === mainContext) return;\n contexts.delete(context.id);\n context.destroy();\n if (context.isApp) host.registerAppContext(null);\n callback?.();\n }\n };\n\n (main as any).WeixinJSContext = nativeInterface;\n\n // subcontext.html 通过 parent.__wxaContexts 回调这两个入口\n (main as any).__wxaContexts = {\n /** 子上下文页面开始执行,基础库之前:交给它基础库需要的全局变量 */\n prepare(id: number, win: Window) {\n const context = contexts.get(id);\n if (!context || context === mainContext) throw new Error(`[wxa-runner] 未知的子上下文 ${id}`);\n context.win = win;\n Object.assign(win, { WeixinJSContext: nativeInterface, WeixinJSContextId: id, __wxConfig: (main as any).__wxConfig });\n if (context.isApp) host.registerAppContext(win);\n },\n /** 子上下文页面执行完(基础库已初始化) */\n loaded(id: number) {\n const context = contexts.get(id);\n if (!context) return;\n context.markReady();\n if (context.isApp) {\n boot.reach('entry');\n // 真机上由客户端在主包就绪后派发,基础库收到后才执行业务入口\n options.dispatchNative('onSubPackageReady', { moduleName: '__APP__' });\n }\n }\n };\n}\n\n/** 一个 JS 上下文:主上下文是逻辑层 iframe 本身,子上下文是其中的一个同源 iframe */\nclass JsContext {\n /** 页面加载完之前收到的任务;加载完后为 null */\n private pending: Callback[] | null;\n\n constructor(readonly id: number, readonly name: string, public win: Window | null, private readonly iframe?: HTMLIFrameElement) {\n this.pending = win ? null : [];\n }\n\n get isApp(): boolean {\n return this.name === APP_CONTEXT_NAME;\n }\n\n /** 加载完后执行,已加载完时立即执行 */\n whenReady(task?: Callback): this {\n if (task) {\n if (this.pending) this.pending.push(task);\n else task();\n }\n return this;\n }\n\n markReady() {\n const tasks = this.pending || [];\n this.pending = null;\n tasks.forEach(task => task());\n }\n\n runSync(urls: string[]) {\n if (this.pending) throw new Error(`[wxa-runner] JS 上下文 ${this.id} 尚未加载完,不能同步执行脚本`);\n for (const url of urls) runScript(this.win!, url, readSync(url));\n }\n\n destroy() {\n this.pending = [];\n this.iframe?.remove();\n }\n}\n\nfunction openSubContext(main: Window, id: number, name: string | undefined, empty: boolean): JsContext {\n const iframe = main.document.createElement('iframe');\n iframe.style.display = 'none';\n iframe.src = `/__wxa__/subcontext.html?id=${id}${empty ? '&empty=1' : ''}`;\n // 基础库在逻辑层页面的 <head> 里执行时就会创建子上下文,那时还没有 body\n main.document.documentElement.appendChild(iframe);\n return new JsContext(id, name || `context${id}`, null, iframe);\n}\n\nconst BOOT_STAGES = {\n alloc: `基础库没有创建业务子上下文(名为 ${APP_CONTEXT_NAME} 的子上下文)`,\n load: '业务子上下文没有加载完(WASubContext.js 加载或执行出错)',\n entry: `基础库没有执行业务代码入口 ${APP_SERVICE_ENTRY}`,\n run: '业务代码没有加载完'\n};\n\ntype BootStage = keyof typeof BOOT_STAGES;\n\n/**\n * 业务代码的启动过程,每一步都依赖基础库的内部行为:\n * 创建业务子上下文 → 子上下文加载完 → 派发 onSubPackageReady → 基础库执行业务入口 → 业务代码执行完。\n * 任何一步没发生,宿主都会一直等逻辑层就绪,所以超时后报告停在哪一步,照常结束启动\n */\nclass AppBoot {\n private stage: BootStage = 'alloc';\n private finished = false;\n private readonly timer: ReturnType<typeof setTimeout>;\n\n constructor(private readonly host: HostApi) {\n this.timer = setTimeout(() => {\n this.finish(new Error(`[wxa-runner] 逻辑层 ${BOOT_TIMEOUT}ms 内没有就绪:${BOOT_STAGES[this.stage]}`));\n }, BOOT_TIMEOUT);\n }\n\n reach(stage: BootStage) {\n this.stage = stage;\n }\n\n /** 通知宿主逻辑层就绪,只通知一次;出错时先报告错误 */\n finish(error?: Error) {\n if (this.finished) return;\n this.finished = true;\n clearTimeout(this.timer);\n if (error) {\n console.error(error.message);\n this.host.reportError('service', 0, error);\n }\n this.host.frameLoaded('service', 0);\n }\n}\n\n/** 按顺序加载外部脚本(保留文件名和行号,便于在 DevTools 里调试),全部执行完后回调 */\nfunction loadScripts(win: Window, urls: string[], done: Callback) {\n let remaining = urls.length;\n if (remaining === 0) {\n done();\n return;\n }\n for (const url of urls) {\n const script = win.document.createElement('script');\n script.async = false;\n script.src = url;\n const settle = () => {\n if (--remaining === 0) done();\n };\n script.onload = settle;\n script.onerror = () => {\n console.error(`[wxa-runner] 加载 ${url} 失败`);\n settle();\n };\n win.document.head.appendChild(script);\n }\n}\n","/**\n * 基础库伴生 SDK 子包能力的占位实现\n *\n * WAService.js 不是自包含的。广告、云开发、米大师支付等能力放在一组伴生文件里\n * (WAAppAd.js / WACloud.js / WAMidasSDK.js 等),真机和开发者工具由原生层调用\n * loadMainContextLibFile 把它们同步加载进同一个上下文,再把导出挂到约定的全局名上\n * (WAAppAd.js → globalThis.AD → 基础库读作 ADSDK)。运行时没有这套加载机制。\n *\n * 缺失不会直接抛到业务代码:基础库把内部异常包成 appServiceSDKScriptError 自己吞掉,\n * 于是 wx.createRewardedVideoAd() 返回 undefined。真正崩的是下一行业务代码\n * ——`ad.onError(...)`,Cannot read properties of undefined。所以占位放在 wx 这一层,\n * 不管基础库内部走的是哪条失败路径(3.7.0 上 createRewardedVideoAd 栽在\n * loadSdkSubPackage,createInterstitialAd 栽在 ADSDK 未定义)都能接住。\n *\n * 不在 ADSDK / __cloudSDKMain__ 这些全局上打桩:基础库 init 时会按子包注册表回写\n * 这些全局,占位会被覆盖掉;而 SkylineGlobal / NativeGlobal / xrFrame 等是基础库会\n * typeof 检测的能力开关,补上反而会让它走进依赖更多的分支,比缺失更糟。\n */\n\nconst UNSUPPORTED = '浏览器运行时不支持广告';\n\ntype Listener = (...args: unknown[]) => void;\n\n/** 没人接的占位调用不该变成 unhandledrejection,但返回的 promise 仍然可以被 catch */\nfunction rejected(reason: unknown): Promise<never> {\n const promise = Promise.reject(reason);\n promise.catch(() => undefined);\n return promise;\n}\n\nclass StubAd {\n private listeners: Record<string, Listener[]> = {};\n\n constructor(private readonly hideable: boolean) {}\n\n load() { return this.fail(); }\n show() { return this.fail(); }\n destroy() { this.listeners = {}; }\n\n onLoad(callback: Listener) { this.add('load', callback); }\n offLoad(callback?: Listener) { this.remove('load', callback); }\n onError(callback: Listener) { this.add('error', callback); }\n offError(callback?: Listener) { this.remove('error', callback); }\n onClose(callback: Listener) { this.add('close', callback); }\n offClose(callback?: Listener) { this.remove('close', callback); }\n\n /** 只有原生模板广告(createCustomAd)有这组接口 */\n hide() { return this.hideable ? Promise.resolve() : undefined; }\n isShow() { return this.hideable ? false : undefined; }\n onHide(callback: Listener) { if (this.hideable) this.add('hide', callback); }\n offHide(callback?: Listener) { if (this.hideable) this.remove('hide', callback); }\n\n private add(event: string, callback: Listener) {\n (this.listeners[event] = this.listeners[event] || []).push(callback);\n }\n\n private remove(event: string, callback?: Listener) {\n if (!this.listeners[event]) return;\n this.listeners[event] = callback ? this.listeners[event].filter(l => l !== callback) : [];\n }\n\n /** 真机上拉取失败也是先回调 onError 再 reject,这里保持一致 */\n private fail() {\n const error = { errCode: 1000, errMsg: UNSUPPORTED };\n queueMicrotask(() => {\n for (const listener of (this.listeners.error || []).slice()) listener({ ...error });\n });\n return rejected(error);\n }\n}\n\n/** 基础库缺少伴生子包时会返回 undefined 的广告接口 */\nexport const UNSUPPORTED_AD_APIS = [\n 'createRewardedVideoAd',\n 'createInterstitialAd',\n 'createCustomAd',\n 'createSkitAd'\n] as const;\n\nexport interface ApiStubOptions {\n /** 默认 console.warn,测试里可以注入收集 */\n warn?: (message: string) => void;\n}\n\n/** 标在占位函数上,重复调用 installApiStubs 时据此跳过 */\nconst STUB = Symbol.for('wxa-runner.apiStub') as unknown as string;\n\n/** 每次 require 都会重装一遍,提示挂在 wx 上,第一次用到广告时出一次 */\nconst WARNED = Symbol.for('wxa-runner.apiStubWarned') as unknown as string;\n\n/**\n * 替换掉基础库里这些返回 undefined 的接口。\n * 幂等:装过的不再重装,可以在每次 require 前安全调用。\n * 返回这次实际替换的名字;wx 上的属性个别基础库版本可能不可配置,那种就跳过。\n */\nexport function installApiStubs(wx: Record<string, any>, options: ApiStubOptions = {}): string[] {\n const warn = options.warn || ((message: string) => console.warn(message));\n const replaced: string[] = [];\n\n for (const name of UNSUPPORTED_AD_APIS) {\n if (wx[name]?.[STUB]) continue;\n\n const stub = () => {\n if (!wx[WARNED]) {\n wx[WARNED] = true;\n warn('[wxa-runner] 广告(WAAppAd.js)在浏览器运行时不可用,广告对象的 load/show 会失败,但不会中断页面');\n }\n return new StubAd(name === 'createCustomAd');\n };\n (stub as any)[STUB] = true;\n\n try {\n Object.defineProperty(wx, name, { value: stub, writable: true, configurable: true, enumerable: true });\n replaced.push(name);\n } catch {\n // 属性不可配置,保持基础库原样(仍会返回 undefined)\n }\n }\n\n return replaced;\n}\n","/**\n * 注入到逻辑层/渲染层 iframe 的脚本,必须在基础库之前执行\n *\n * 1. 准备开发者工具会预置的全局变量(基础库依赖它们)\n * 2. 提供 WeixinJSBridge,把调用转发给宿主\n * 3. 渲染层:模拟手机屏幕尺寸,处理鼠标输入(见 installInput)\n *\n * 新版基础库的逻辑层分主上下文和子上下文(见 context.ts)。逻辑层 iframe 是主上下文;\n * 子上下文页面也加载这个脚本(data-context-id),只准备全局变量,桥由主上下文的基础库交给它。\n */\n\nimport { installWeixinJSContext } from './context';\nimport { installApiStubs } from './sdkStubs';\nimport type { FrameBridge, FrameKind, HostApi } from './types';\n\ntype Listener = (data: unknown, webviewId?: number) => void;\n\nconst script = document.currentScript as HTMLScriptElement;\nconst kind = (script.dataset.kind || 'webview') as FrameKind;\nconst webviewId = Number(script.dataset.webviewId || 0);\nconst subContextId = Number(script.dataset.contextId || 0);\nconst host = ((subContextId ? window.parent.parent : window.parent) as any).__wxaHost as HostApi;\nconst g = window as any;\n\ng.__global = g;\n\nif (kind === 'service') {\n Object.assign(g, {\n __wxAppData: {},\n __wxRoute: undefined,\n __wxRouteBegin: undefined,\n __wxAppCode__: {},\n __wxAppCurrentFile__: undefined,\n __vd_version_info__: {},\n global: {},\n __workerVendorCode__: {},\n __workersCode__: {},\n WeixinWorker: {},\n $gwx: undefined\n });\n g.__WeixinWorker = g.WeixinWorker;\n // 基础库初始化完成后通过它交出 App/Page/Component/wx/define/require 等全局对象\n g.__passWAServiceGlobal__ = (globals: Record<string, unknown>) => {\n for (const key of Object.keys(globals)) {\n if (key !== 'Protect') g[key] = globals[key];\n }\n };\n hookRequire();\n} else {\n emulateDeviceScreen(host.device);\n installInput();\n runLoadCallbacksEarly();\n}\n\noverrideUserAgent();\n\nwindow.addEventListener('error', event => host.reportError(kind, webviewId, event.error || event.message));\nwindow.addEventListener('unhandledrejection', event => host.reportError(kind, webviewId, event.reason));\n\nif (subContextId) {\n (window.parent as any).__wxaContexts.prepare(subContextId, window);\n} else {\n const bridge = createBridge();\n g.WeixinJSBridge = bridge;\n // 基础库会用自己的包装替换 WeixinJSBridge,宿主始终通过这个引用回调\n g.__wxaBridge = bridge;\n if (script.dataset.appService) {\n installWeixinJSContext(window, host, {\n dispatchNative: bridge.__dispatchOn,\n appServiceScripts: JSON.parse(script.dataset.appService),\n hot: script.dataset.hot === '1'\n });\n }\n host.registerFrame(kind, window, bridge, webviewId);\n}\n\n/**\n * 基础库初始化完会把广告等缺伴生子包的接口改成「返回 undefined」的函数,占位只有在\n * 业务代码执行前装才留得住 —— bootstrap 里 require 第一个业务模块就是那个时机。\n *\n * 这里用存取器占住 require 再等基础库赋值,而不是事后包装:基础库交出全局的方式按版本\n * 而异(3.7.0 直接写 globalThis,并不调 __passWAServiceGlobal__),事后包装没有可靠的时机。\n * installApiStubs 幂等,每次 require 都查一遍,不赌某一次调用的先后。\n */\nfunction hookRequire() {\n let real: unknown;\n const wrapper = function (this: unknown, ...args: unknown[]) {\n if (g.wx) installApiStubs(g.wx);\n return (real as (...a: unknown[]) => unknown).apply(this, args);\n };\n try {\n Object.defineProperty(g, 'require', {\n configurable: true,\n enumerable: true,\n get: () => (typeof real === 'function' ? wrapper : real),\n set: value => { real = value; }\n });\n } catch {\n // 定义不了就算了,广告接口退回基础库原样(返回 undefined)\n }\n}\n\nfunction createBridge(): FrameBridge & Record<string, unknown> {\n const onListeners: Record<string, Listener[]> = {};\n const subListeners: Record<string, Listener[]> = {};\n\n const add = (map: Record<string, Listener[]>, event: string, listener: Listener) => {\n (map[event] = map[event] || []).push(listener);\n };\n const remove = (map: Record<string, Listener[]>, event: string, listener?: Listener) => {\n if (!map[event]) return;\n map[event] = listener ? map[event].filter(l => l !== listener) : [];\n };\n const emit = (map: Record<string, Listener[]>, event: string, data: unknown, id?: number) => {\n for (const listener of (map[event] || []).slice()) {\n try {\n listener(data, id);\n } catch (error) {\n console.error(`[wxa-runner] ${event} 处理出错`, error);\n }\n }\n };\n\n return {\n invoke(api: string, args: unknown, callback?: (res: any) => void) {\n host.invoke(kind, window, api, args, callback);\n },\n publish(event: string, data: unknown, webviewIds?: number[]) {\n host.publish(kind, window, event, data, webviewIds);\n },\n subscribe(event: string, listener: Listener) {\n add(subListeners, event, listener);\n },\n on(event: string, listener: Listener) {\n add(onListeners, event, listener);\n },\n addEventListener(event: string, listener: Listener) {\n add(onListeners, event, listener);\n },\n removeEventListener(event: string, listener?: Listener) {\n remove(onListeners, event, listener);\n },\n addSubscribeListener(event: string, listener: Listener) {\n add(subListeners, event, listener);\n },\n removeSubscribeListener(event: string, listener?: Listener) {\n remove(subListeners, event, listener);\n },\n __dispatchOn(event: string, data: unknown, id?: number) {\n emit(onListeners, event, data, id);\n },\n __dispatchSub(event: string, data: unknown, id?: number) {\n emit(subListeners, event, data, id);\n }\n };\n}\n\n/**\n * wcsc 生成的 rpx 换算读取 window.screen.width,桌面浏览器里那是显示器宽度,\n * 这里改成模拟设备的尺寸。\n */\nfunction emulateDeviceScreen(device: HostApi['device']) {\n const values: Record<string, number> = {\n width: device.screenWidth,\n height: device.screenHeight,\n availWidth: device.screenWidth,\n availHeight: device.screenHeight\n };\n for (const key of Object.keys(values)) {\n try {\n Object.defineProperty(window.screen, key, { get: () => values[key], configurable: true });\n } catch {\n // 个别浏览器不允许重定义,退回到真实值\n }\n }\n // 桌面浏览器报告横屏,基础库会因此改用 screen.height 作为设备宽度换算 rpx\n const portrait = {\n type: 'portrait-primary',\n angle: 0,\n onchange: null,\n addEventListener() {},\n removeEventListener() {},\n dispatchEvent: () => false,\n lock: () => Promise.reject(new Error('not supported')),\n unlock() {}\n };\n try {\n Object.defineProperty(window.screen, 'orientation', { get: () => portrait, configurable: true });\n } catch {\n // 同上\n }\n try {\n Object.defineProperty(window, 'devicePixelRatio', { get: () => device.pixelRatio, configurable: true });\n } catch {\n // 同上\n }\n}\n\n/**\n * 基础库在文档没加载完时,把内置组件样式(wx-view 的 display、wx-canvas 的默认尺寸等)推迟到\n * window.onload 再注入。开发者工具在文档加载完后才注入基础库,那边是立即注入;这里基础库随页面\n * 同步加载,首屏渲染早于 onload,canvas 这类挂载时测量尺寸的组件会量到没有样式时的大小。\n * 所以加载完成前赋给 window.onload 的回调改为在当前脚本执行完后立即运行,仍早于首屏渲染。\n * 效果与开发者工具一致:那边每处都直接调用回调,多次赋值各自执行,window.onload 本身始终为空。\n */\nfunction runLoadCallbacksEarly() {\n let owner: object | null = window;\n while (owner && !Object.getOwnPropertyDescriptor(owner, 'onload')) owner = Object.getPrototypeOf(owner);\n const native = owner && Object.getOwnPropertyDescriptor(owner, 'onload');\n if (!native?.get || !native.set) return;\n Object.defineProperty(window, 'onload', {\n configurable: true,\n get: () => native.get!.call(window),\n set(handler: unknown) {\n if (typeof handler === 'function' && document.readyState !== 'complete') {\n queueMicrotask(() => handler.call(window, new Event('load')));\n } else {\n native.set!.call(window, handler);\n }\n }\n });\n}\n\nfunction overrideUserAgent() {\n const ua = `${navigator.userAgent} (iPhone; wxa-runner) MicroMessenger/8.0.50 miniProgram`;\n try {\n Object.defineProperty(navigator, 'userAgent', { get: () => ua, configurable: true });\n } catch {\n // 只影响基础库对平台的判断,失败可以忽略\n }\n}\n\n/**\n * 鼠标输入 → 触摸事件\n *\n * 模拟的是手机,页面只应收到触摸事件。基础库在部分版本/平台上会自己把鼠标或 pointer 事件\n * 转换为触摸,和这里的转换叠加会导致一次点击触发两次 tap,所以在 window 捕获阶段\n * (先于基础库注册的任何监听)拦下鼠标类事件。不调用 preventDefault,输入框聚焦等默认行为不受影响。\n *\n * 另外,基础库在元素滚动后 50ms 内会把触摸当作滑动、取消 tap。自动化测试常常是\n * 「滚动到元素 → 立刻点击」,而 scroll 事件要到下一帧才派发,所以按下时先等两帧\n * 让挂起的 scroll 事件派发完,刚滚动过的话再顺延到窗口之后。同一次按压的事件按原顺序派发。\n */\nfunction installInput() {\n const SCROLL_TAP_GUARD = 80;\n let lastScroll = 0;\n let queue: Promise<void> = Promise.resolve();\n let target: EventTarget | null = null;\n\n document.addEventListener('scroll', () => {\n lastScroll = Date.now();\n }, true);\n\n const nextFrame = () => new Promise<void>(resolve => requestAnimationFrame(() => resolve()));\n const sleep = (ms: number) => new Promise<void>(resolve => setTimeout(resolve, ms));\n\n const fire = (type: 'touchstart' | 'touchmove' | 'touchend', event: MouseEvent, eventTarget: EventTarget) => {\n const point = {\n clientX: event.clientX,\n clientY: event.clientY,\n pageX: event.pageX,\n pageY: event.pageY,\n screenX: event.screenX,\n screenY: event.screenY\n };\n queue = queue.then(async () => {\n if (type === 'touchstart') {\n await nextFrame();\n await nextFrame();\n const wait = lastScroll + SCROLL_TAP_GUARD - Date.now();\n if (wait > 0) await sleep(wait);\n }\n const touch = new Touch({ identifier: 1, target: eventTarget, ...point });\n const active = type === 'touchend' ? [] : [touch];\n eventTarget.dispatchEvent(new TouchEvent(type, {\n bubbles: true,\n cancelable: true,\n composed: true,\n touches: active,\n targetTouches: active,\n changedTouches: [touch]\n }));\n });\n };\n\n window.addEventListener('mousedown', event => {\n event.stopImmediatePropagation();\n if (event.button !== 0 || !event.target) return;\n target = event.target;\n fire('touchstart', event, target);\n }, true);\n window.addEventListener('mousemove', event => {\n event.stopImmediatePropagation();\n if (target) fire('touchmove', event, target);\n }, true);\n window.addEventListener('mouseup', event => {\n event.stopImmediatePropagation();\n if (!target) return;\n fire('touchend', event, target);\n target = null;\n }, true);\n for (const type of ['pointerdown', 'pointermove', 'pointerup', 'pointercancel']) {\n window.addEventListener(type, event => {\n if ((event as PointerEvent).pointerType !== 'touch') event.stopImmediatePropagation();\n }, true);\n }\n}\n"],"mappings":"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","names":["script","host","script"]}
@@ -84,6 +84,160 @@
84
84
  return { errMsg: `${api}:fail ${message}` };
85
85
  }
86
86
 
87
+ // src/runtime/host/api/audio.ts
88
+ var STATES = {
89
+ canplay: "canplay",
90
+ playing: "play",
91
+ ended: "ended",
92
+ waiting: "waiting",
93
+ seeking: "seeking",
94
+ seeked: "seeked"
95
+ };
96
+ var HAVE_METADATA = 1;
97
+ var ERROR_CODES = { 2: 10002, 3: 10004, 4: 10004 };
98
+ var audioSeq = 0;
99
+ function createAudioApis(options) {
100
+ const { emit, createAudio = () => new Audio() } = options;
101
+ const instances = /* @__PURE__ */ new Map();
102
+ const createAudioInstance = (_args, { api }) => {
103
+ const audioId = ++audioSeq;
104
+ const audio = createAudio();
105
+ const listening = new AbortController();
106
+ const instance = {
107
+ audio,
108
+ src: "",
109
+ startTime: 0,
110
+ played: false,
111
+ stopped: false,
112
+ report: (state, extra) => emit("onAudioStateChange", { audioId, state, ...extra }),
113
+ destroy: () => {
114
+ listening.abort();
115
+ audio.pause();
116
+ audio.removeAttribute("src");
117
+ audio.load();
118
+ }
119
+ };
120
+ const on = (type, listener) => audio.addEventListener(type, listener, { signal: listening.signal });
121
+ for (const [type, state] of Object.entries(STATES)) {
122
+ on(type, () => {
123
+ if (!instance.stopped) instance.report(state);
124
+ });
125
+ }
126
+ on("loadedmetadata", () => {
127
+ if (!instance.played && instance.startTime > 0) audio.currentTime = instance.startTime / 1e3;
128
+ });
129
+ on("error", () => {
130
+ const code = audio.error?.code ?? 0;
131
+ instance.report("error", { errCode: ERROR_CODES[code] ?? -1, errMsg: audio.error?.message || `MediaError ${code}` });
132
+ });
133
+ instances.set(audioId, instance);
134
+ return ok(api, { audioId });
135
+ };
136
+ const withInstance = (args, api, action) => {
137
+ const instance = instances.get(args.audioId);
138
+ return instance ? ok(api, action(instance) || {}) : fail(api, `audio instance ${args.audioId} not found`);
139
+ };
140
+ return {
141
+ createAudioInstance,
142
+ createAudioInstanceAsync: createAudioInstance,
143
+ // 状态里的 paused、currentTime 等是基础库缓存的旧值,只取能设置的属性
144
+ setAudioState: (args, { api }) => withInstance(args, api, (instance) => {
145
+ const { audio } = instance;
146
+ if (typeof args.autoplay === "boolean") audio.autoplay = args.autoplay;
147
+ if (typeof args.loop === "boolean") audio.loop = args.loop;
148
+ if (typeof args.volume === "number") audio.volume = args.volume;
149
+ if (typeof args.playbackRate === "number") audio.playbackRate = args.playbackRate;
150
+ if (typeof args.src === "string" && args.src !== instance.src) {
151
+ Object.assign(instance, { src: args.src, played: false, stopped: false });
152
+ audio.src = args.src;
153
+ }
154
+ if (typeof args.startTime === "number" && args.startTime !== instance.startTime) {
155
+ instance.startTime = args.startTime;
156
+ if (!instance.played && audio.readyState >= HAVE_METADATA) audio.currentTime = args.startTime / 1e3;
157
+ }
158
+ }),
159
+ getAudioState: (args, { api }) => withInstance(args, api, ({ audio, src, startTime }) => ({
160
+ src,
161
+ startTime,
162
+ paused: audio.paused,
163
+ currentTime: Math.round(audio.currentTime * 1e3),
164
+ duration: Number.isFinite(audio.duration) ? Math.round(audio.duration * 1e3) : 0,
165
+ buffered: audio.buffered.length ? Math.round(audio.buffered.end(audio.buffered.length - 1) * 1e3) : 0,
166
+ volume: audio.volume,
167
+ autoplay: audio.autoplay,
168
+ loop: audio.loop,
169
+ playbackRate: audio.playbackRate
170
+ })),
171
+ operateAudio: (args, { api }) => withInstance(args, api, (instance) => {
172
+ const { audio } = instance;
173
+ switch (args.operationType) {
174
+ case "play":
175
+ Object.assign(instance, { played: true, stopped: false });
176
+ audio.play().catch((error) => {
177
+ if (error.name === "NotAllowedError") instance.report("error", { errCode: -1, errMsg: `${error.name}: ${error.message}` });
178
+ });
179
+ break;
180
+ // 浏览器的 pause 事件不转发:它在 stop 之后才异步派发,播到结尾时也会先派发一次
181
+ case "pause":
182
+ if (!audio.paused) instance.report("pause");
183
+ audio.pause();
184
+ break;
185
+ case "stop":
186
+ instance.stopped = true;
187
+ audio.pause();
188
+ audio.currentTime = 0;
189
+ instance.report("stop");
190
+ break;
191
+ case "seek":
192
+ instance.stopped = false;
193
+ audio.currentTime = Number(args.currentTime) / 1e3;
194
+ break;
195
+ default:
196
+ throw new Error(`unknown operationType ${args.operationType}`);
197
+ }
198
+ }),
199
+ destroyAudioInstance: (args, { api }) => {
200
+ instances.get(args.audioId)?.destroy();
201
+ instances.delete(args.audioId);
202
+ return ok(api);
203
+ }
204
+ };
205
+ }
206
+
207
+ // src/runtime/syncScript.ts
208
+ function readSync(url) {
209
+ const xhr = new XMLHttpRequest();
210
+ xhr.open("GET", url, false);
211
+ xhr.send();
212
+ if (xhr.status !== 200) throw new Error(`[wxa-runner] \u52A0\u8F7D ${url} \u5931\u8D25\uFF1A${xhr.status}`);
213
+ return xhr.responseText;
214
+ }
215
+ function runScript(win, url, code) {
216
+ const href = new URL(url, location.href).href;
217
+ const sourceMap = url.startsWith("/__baselib__/") ? `
218
+ //# sourceMappingURL=${href}.map` : "";
219
+ const script = win.document.createElement("script");
220
+ script.text = `${code}
221
+ //# sourceURL=${href}${sourceMap}`;
222
+ win.document.head.appendChild(script);
223
+ }
224
+
225
+ // src/runtime/host/api/libFiles.ts
226
+ function createLibFileApis(options) {
227
+ const loadLibFiles = (args, { api, from, webviewId }) => {
228
+ const win = from === "webview" ? options.windowOf(webviewId) : null;
229
+ if (!win) return ok(api);
230
+ const codes = args.paths.map((file) => {
231
+ const url = `/__baselib__/${file}`;
232
+ const code = readSync(url);
233
+ if (file.endsWith(".js")) runScript(win, url, code);
234
+ return code;
235
+ });
236
+ return ok(api, { __codes: codes });
237
+ };
238
+ return { loadLibFiles, loadLibFilesSync: loadLibFiles };
239
+ }
240
+
87
241
  // src/runtime/host/api/tempFiles.ts
88
242
  var TEMP_DIR = "/__wxa__/tmp";
89
243
  async function saveTempFile(data, type) {
@@ -300,6 +454,11 @@
300
454
  for (const name of Object.keys(fileApis)) {
301
455
  if (!name.startsWith("fs_")) fileApis[name + "Sync"] = fileApis[name];
302
456
  }
457
+ const readMemoryFile = fileApis.readFile;
458
+ fileApis.readFile = (args, context) => /^[a-z]+:\/\//i.test(String(args.filePath)) ? readMemoryFile(args, context) : readPackageFile(fs.normalize(args.filePath), args.encoding).then(
459
+ (data) => ok(context.api, { data }),
460
+ (error) => fail(context.api, error.message)
461
+ );
303
462
  return {
304
463
  ...fileApis,
305
464
  // canvas 导出图片、拍照、录像的结果都经过这里
@@ -344,6 +503,14 @@
344
503
  if (!response.ok || !body) throw new Error(body?.error || `\u5F00\u53D1\u670D\u52A1\u5668\u8FD4\u56DE HTTP ${response.status}`);
345
504
  return body;
346
505
  }
506
+ async function readPackageFile(filePath, encoding) {
507
+ if (encoding !== void 0 && encoding !== "utf8" && encoding !== "utf-8") {
508
+ 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}`);
509
+ }
510
+ const response = await fetch(filePath.split("/").map(encodeURIComponent).join("/"));
511
+ if (!response.ok) throw new Error(`no such file or directory, open ${filePath}`);
512
+ return encoding ? response.text() : response.arrayBuffer();
513
+ }
347
514
  function mockUser() {
348
515
  return { nickName: "wxa-runner", avatarUrl: "", gender: 0, country: "", province: "", city: "", language: "zh_CN" };
349
516
  }
@@ -508,25 +675,42 @@
508
675
  }
509
676
  return ok(api);
510
677
  };
511
- const createTask = {
512
- createRequestTask,
513
- createRequestTaskAsync: createRequestTask,
514
- createDownloadTask,
515
- createDownloadTaskAsync: createDownloadTask,
516
- createUploadTask,
517
- createUploadTaskAsync: createUploadTask,
518
- createSocketTask
678
+ const downloadAudio = (args, { api }) => {
679
+ const requestTaskId = startTask(args, async (signal, id) => {
680
+ try {
681
+ const res = await proxyFetch(args.url, { method: "GET", header: args.header, signal });
682
+ const meta = { requestTaskId: id, statusCode: res.statusCode, header: res.header, cookies: res.cookies };
683
+ emit("onRequestTaskStateChange", { ...meta, state: "headersReceived" });
684
+ emit("onRequestTaskStateChange", { ...meta, state: "success", data: await res.response.arrayBuffer(), profile: {} });
685
+ } catch (error) {
686
+ emit("onRequestTaskStateChange", { requestTaskId: id, state: "fail", errMsg: `request:fail ${reason(error)}` });
687
+ }
688
+ });
689
+ return ok(api, { requestTaskId });
519
690
  };
691
+ const requestTask = byCaller(createRequestTask, (args, context) => isAudioDownload(args) ? downloadAudio(args, context) : rejectBaseLib(args, context));
692
+ const downloadTask = byCaller(createDownloadTask);
693
+ const uploadTask = byCaller(createUploadTask);
520
694
  return {
521
- ...Object.fromEntries(Object.entries(createTask).map(([api, handler]) => [api, rejectBaseLibInternal(handler)])),
695
+ createRequestTask: requestTask,
696
+ createRequestTaskAsync: requestTask,
697
+ createDownloadTask: downloadTask,
698
+ createDownloadTaskAsync: downloadTask,
699
+ createUploadTask: uploadTask,
700
+ createUploadTaskAsync: uploadTask,
701
+ createSocketTask: byCaller(createSocketTask),
522
702
  operateRequestTask: (args) => abortTask(args, "requestTaskId"),
523
703
  operateDownloadTask: (args) => abortTask(args, "downloadTaskId"),
524
704
  operateUploadTask: (args) => abortTask(args, "uploadTaskId"),
525
705
  operateSocketTask
526
706
  };
527
707
  }
528
- function rejectBaseLibInternal(handler) {
529
- return (args, context) => args?.__skipDomainCheck__ === true ? fail(context.api, "\u57FA\u7840\u5E93\u5185\u90E8\u7684\u7F51\u7EDC\u8BF7\u6C42\uFF0Cwxa-runner \u4E0D\u53D1\u51FA") : handler(args, context);
708
+ var rejectBaseLib = (_args, { api }) => fail(api, "\u57FA\u7840\u5E93\u5185\u90E8\u7684\u7F51\u7EDC\u8BF7\u6C42\uFF0Cwxa-runner \u4E0D\u53D1\u51FA");
709
+ function byCaller(forApp, forBaseLib = rejectBaseLib) {
710
+ return (args, context) => args?.__skipDomainCheck__ === true ? forBaseLib(args, context) : forApp(args, context);
711
+ }
712
+ function isAudioDownload(args) {
713
+ return args.responseType === "arraybuffer" && args.enableCache === true;
530
714
  }
531
715
  async function proxyFetch(url, init) {
532
716
  if (!/^https?:\/\//i.test(url)) throw new Error(`invalid url "${url}"`);
@@ -1970,7 +2154,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
1970
2154
  const webviewId = kind === "webview" ? this.webviewIdOf(win) : this.currentPage()?.id ?? 0;
1971
2155
  const result = this.api.invoke(api, args, { api, from: kind, webviewId });
1972
2156
  const deliver = (res) => {
1973
- if (callback) callback(kind === "service" ? this.cloneForService(res) : cloneInto(win, res));
2157
+ if (callback) callback(cloneNativeInto(kind === "service" ? this.serviceWindow() : win, res));
1974
2158
  };
1975
2159
  if (result && typeof result.then === "function") {
1976
2160
  result.then(deliver);
@@ -2007,7 +2191,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
2007
2191
  }
2008
2192
  /**
2009
2193
  * 业务代码只运行在逻辑层,所以只记逻辑层调用、名字在 wx 上的 API,每个 API 一次。
2010
- * 其余是基础库内部调用的原生接口(如 getPermissionBytes、loadLibFilesSync),业务既没调用也 mock 不了
2194
+ * 其余是基础库内部调用的原生接口(如 getPermissionBytes),业务既没调用也 mock 不了
2011
2195
  */
2012
2196
  reportUnimplemented({ api, from }) {
2013
2197
  const wx = this.serviceWindow()?.wx;
@@ -2201,7 +2385,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
2201
2385
  emitToService(event, data, webviewId) {
2202
2386
  const service = this.service;
2203
2387
  if (!service) return;
2204
- const payload = this.cloneForService(data);
2388
+ const payload = cloneNativeInto(this.serviceWindow(), data);
2205
2389
  queueMicrotask(() => service.bridge.__dispatchOn(event, payload, webviewId));
2206
2390
  }
2207
2391
  /** 派发给渲染层的原生事件(渲染层里 WeixinJSBridge.on 收到) */
@@ -2245,6 +2429,8 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
2245
2429
  routes: this.routes,
2246
2430
  onRequest: (request) => this.requests.add(request)
2247
2431
  }),
2432
+ ...createAudioApis({ emit: (event, data) => this.emitToService(event, data) }),
2433
+ ...createLibFileApis({ windowOf: (webviewId) => this.pages.get(webviewId)?.win }),
2248
2434
  ...createUiApis({ shell: this.shell, updateNavigation: (state) => this.updateNavigation(state) }),
2249
2435
  ...createMediaApis({
2250
2436
  showActionSheet: (options) => this.shell.showActionSheet(options),
@@ -2272,6 +2458,24 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
2272
2458
  if (value === void 0) return value;
2273
2459
  return win.JSON.parse(JSON.stringify(value));
2274
2460
  }
2461
+ var BUFFER_KEY = "__wxa_array_buffer__";
2462
+ function cloneNativeInto(win, value) {
2463
+ if (value === void 0) return value;
2464
+ const buffers = [];
2465
+ const json = JSON.stringify(value, (_key, item) => {
2466
+ if (Object.prototype.toString.call(item) !== "[object ArrayBuffer]") return item;
2467
+ buffers.push(item);
2468
+ return { [BUFFER_KEY]: buffers.length - 1 };
2469
+ });
2470
+ const targetJson = win.JSON;
2471
+ if (!buffers.length) return targetJson.parse(json);
2472
+ return targetJson.parse(json, (_key, item) => item?.[BUFFER_KEY] === void 0 ? item : copyBuffer(win, buffers[item[BUFFER_KEY]]));
2473
+ }
2474
+ function copyBuffer(win, source) {
2475
+ const copy = new win.ArrayBuffer(source.byteLength);
2476
+ new Uint8Array(copy).set(new Uint8Array(source));
2477
+ return copy;
2478
+ }
2275
2479
  function withDrawableImages(message) {
2276
2480
  const actions = message?.data?.actions;
2277
2481
  if (!Array.isArray(actions)) return message;
@@ -2322,7 +2526,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
2322
2526
  const sheets = win.__styleSheetManager2__?._pathMap;
2323
2527
  if (!sheets) throw new Error("\u57FA\u7840\u5E93\u6CA1\u6709\u6837\u5F0F\u8868\u7BA1\u7406\u5668\uFF0C\u65E0\u6CD5\u70ED\u66FF\u6362\u6837\u5F0F");
2324
2528
  const applied = Object.keys(sheets);
2325
- runScript(win, code);
2529
+ runScript2(win, code);
2326
2530
  for (const key of applied) {
2327
2531
  const [, file, classPrefix] = /^\.\/(.+\.wxss):(.*)$/.exec(key) || [];
2328
2532
  const inject = file && win.__wxAppCode__[file];
@@ -2342,7 +2546,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
2342
2546
  function updateTemplates(win, code, units) {
2343
2547
  const cache = win.__WXML_GLOBAL__;
2344
2548
  if (cache) Object.assign(cache, { ops_cached: {}, ops_set: {}, ops_init: {}, debuginfo_set: {}, modules: {} });
2345
- runScript(win, code);
2549
+ runScript2(win, code);
2346
2550
  for (const id of units) {
2347
2551
  const generate = win.__wxAppCode__[id + ".wxml"];
2348
2552
  if (generate) win.__virtualDOM__.updateWxAppCode(id + ".wxml", generate);
@@ -2381,7 +2585,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
2381
2585
  factory = fn;
2382
2586
  };
2383
2587
  try {
2384
- runScript(service, `(function (define) {
2588
+ runScript2(service, `(function (define) {
2385
2589
  ${script}
2386
2590
  })(__wxaHotDefine__);`);
2387
2591
  } finally {
@@ -2415,7 +2619,7 @@ ${script}
2415
2619
  const added = Object.keys(data).filter((key) => !(key in instance.data));
2416
2620
  if (added.length) instance.setData(Object.fromEntries(added.map((key) => [key, data[key]])));
2417
2621
  }
2418
- function runScript(win, code) {
2622
+ function runScript2(win, code) {
2419
2623
  let failed = false;
2420
2624
  let error;
2421
2625
  const onError = (event) => {