@open-wxa/wxa-runner-core 0.2.5 → 0.3.1
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 +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/runtime/frame.js +2 -0
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/host.js +69 -19
- package/dist/runtime/host.js.map +1 -1
- package/dist/{setup-COzZ6vzS.d.mts → setup-Cv340Lvj.d.mts} +7 -3
- package/dist/{setup-COzZ6vzS.d.ts → setup-Cv340Lvj.d.ts} +7 -3
- package/dist/setup.d.mts +1 -1
- package/dist/setup.d.ts +1 -1
- package/dist/setup.js.map +1 -1
- package/dist/setup.mjs.map +1 -1
- package/dist/test-api.d.mts +2 -2
- package/dist/test-api.d.ts +2 -2
- package/dist/{testApi-CbBoHXdN.d.mts → testApi-DO2FyR78.d.mts} +1 -1
- package/dist/{testApi-DRZ-hXpC.d.ts → testApi-nKsjjEhz.d.ts} +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ResolvedBaseLib } from '@open-wxa/wxa-runner-extractor';
|
|
2
|
-
import { D as DeviceProfile } from './setup-
|
|
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-
|
|
4
|
-
export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-
|
|
2
|
+
import { D as DeviceProfile } from './setup-Cv340Lvj.mjs';
|
|
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-Cv340Lvj.mjs';
|
|
4
|
+
export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-DO2FyR78.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
|
-
import { D as DeviceProfile } from './setup-
|
|
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-
|
|
4
|
-
export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-
|
|
2
|
+
import { D as DeviceProfile } from './setup-Cv340Lvj.js';
|
|
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-Cv340Lvj.js';
|
|
4
|
+
export { F as FrameError, P as PageSnapshot, R as RecordedRequest, W as WxaTestApi } from './testApi-nKsjjEhz.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* 小程序项目结构解析
|
package/dist/runtime/frame.js
CHANGED
|
@@ -336,6 +336,8 @@
|
|
|
336
336
|
$gwx: void 0
|
|
337
337
|
});
|
|
338
338
|
g.__WeixinWorker = g.WeixinWorker;
|
|
339
|
+
delete g.MutationObserver;
|
|
340
|
+
delete g.WebKitMutationObserver;
|
|
339
341
|
g.__passWAServiceGlobal__ = (globals) => {
|
|
340
342
|
for (const key of Object.keys(globals)) {
|
|
341
343
|
if (key !== "Protect") g[key] = globals[key];
|
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
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 // 真机的逻辑层没有 DOM。按全局对象上有没有 MutationObserver 判断是否在浏览器里的库(如 core-js 2 的微任务 polyfill)\n // 看到它就去用 document,而业务代码里的 document 被模块包装屏蔽了(见 AppBuilder 的 MODULE_PARAMS),app.js 执行出错\n delete g.MutationObserver;\n delete g.WebKitMutationObserver;\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"]}
|
package/dist/runtime/host.js
CHANGED
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
return { ...extra, errMsg: `${api}:fail ${reason2}` };
|
|
77
77
|
}
|
|
78
78
|
function normalize(api, result) {
|
|
79
|
+
if (typeof result === "string") return result;
|
|
79
80
|
if (!result) return { errMsg: `${api}:ok` };
|
|
80
81
|
return result.errMsg ? result : { ...result, errMsg: `${api}:ok` };
|
|
81
82
|
}
|
|
@@ -238,6 +239,44 @@
|
|
|
238
239
|
return { loadLibFiles, loadLibFilesSync: loadLibFiles };
|
|
239
240
|
}
|
|
240
241
|
|
|
242
|
+
// src/runtime/host/api/map.ts
|
|
243
|
+
function createMapApis({ registry, operations }) {
|
|
244
|
+
return {
|
|
245
|
+
private_geolocation: async (_args, context) => {
|
|
246
|
+
const location2 = await registry.invoke("getLocation", { type: "gcj02" }, { ...context, api: "getLocation" });
|
|
247
|
+
if (location2.errMsg !== "getLocation:ok") return JSON.stringify({ message: location2.errMsg });
|
|
248
|
+
return JSON.stringify({ result: { location: { lat: location2.latitude, lng: location2.longitude } } });
|
|
249
|
+
},
|
|
250
|
+
// 开发者工具上没有原生地图,照基础库的格式转给当前页的 map 组件
|
|
251
|
+
moveToMapLocation: (args, { webviewId }) => operations.send(webviewId, { ...args, method: "moveToMapLocation" })
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
var MapOperations = class {
|
|
255
|
+
/** @param publish 发给渲染层,渲染层的 WeixinJSBridge.subscribe 收到 */
|
|
256
|
+
constructor(publish) {
|
|
257
|
+
this.publish = publish;
|
|
258
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
259
|
+
this.seq = 0;
|
|
260
|
+
}
|
|
261
|
+
/** map 组件做完才返回;页面上没有这个 map 时一直不返回,同基础库自己发的操作 */
|
|
262
|
+
send(webviewId, operation) {
|
|
263
|
+
const callbackId = `wxa_${++this.seq}`;
|
|
264
|
+
return new Promise((resolve) => {
|
|
265
|
+
this.pending.set(callbackId, resolve);
|
|
266
|
+
this.publish(webviewId, "operateMap", { data: { ...operation, callbackId }, options: { timestamp: Date.now() } });
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
/** map 组件发回的 operateMapCallback:是宿主发的操作时收下并返回 true,不再交给逻辑层 */
|
|
270
|
+
receive(message) {
|
|
271
|
+
const reply = message?.data;
|
|
272
|
+
const resolve = this.pending.get(reply?.callbackId);
|
|
273
|
+
if (!resolve) return false;
|
|
274
|
+
this.pending.delete(reply.callbackId);
|
|
275
|
+
resolve({ errMsg: reply.errMsg });
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
241
280
|
// src/runtime/host/api/tempFiles.ts
|
|
242
281
|
var TEMP_DIR = "/__wxa__/tmp";
|
|
243
282
|
async function saveTempFile(data, type) {
|
|
@@ -467,7 +506,11 @@
|
|
|
467
506
|
return { tempFilePath: await saveTempFile(bytes, String(args.fileType || "png")) };
|
|
468
507
|
},
|
|
469
508
|
// 基础库经这两个接口向后台拉各种配置和小程序信息
|
|
470
|
-
operateWXData: (args, { api }) =>
|
|
509
|
+
operateWXData: (args, { api }) => {
|
|
510
|
+
if (args.data?.api_name === "webapi_getwxanetwork") return bizDomainUnavailable(api);
|
|
511
|
+
if (args.data?.api_name === "webapi_getwxauserprivacyauthinfo") return ok(api, { data: { data: JSON.stringify(PRIVACY_AUTH_INFO) } });
|
|
512
|
+
return ok(api);
|
|
513
|
+
},
|
|
471
514
|
getAppContact: (args, { api }) => args.keyPath === "WxaAppInfo.Network.BizDomain" ? bizDomainUnavailable(api) : ok(api),
|
|
472
515
|
// 真实登录失败时明确返回 fail,不退回假数据:配置或登录态的问题要让开发者马上发现
|
|
473
516
|
login: options?.realLogin ? async (_args, { api }) => ok(api, { code: (await realLogin(api, "/__wxa__/api/login")).code }) : (_args, { api }) => ok(api, { code: `wxa_mock_code_${Date.now().toString(36)}` }),
|
|
@@ -514,6 +557,7 @@
|
|
|
514
557
|
function mockUser() {
|
|
515
558
|
return { nickName: "wxa-runner", avatarUrl: "", gender: 0, country: "", province: "", city: "", language: "zh_CN" };
|
|
516
559
|
}
|
|
560
|
+
var PRIVACY_AUTH_INFO = { action_code: 0, need_popup_scope_list: [], unauth_scope_list: [], wording: {} };
|
|
517
561
|
function bizDomainUnavailable(api) {
|
|
518
562
|
return fail(api, "not available in wxa-runner");
|
|
519
563
|
}
|
|
@@ -565,7 +609,7 @@
|
|
|
565
609
|
const requestTaskId = startTask(args, async (signal, id) => {
|
|
566
610
|
try {
|
|
567
611
|
const mocked = route && await route.respond(signal);
|
|
568
|
-
const res = mocked ? { statusCode: mocked.statusCode, header: mocked.header, cookies: [],
|
|
612
|
+
const res = mocked ? { statusCode: mocked.statusCode, header: mocked.header, cookies: [], response: new Response(mocked.body) } : await proxyFetch(request.url, { method: request.method, header: args.header, body: args.data, signal });
|
|
569
613
|
emit("onRequestTaskStateChange", {
|
|
570
614
|
requestTaskId: id,
|
|
571
615
|
state: "headersReceived",
|
|
@@ -573,7 +617,7 @@
|
|
|
573
617
|
statusCode: res.statusCode,
|
|
574
618
|
cookies: res.cookies
|
|
575
619
|
});
|
|
576
|
-
const data = await res.text();
|
|
620
|
+
const data = args.responseType === "arraybuffer" ? await res.response.arrayBuffer() : await res.response.text();
|
|
577
621
|
emit("onRequestTaskStateChange", {
|
|
578
622
|
requestTaskId: id,
|
|
579
623
|
state: "success",
|
|
@@ -652,11 +696,7 @@
|
|
|
652
696
|
socket.binaryType = "arraybuffer";
|
|
653
697
|
sockets.set(socketTaskId, socket);
|
|
654
698
|
socket.onopen = () => emit("onSocketTaskStateChange", { socketTaskId, state: "open", header: {}, profile: {} });
|
|
655
|
-
socket.onmessage = (event) => emit("onSocketTaskStateChange", {
|
|
656
|
-
socketTaskId,
|
|
657
|
-
state: "message",
|
|
658
|
-
data: typeof event.data === "string" ? event.data : "[binary message not supported]"
|
|
659
|
-
});
|
|
699
|
+
socket.onmessage = (event) => emit("onSocketTaskStateChange", { socketTaskId, state: "message", data: event.data });
|
|
660
700
|
socket.onerror = () => emit("onSocketTaskStateChange", { socketTaskId, state: "error", errMsg: "connectSocket:fail" });
|
|
661
701
|
socket.onclose = (event) => {
|
|
662
702
|
sockets.delete(socketTaskId);
|
|
@@ -991,11 +1031,11 @@
|
|
|
991
1031
|
checkDelay(response.delay);
|
|
992
1032
|
if (response.delay) await sleep(response.delay, signal);
|
|
993
1033
|
const { body } = response;
|
|
994
|
-
const
|
|
1034
|
+
const isJson = body !== void 0 && typeof body !== "string" && !isBinary(body);
|
|
995
1035
|
return {
|
|
996
1036
|
statusCode: response.status ?? 200,
|
|
997
|
-
header: { ...
|
|
998
|
-
|
|
1037
|
+
header: { ...isJson ? { "Content-Type": "application/json" } : {}, ...response.header },
|
|
1038
|
+
body: body === void 0 ? "" : isJson ? JSON.stringify(body) : body
|
|
999
1039
|
};
|
|
1000
1040
|
}
|
|
1001
1041
|
};
|
|
@@ -1010,6 +1050,9 @@
|
|
|
1010
1050
|
const regexp = globToRegExp(url);
|
|
1011
1051
|
return (request) => (!method || method === request.method) && regexp.test(String(request.url).replace(/[?#].*$/, ""));
|
|
1012
1052
|
}
|
|
1053
|
+
function isBinary(value) {
|
|
1054
|
+
return ArrayBuffer.isView(value) || Object.prototype.toString.call(value) === "[object ArrayBuffer]";
|
|
1055
|
+
}
|
|
1013
1056
|
function checkDelay(delay) {
|
|
1014
1057
|
if (delay !== void 0 && !(typeof delay === "number" && delay >= 0 && Number.isFinite(delay))) {
|
|
1015
1058
|
throw new Error(`delay \u9700\u8981\u662F\u4E0D\u5C0F\u4E8E 0 \u7684\u6BEB\u79D2\u6570\uFF0C\u5B9E\u9645\u662F ${String(delay)}`);
|
|
@@ -2096,6 +2139,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
|
|
|
2096
2139
|
this.api = new ApiRegistry((context) => this.reportUnimplemented(context));
|
|
2097
2140
|
/** setup 和测试 API 声明的请求拦截 */
|
|
2098
2141
|
this.routes = new RequestRoutes();
|
|
2142
|
+
this.mapOperations = new MapOperations((webviewId, event, data) => this.publishToPages(event, data, [webviewId]));
|
|
2099
2143
|
this.service = null;
|
|
2100
2144
|
/** 新版基础库的业务子上下文;旧版基础库业务代码直接在逻辑层 iframe 里 */
|
|
2101
2145
|
this.appContext = null;
|
|
@@ -2164,22 +2208,27 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
|
|
|
2164
2208
|
}
|
|
2165
2209
|
publish(kind, win, event, data, webviewIds) {
|
|
2166
2210
|
if (kind === "service") {
|
|
2167
|
-
|
|
2168
|
-
const message = event === "canvasActionsChanged" ? withDrawableImages(data) : data;
|
|
2169
|
-
for (const page of targets) {
|
|
2170
|
-
page?.dispatch((bridge, target) => {
|
|
2171
|
-
const payload2 = cloneInto(target, message);
|
|
2172
|
-
queueMicrotask(() => bridge.__dispatchSub(event, payload2, 0));
|
|
2173
|
-
});
|
|
2174
|
-
}
|
|
2211
|
+
this.publishToPages(event, data, webviewIds);
|
|
2175
2212
|
return;
|
|
2176
2213
|
}
|
|
2214
|
+
if (event === "operateMapCallback" && this.mapOperations.receive(data)) return;
|
|
2177
2215
|
const fromId = this.webviewIdOf(win);
|
|
2178
2216
|
const service = this.service;
|
|
2179
2217
|
if (!service) return;
|
|
2180
2218
|
const payload = this.cloneForService(data);
|
|
2181
2219
|
queueMicrotask(() => service.bridge.__dispatchSub(event, payload, fromId));
|
|
2182
2220
|
}
|
|
2221
|
+
/** 不指定目标时发给所有页面:旧版 canvas 的绘制指令就是这样发的,由 canvasNumber 找到对应画布 */
|
|
2222
|
+
publishToPages(event, data, webviewIds) {
|
|
2223
|
+
const targets = webviewIds?.length ? webviewIds.map((id) => this.pages.get(Number(id))) : this.livePages();
|
|
2224
|
+
const message = event === "canvasActionsChanged" ? withDrawableImages(data) : data;
|
|
2225
|
+
for (const page of targets) {
|
|
2226
|
+
page?.dispatch((bridge, target) => {
|
|
2227
|
+
const payload = cloneInto(target, message);
|
|
2228
|
+
queueMicrotask(() => bridge.__dispatchSub(event, payload, 0));
|
|
2229
|
+
});
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2183
2232
|
reportError(kind, webviewId, error) {
|
|
2184
2233
|
const err = typeof error?.message === "string" ? error : null;
|
|
2185
2234
|
this.errors.push({
|
|
@@ -2430,6 +2479,7 @@ html, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50
|
|
|
2430
2479
|
onRequest: (request) => this.requests.add(request)
|
|
2431
2480
|
}),
|
|
2432
2481
|
...createAudioApis({ emit: (event, data) => this.emitToService(event, data) }),
|
|
2482
|
+
...createMapApis({ registry: this.api, operations: this.mapOperations }),
|
|
2433
2483
|
...createLibFileApis({ windowOf: (webviewId) => this.pages.get(webviewId)?.win }),
|
|
2434
2484
|
...createUiApis({ shell: this.shell, updateNavigation: (state) => this.updateNavigation(state) }),
|
|
2435
2485
|
...createMediaApis({
|