@open-wxa/wxa-runner-core 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/runtime/host.js +44 -0
- package/dist/runtime/host.js.map +1 -1
- package/package.json +4 -4
package/dist/runtime/host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/host/api/registry.ts","../../src/runtime/host/api/audio.ts","../../src/runtime/host/api/tempFiles.ts","../../src/runtime/host/api/fs.ts","../../src/runtime/syncScript.ts","../../src/runtime/host/api/libFiles.ts","../../src/runtime/host/api/map.ts","../../src/runtime/host/api/media.ts","../../src/runtime/host/api/misc.ts","../../src/runtime/host/api/network.ts","../../src/runtime/host/api/picker.ts","../../src/runtime/host/api/routes.ts","../../src/runtime/host/api/savedFiles.ts","../../src/runtime/host/api/storage.ts","../../src/runtime/host/api/system.ts","../../src/runtime/host/api/ui.ts","../../src/runtime/host/api/webView.ts","../../src/runtime/host/PageStack.ts","../../src/runtime/host/PageView.ts","../../src/runtime/host/realm.ts","../../src/runtime/host/ui/fileChooser.ts","../../src/runtime/host/ui/dom.ts","../../src/runtime/host/ui/ImagePreview.ts","../../src/runtime/host/ui/styles.ts","../../src/runtime/host/ui/Picker.ts","../../src/runtime/host/ui/PhoneShell.ts","../../src/runtime/host/Host.ts","../../src/runtime/host/hmr.ts","../../src/runtime/host/pageStackRestore.ts","../../src/runtime/host/setup.ts","../../src/runtime/host/testApi.ts","../../src/runtime/host/index.ts"],"sourcesContent":["/**\n * 原生 API 注册表\n *\n * 处理函数返回结果对象(可以是 Promise)。结果能同步得到时同步回调——\n * 基础库在一些非 Sync 结尾的 API(如带 type 参数的 getSystemInfo)上也依赖同步回调。\n * 少数原生接口的结果是字符串,由基础库自己解析(如地图的 private_geolocation),原样交回。\n */\n\nimport type { FrameKind } from '../../types';\n\nexport type ApiResult = Record<string, any>;\n\nexport interface ApiContext {\n api: string;\n from: FrameKind;\n /** 发起调用的渲染层 id,逻辑层调用时为当前页面 */\n webviewId: number;\n}\n\nexport type ApiHandler = (args: any, context: ApiContext) => ApiResult | string | void | Promise<ApiResult | string | void>;\n\n/** 基础库内部频繁调用、无需提示的 API */\nconst SILENT_APIS = new Set([\n 'reportKeyValue', 'reportIDKey', 'reportRealtimeAction', 'reportPerformance', 'systemLog', 'traceEvent',\n 'getPermissionBytes', 'getABTestConfig', 'initRenderDone', 'saveInitialRenderingCache',\n 'setKeyValue', 'invokeMiniProgramAPI', 'updatePerfData', 'reportSubmitForm',\n 'initReady', 'noticePerformanceMetrics'\n]);\n\nexport class ApiRegistry {\n private handlers = new Map<string, ApiHandler>();\n private mocks = new Map<string, ApiHandler>();\n private warned = new Set<string>();\n\n /** @param onUnimplemented 调用了没有实现、也没有 mock 的 API 时触发,每次调用都触发;基础库内部的上报类接口不触发 */\n constructor(private readonly onUnimplemented?: (context: ApiContext) => void) {}\n\n register(handlers: Record<string, ApiHandler>) {\n for (const [name, handler] of Object.entries(handlers)) {\n this.handlers.set(name, handler);\n }\n }\n\n has(api: string): boolean {\n return this.handlers.has(api) || this.mocks.has(api);\n }\n\n /** 测试用:覆盖某个 API;传入对象时直接作为结果返回 */\n mock(api: string, impl: ApiHandler | ApiResult) {\n this.mocks.set(api, typeof impl === 'function' ? impl as ApiHandler : () => impl as ApiResult);\n }\n\n unmock(api?: string) {\n if (api) this.mocks.delete(api);\n else this.mocks.clear();\n }\n\n invoke(api: string, args: any, context: ApiContext): ApiResult | string | Promise<ApiResult | string> {\n const handler = this.mocks.get(api) || this.handlers.get(api);\n\n if (!handler) {\n if (!SILENT_APIS.has(api)) {\n this.onUnimplemented?.(context);\n if (!this.warned.has(api)) {\n this.warned.add(api);\n console.warn(`[wxa-runner] wx.${api} 尚未实现,返回默认成功`, args);\n }\n }\n return { errMsg: `${api}:ok` };\n }\n\n try {\n const result = handler(args || {}, context);\n if (result && typeof (result as Promise<ApiResult>).then === 'function') {\n return (result as Promise<ApiResult | string | void>).then(\n value => normalize(api, value),\n error => failure(api, error)\n );\n }\n return normalize(api, result as ApiResult | string | void);\n } catch (error) {\n return failure(api, error);\n }\n }\n}\n\nexport function ok(api: string, extra: ApiResult = {}): ApiResult {\n return { ...extra, errMsg: `${api}:ok` };\n}\n\nexport function fail(api: string, reason: string, extra: ApiResult = {}): ApiResult {\n return { ...extra, errMsg: `${api}:fail ${reason}` };\n}\n\nfunction normalize(api: string, result: ApiResult | string | void): ApiResult | string {\n if (typeof result === 'string') return result;\n if (!result) return { errMsg: `${api}:ok` };\n return result.errMsg ? result : { ...result, errMsg: `${api}:ok` };\n}\n\nfunction failure(api: string, error: unknown): ApiResult {\n const message = error instanceof Error ? error.message : String(error);\n return { errMsg: `${api}:fail ${message}` };\n}\n","/**\n * 原生音频接口:基础库 3.3.x 及更早版本的 InnerAudioContext 调这些接口播放,宿主用 <audio> 实现\n *\n * 3.5.8 起平台是 devtools 时基础库改用 Web Audio,不再调这些接口(下载音频见 network.ts 的 isAudioDownload)。\n * 与基础库的约定:时间都以毫秒为单位;基础库每次改属性都带上全部状态调 setAudioState;\n * timeupdate 由基础库轮询 getAudioState 自己产生,这里只推送 onAudioStateChange。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\n\nexport interface AudioApiOptions {\n /** 向逻辑层派发事件 */\n emit: (event: string, data: Record<string, unknown>) => void;\n createAudio?: () => HTMLAudioElement;\n}\n\ninterface AudioInstance {\n audio: HTMLAudioElement;\n /** 基础库设置的 src。audio.src 是浏览器解析后的完整地址,比较不出有没有变 */\n src: string;\n /** 毫秒,还没播放过时从这里开始 */\n startTime: number;\n played: boolean;\n /** stop 之后到下一次播放、跳转或换 src 之前:stop 把进度归零引起的 seeking、seeked 等不转给基础库 */\n stopped: boolean;\n report: (state: string, extra?: Record<string, unknown>) => void;\n destroy: () => void;\n}\n\n/**\n * 浏览器事件 → 基础库的状态。play 用 playing:缓冲(waiting)后浏览器只派发 playing,\n * 基础库收到 waiting 就当作暂停、停止轮询进度,要再收到 play 才恢复\n */\nconst STATES: Record<string, string> = {\n canplay: 'canplay',\n playing: 'play',\n ended: 'ended',\n waiting: 'waiting',\n seeking: 'seeking',\n seeked: 'seeked'\n};\n\n/** HTMLMediaElement.HAVE_METADATA,单元测试的 Node 环境里没有 HTMLMediaElement */\nconst HAVE_METADATA = 1;\n\n/** MediaError.code → 基础库的 errCode:10002 网络错误,10004 格式错误,其余为 -1 未知错误 */\nconst ERROR_CODES: Record<number, number> = { 2: 10002, 3: 10004, 4: 10004 };\n\nlet audioSeq = 0;\n\nexport function createAudioApis(options: AudioApiOptions): Record<string, ApiHandler> {\n const { emit, createAudio = () => new Audio() } = options;\n const instances = new Map<number, AudioInstance>();\n\n const createAudioInstance: ApiHandler = (_args, { api }) => {\n const audioId = ++audioSeq;\n const audio = createAudio();\n const listening = new AbortController();\n const instance: AudioInstance = {\n audio,\n src: '',\n startTime: 0,\n played: false,\n stopped: false,\n report: (state, extra) => emit('onAudioStateChange', { audioId, state, ...extra }),\n destroy: () => {\n listening.abort();\n audio.pause();\n audio.removeAttribute('src');\n audio.load();\n }\n };\n const on = (type: string, listener: () => void) => audio.addEventListener(type, listener, { signal: listening.signal });\n\n for (const [type, state] of Object.entries(STATES)) {\n on(type, () => {\n if (!instance.stopped) instance.report(state);\n });\n }\n on('loadedmetadata', () => {\n if (!instance.played && instance.startTime > 0) audio.currentTime = instance.startTime / 1000;\n });\n on('error', () => {\n const code = audio.error?.code ?? 0;\n instance.report('error', { errCode: ERROR_CODES[code] ?? -1, errMsg: audio.error?.message || `MediaError ${code}` });\n });\n\n instances.set(audioId, instance);\n return ok(api, { audioId });\n };\n\n /** @returns 找不到时为失败结果 */\n const withInstance = (args: any, api: string, action: (instance: AudioInstance) => Record<string, unknown> | void) => {\n const instance = instances.get(args.audioId);\n return instance ? ok(api, action(instance) || {}) : fail(api, `audio instance ${args.audioId} not found`);\n };\n\n return {\n createAudioInstance,\n createAudioInstanceAsync: createAudioInstance,\n\n // 状态里的 paused、currentTime 等是基础库缓存的旧值,只取能设置的属性\n setAudioState: (args, { api }) => withInstance(args, api, instance => {\n const { audio } = instance;\n if (typeof args.autoplay === 'boolean') audio.autoplay = args.autoplay;\n if (typeof args.loop === 'boolean') audio.loop = args.loop;\n if (typeof args.volume === 'number') audio.volume = args.volume;\n if (typeof args.playbackRate === 'number') audio.playbackRate = args.playbackRate;\n // 重新赋值 src 会从头加载\n if (typeof args.src === 'string' && args.src !== instance.src) {\n Object.assign(instance, { src: args.src, played: false, stopped: false });\n audio.src = args.src;\n }\n // 和基础库的 Web Audio 实现一致:还没播放过时立即跳过去,没加载好的等 loadedmetadata\n if (typeof args.startTime === 'number' && args.startTime !== instance.startTime) {\n instance.startTime = args.startTime;\n if (!instance.played && audio.readyState >= HAVE_METADATA) audio.currentTime = args.startTime / 1000;\n }\n }),\n\n getAudioState: (args, { api }) => withInstance(args, api, ({ audio, src, startTime }) => ({\n src,\n startTime,\n paused: audio.paused,\n currentTime: Math.round(audio.currentTime * 1000),\n duration: Number.isFinite(audio.duration) ? Math.round(audio.duration * 1000) : 0,\n buffered: audio.buffered.length ? Math.round(audio.buffered.end(audio.buffered.length - 1) * 1000) : 0,\n volume: audio.volume,\n autoplay: audio.autoplay,\n loop: audio.loop,\n playbackRate: audio.playbackRate\n })),\n\n operateAudio: (args, { api }) => withInstance(args, api, instance => {\n const { audio } = instance;\n switch (args.operationType) {\n case 'play':\n Object.assign(instance, { played: true, stopped: false });\n // 被随后的 pause 打断(AbortError)不算错;音频本身加载失败由 error 事件报告\n audio.play().catch((error: DOMException) => {\n if (error.name === 'NotAllowedError') instance.report('error', { errCode: -1, errMsg: `${error.name}: ${error.message}` });\n });\n break;\n // 浏览器的 pause 事件不转发:它在 stop 之后才异步派发,播到结尾时也会先派发一次\n case 'pause':\n if (!audio.paused) instance.report('pause');\n audio.pause();\n break;\n case 'stop':\n instance.stopped = true;\n audio.pause();\n audio.currentTime = 0;\n instance.report('stop');\n break;\n case 'seek':\n instance.stopped = false;\n audio.currentTime = Number(args.currentTime) / 1000;\n break;\n default:\n throw new Error(`unknown operationType ${args.operationType}`);\n }\n }),\n\n destroyAudioInstance: (args, { api }) => {\n instances.get(args.audioId)?.destroy();\n instances.delete(args.audioId);\n return ok(api);\n }\n };\n}\n","/**\n * 临时文件:canvas 导出、拍照、选图、下载的结果都存在开发服务器上\n *\n * 返回的是 http 地址:image、video 组件只原样使用 http(s) 地址,其余的会被当成页面相对路径;\n * uploadFile 也能直接读取。\n */\n\nconst TEMP_DIR = '/__wxa__/tmp';\n\n/**\n * @param type 扩展名(如 png),读取时按它返回 Content-Type\n * @throws 开发服务器拒绝保存时,带上它给出的原因(如扩展名不合法)\n */\nexport async function saveTempFile(data: BodyInit, type: string): Promise<string> {\n const res = await fetch(`${TEMP_DIR}?type=${encodeURIComponent(type)}`, { method: 'POST', body: data });\n if (!res.ok) throw new Error(await res.text());\n const { url } = await res.json();\n return url;\n}\n\n/**\n * 临时文件的地址换成根路径(/__wxa__/tmp/…),其他地址原样返回。\n * 根路径在页面和组件里都按开发服务器的根目录解析,指向的还是同一个文件\n */\nexport function tempFileRootPath(url: string): string {\n const prefix = `${location.origin}${TEMP_DIR}/`;\n return url.startsWith(prefix) ? url.slice(location.origin.length) : url;\n}\n\n/** 临时文件的扩展名:优先用原文件名的,其次按 MIME 类型(如 image/png),都看不出来时用 fallback */\nexport function tempFileType(name: string, mimeType: string, fallback: string): string {\n const fromName = /\\.([a-z\\d]+)$/i.exec(name)?.[1];\n const fromType = /^[a-z]+\\/([a-z\\d]+)\\s*(;|$)/i.exec(mimeType)?.[1];\n return (fromName || fromType || fallback).toLowerCase();\n}\n\n/** 是不是开发服务器上的临时文件,保存的文件(wx.saveFile)也存在这里 */\nexport function isTempFile(filePath: unknown): filePath is string {\n return typeof filePath === 'string' && filePath.startsWith(`${location.origin}${TEMP_DIR}/`);\n}\n\n/** @returns 文件大小(字节),文件不存在时为 null */\nexport async function tempFileSize(url: string): Promise<number | null> {\n const res = await fetch(url, { method: 'HEAD' });\n return res.ok ? Number(res.headers.get('content-length')) : null;\n}\n\n/** 文件不存在时什么也不做 */\nexport async function removeTempFile(url: string): Promise<void> {\n await fetch(url, { method: 'DELETE' });\n}\n","/**\n * 文件系统 API:内存文件系统,以及读取代码包里的文件\n *\n * 带协议的路径(如 http://usr/)在内存文件系统里;不带协议的是代码包里的文件,由开发服务器提供。\n * 临时文件和保存的文件见 tempFiles.ts、savedFiles.ts。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\nimport { isTempFile, tempFileSize } from './tempFiles';\n\nconst DIR_MODE = 0o40755;\nconst FILE_MODE = 0o100644;\n\ninterface FsNode {\n dir: boolean;\n data: string;\n mtime: number;\n}\n\n/** 基础库会往 http://usr/ 写运行日志;业务代码也可以通过 FileSystemManager 读写 */\nexport class MemoryFileSystem {\n private nodes = new Map<string, FsNode>([['/', { dir: true, data: '', mtime: Date.now() }]]);\n\n normalize(filePath: string): string {\n const stripped = String(filePath || '').replace(/^[a-z]+:\\/\\/[^/]*/i, '');\n const parts: string[] = [];\n for (const part of stripped.split('/')) {\n if (!part || part === '.') continue;\n if (part === '..') parts.pop();\n else parts.push(part);\n }\n return '/' + parts.join('/');\n }\n\n stat(filePath: string): FsNode | undefined {\n return this.nodes.get(this.normalize(filePath));\n }\n\n mkdir(dirPath: string, recursive = false) {\n const target = this.normalize(dirPath);\n if (this.nodes.has(target)) throw new Error(`file already exists ${dirPath}`);\n const parent = target.slice(0, target.lastIndexOf('/')) || '/';\n if (!this.nodes.get(parent)?.dir) {\n if (!recursive) throw new Error(`no such file or directory ${dirPath}`);\n this.mkdir(parent, true);\n }\n this.nodes.set(target, { dir: true, data: '', mtime: Date.now() });\n }\n\n write(filePath: string, data: string, append = false) {\n const target = this.normalize(filePath);\n const parent = target.slice(0, target.lastIndexOf('/')) || '/';\n if (!this.nodes.get(parent)?.dir) throw new Error(`no such file or directory ${filePath}`);\n const existing = this.nodes.get(target);\n if (existing?.dir) throw new Error(`illegal operation on a directory ${filePath}`);\n this.nodes.set(target, { dir: false, data: append && existing ? existing.data + data : data, mtime: Date.now() });\n }\n\n read(filePath: string): string {\n const node = this.stat(filePath);\n if (!node) throw new Error(`no such file or directory, open ${filePath}`);\n if (node.dir) throw new Error(`illegal operation on a directory ${filePath}`);\n return node.data;\n }\n\n readdir(dirPath: string): string[] {\n const target = this.normalize(dirPath);\n if (!this.nodes.get(target)?.dir) throw new Error(`no such file or directory ${dirPath}`);\n const prefix = target === '/' ? '/' : target + '/';\n return [...this.nodes.keys()]\n .filter(key => key.startsWith(prefix) && key !== target && !key.slice(prefix.length).includes('/'))\n .map(key => key.slice(prefix.length));\n }\n\n remove(filePath: string, options: { dir: boolean; recursive?: boolean }) {\n const target = this.normalize(filePath);\n const node = this.nodes.get(target);\n if (!node) throw new Error(`no such file or directory ${filePath}`);\n if (node.dir !== options.dir) throw new Error(options.dir ? `not a directory ${filePath}` : `operation not permitted ${filePath}`);\n if (node.dir) {\n const children = this.readdir(target);\n if (children.length && !options.recursive) throw new Error(`directory not empty ${filePath}`);\n for (const key of [...this.nodes.keys()]) if (key.startsWith(target + '/')) this.nodes.delete(key);\n }\n this.nodes.delete(target);\n }\n}\n\nexport function createFileSystemApis(): Record<string, ApiHandler> {\n const fs = new MemoryFileSystem();\n\n const guard = (api: string, action: () => Record<string, unknown> | void) => {\n try {\n return ok(api, action() || {});\n } catch (error) {\n return fail(api, (error as Error).message);\n }\n };\n\n const statResult = (node: FsNode) => {\n const stats = {\n mode: node.dir ? DIR_MODE : FILE_MODE,\n size: node.data.length,\n lastAccessedTime: Math.floor(node.mtime / 1000),\n lastModifiedTime: Math.floor(node.mtime / 1000)\n };\n return { stats, ...stats };\n };\n\n const readMemoryFile: ApiHandler = (args, { api }) => guard(api, () => ({ data: fs.read(args.filePath) }));\n\n const apis: Record<string, ApiHandler> = {\n access: (args, { api }) => (fs.stat(args.path) ? ok(api) : fail(api, `no such file or directory ${args.path}`)),\n stat: (args, { api }) => {\n const node = fs.stat(args.path);\n return node ? ok(api, statResult(node)) : fail(api, `no such file or directory ${args.path}`);\n },\n mkdir: (args, { api }) => guard(api, () => fs.mkdir(args.dirPath, !!args.recursive)),\n writeFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ''))),\n appendFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ''), true)),\n readdir: (args, { api }) => guard(api, () => ({ files: fs.readdir(args.dirPath) })),\n unlink: (args, { api }) => guard(api, () => fs.remove(args.filePath, { dir: false })),\n rmdir: (args, { api }) => guard(api, () => fs.remove(args.dirPath, { dir: true, recursive: !!args.recursive })),\n getFileInfo: (args, { api }) => {\n if (isTempFile(args.filePath)) {\n return tempFileSize(args.filePath).then(size => (size === null ? fail(api, 'file not exist') : ok(api, { size })));\n }\n const node = fs.stat(args.filePath);\n return node ? ok(api, { size: node.data.length }) : fail(api, 'file not exist');\n }\n };\n for (const name of Object.keys(apis)) apis[name + 'Sync'] = apis[name];\n\n return {\n ...apis,\n fs_appendFile: apis.appendFile,\n // 不带协议的是代码包里的文件,要向开发服务器取;readFileSync 同步返回不了,只读内存文件系统。\n // 内存文件系统的路径去掉了协议,不能先在里面找:用户目录下的同名文件会顶替代码包里的\n readFile: (args, context) => (/^[a-z]+:\\/\\//i.test(String(args.filePath))\n ? readMemoryFile(args, context)\n : readPackageFile(fs.normalize(args.filePath), args.encoding).then(\n data => ok(context.api, { data }),\n error => fail(context.api, error.message)\n )),\n readFileSync: readMemoryFile\n };\n}\n\n/**\n * 开发服务器以项目目录为根目录提供代码包里的文件\n * @param filePath 以 / 开头、相对代码包根目录的路径\n * @param encoding 不指定时得到 ArrayBuffer\n * @throws 文件不存在,或 encoding 不是 utf8\n */\nasync function readPackageFile(filePath: string, encoding: unknown): Promise<string | ArrayBuffer> {\n if (encoding !== undefined && encoding !== 'utf8' && encoding !== 'utf-8') {\n throw new Error(`读取代码包里的文件只支持 utf8 编码,或不指定编码得到 ArrayBuffer,不支持 ${encoding}`);\n }\n // encodeURI 不编码 # 和 ?,文件名里有的话会被当成地址的片段和查询\n const response = await fetch(filePath.split('/').map(encodeURIComponent).join('/'));\n if (!response.ok) throw new Error(`no such file or directory, open ${filePath}`);\n return encoding ? response.text() : response.arrayBuffer();\n}\n","/**\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 * 渲染层按需加载基础库文件:3.3.x、3.5.x 的 video 等组件不在 WAWebview.js 里,用到时才经 loadLibFilesSync 加载\n *\n * 脚本在调用返回前执行完:基础库在调用前后设置、清理 window.__Behaviour 等全局变量。\n * 各文件的内容按顺序放在 __codes 里交回,基础库从这里取 CSS 自己插入页面,所以 CSS 不当脚本执行。\n */\n\nimport { readSync, runScript } from '../../syncScript';\nimport { ApiHandler, ok } from './registry';\n\nexport interface LibFileApiOptions {\n windowOf: (webviewId: number) => Window | null | undefined;\n}\n\nexport function createLibFileApis(options: LibFileApiOptions): Record<string, ApiHandler> {\n const loadLibFiles: ApiHandler = (args, { api, from, webviewId }) => {\n const win = from === 'webview' ? options.windowOf(webviewId) : null;\n // 逻辑层也会调(加载广告、云开发等伴生 SDK),由 sdkStubs 在 wx 这一层接住,这里照旧返回成功\n if (!win) return ok(api);\n const codes = (args.paths as string[]).map(file => {\n const url = `/__baselib__/${file}`;\n const code = readSync(url);\n if (file.endsWith('.js')) runScript(win, url, code);\n return code;\n });\n return ok(api, { __codes: codes });\n };\n\n return { loadLibFiles, loadLibFilesSync: loadLibFiles };\n}\n","/**\n * map 组件用到的原生接口\n *\n * 平台是 devtools 时,基础库用腾讯地图网页 SDK 实现 map 组件,MapContext 的方法大多经 operateMap 消息发给它。\n * 有两处要原生接口配合:\n * - 要用户的当前位置时(moveToLocation、show-location),map 组件在渲染层调 private_geolocation,把结果当作\n * 腾讯位置服务定位接口返回的 JSON 文本解析,没有位置就按定位失败处理,带着经纬度的 moveToLocation 也会因此失败\n * - 3.10.1 起,带经纬度的 moveToLocation 不再经 operateMap 发给 map 组件,改调原生的 moveToMapLocation\n */\n\nimport type { ApiHandler, ApiRegistry, ApiResult } from './registry';\n\nexport interface MapApiOptions {\n /** 当前位置取这里 getLocation 的结果:和真机一样,地图上的当前位置就是 getLocation 的位置,mock 了也跟着变 */\n registry: ApiRegistry;\n operations: MapOperations;\n}\n\nexport function createMapApis({ registry, operations }: MapApiOptions): Record<string, ApiHandler> {\n return {\n private_geolocation: async (_args, context) => {\n const location = await registry.invoke('getLocation', { type: 'gcj02' }, { ...context, api: 'getLocation' }) as ApiResult;\n if (location.errMsg !== 'getLocation:ok') return JSON.stringify({ message: location.errMsg });\n return JSON.stringify({ result: { location: { lat: location.latitude, lng: location.longitude } } });\n },\n // 开发者工具上没有原生地图,照基础库的格式转给当前页的 map 组件\n moveToMapLocation: (args, { webviewId }) => operations.send(webviewId, { ...args, method: 'moveToMapLocation' })\n };\n}\n\n/**\n * 宿主替基础库发给 map 组件的操作:按 callbackId 收下 map 组件发回的 operateMapCallback。\n * 消息格式同基础库,包一层 { data, options }\n */\nexport class MapOperations {\n private readonly pending = new Map<string, (result: ApiResult) => void>();\n private seq = 0;\n\n /** @param publish 发给渲染层,渲染层的 WeixinJSBridge.subscribe 收到 */\n constructor(private readonly publish: (webviewId: number, event: string, data: unknown) => void) {}\n\n /** map 组件做完才返回;页面上没有这个 map 时一直不返回,同基础库自己发的操作 */\n send(webviewId: number, operation: Record<string, unknown>): Promise<ApiResult> {\n const callbackId = `wxa_${++this.seq}`;\n return new Promise(resolve => {\n this.pending.set(callbackId, resolve);\n this.publish(webviewId, 'operateMap', { data: { ...operation, callbackId }, options: { timestamp: Date.now() } });\n });\n }\n\n /** map 组件发回的 operateMapCallback:是宿主发的操作时收下并返回 true,不再交给逻辑层 */\n receive(message: any): boolean {\n const reply = message?.data;\n const resolve = this.pending.get(reply?.callbackId);\n if (!resolve) return false;\n this.pending.delete(reply.callbackId);\n resolve({ errMsg: reply.errMsg });\n return true;\n }\n}\n","/**\n * 媒体 API:选图(chooseImage / chooseMedia)、预览、读取图片信息、保存到相册\n *\n * 浏览器拿不到相册和相机,「从手机相册选择」和「拍摄」都打开文件选择框(手机浏览器上拍摄会打开相机)。\n * 选中的文件存成临时文件,路径可以直接作为 image 的 src,也可以直接 uploadFile。\n */\n\nimport type { FileChooserOptions } from '../ui/fileChooser';\nimport type { ActionSheetOptions } from '../ui/PhoneShell';\nimport { ApiHandler, fail, ok } from './registry';\nimport { saveTempFile, tempFileType } from './tempFiles';\n\nexport interface MediaApiOptions {\n /** @returns 用户点的下标,取消时为 null */\n showActionSheet: (options: ActionSheetOptions) => Promise<number | null>;\n /** @returns 用户关掉文件选择框时为 null */\n chooseFiles: (options: FileChooserOptions) => Promise<File[] | null>;\n /** 用户刚点击过、浏览器允许打开文件选择框 */\n hasUserActivation: () => boolean;\n showImagePreview: (urls: string[], current: number) => void;\n}\n\ntype Source = 'camera' | 'album';\n\n/** 菜单里的顺序和真机一致 */\nconst SOURCES: Source[] = ['camera', 'album'];\nconst SOURCE_LABELS: Record<Source, string> = { camera: '拍摄', album: '从手机相册选择' };\nconst DEFAULT_COUNT = 9;\n\nexport function createMediaApis(\n { showActionSheet, chooseFiles, hasUserActivation, showImagePreview }: MediaApiOptions\n): Record<string, ApiHandler> {\n /**\n * 和真机一样,相册和拍摄都可选时先弹菜单。浏览器只允许在用户点击后的几秒内打开文件选择框,\n * 没有经过点击、或者离点击已经太久时也先弹菜单,用户点菜单就是一次点击\n * @returns 用户取消时为 null;选的比 count 多时只取前 count 个\n */\n async function chooseImages(args: { count?: number; sourceType?: string[] }): Promise<File[] | null> {\n const allowed = SOURCES.filter(source => args.sourceType?.includes(source));\n const sources = allowed.length ? allowed : SOURCES;\n let source = sources[0];\n if (sources.length > 1 || !hasUserActivation()) {\n const index = await showActionSheet({ itemList: sources.map(item => SOURCE_LABELS[item]) });\n if (index === null) return null;\n source = sources[index];\n }\n\n const count = Math.max(1, Number(args.count) || DEFAULT_COUNT);\n const files = await chooseFiles({ accept: 'image/*', multiple: count > 1, capture: source === 'camera' });\n return files && files.slice(0, count);\n }\n\n const saveAll = (files: File[]) => Promise.all(files.map(file => saveTempFile(file, tempFileType(file.name, file.type, 'jpg'))));\n\n return {\n chooseImage: async (args, { api }) => {\n const files = await chooseImages(args);\n if (!files) return fail(api, 'cancel');\n const paths = await saveAll(files);\n return ok(api, { tempFilePaths: paths, tempFiles: files.map((file, i) => ({ path: paths[i], size: file.size })) });\n },\n\n chooseMedia: async (args, { api }) => {\n const mediaType: string[] = args.mediaType?.length ? args.mediaType : ['image', 'video'];\n if (!mediaType.includes('image') && !mediaType.includes('mix')) return fail(api, 'wxa-runner 暂不支持选择视频');\n const files = await chooseImages(args);\n if (!files) return fail(api, 'cancel');\n const paths = await saveAll(files);\n return ok(api, {\n type: 'image',\n tempFiles: files.map((file, i) => ({ tempFilePath: paths[i], size: file.size, fileType: 'image' }))\n });\n },\n\n // 基础库已经把 current 换成了 urls 里的地址;也兼容直接传下标\n previewImage: args => {\n const urls: string[] = (args.urls || []).map(String);\n if (!urls.length) return;\n const current = typeof args.current === 'number' ? args.current : urls.indexOf(args.current);\n showImagePreview(urls, Math.max(current, 0));\n },\n\n // 网络图片基础库已先下载成本地地址,包内图片已换成相对小程序根目录的路径\n getImageInfo: async args => {\n const src = String(args.src || '');\n const blob = await fetchFile(src);\n const bitmap = await createImageBitmap(blob);\n const info = { width: bitmap.width, height: bitmap.height, type: imageType(blob), orientation: 'up' };\n bitmap.close();\n return info;\n },\n\n // 浏览器没有相册,保存到相册就是下载这张图片\n saveImageToPhotosAlbum: async args => {\n const filePath = String(args.filePath || '');\n const link = document.createElement('a');\n link.href = URL.createObjectURL(await fetchFile(filePath));\n link.download = filePath.split(/[?#]/)[0].split('/').pop() || 'image';\n link.click();\n // 立即释放会让还没开始的下载失败\n setTimeout(() => URL.revokeObjectURL(link.href), 60_000);\n }\n };\n}\n\n/** @throws 文件不存在时 */\nasync function fetchFile(path: string): Promise<Blob> {\n const url = /^[a-z][a-z\\d+.-]*:/i.test(path) ? path : '/' + path.replace(/^\\//, '');\n const res = await fetch(url);\n if (!res.ok) throw new Error(`file not exist ${path}`);\n return res.blob();\n}\n\n/** 与真机一致的格式名:png、jpeg、gif 等,看不出来时为 unknown */\nfunction imageType(blob: Blob): string {\n return /^image\\/([a-z\\d]+)/i.exec(blob.type)?.[1].toLowerCase() || 'unknown';\n}\n","/**\n * 其余 API:开放接口 Mock、剪贴板等\n *\n * 开放接口(登录、用户信息、支付)在浏览器里无法真实调用,返回可预测的假数据,\n * 测试中可以用 __wxa_test_api__.mock() 覆盖。开启 --real-login 时,登录和手机号经开发服务器向微信换取真实结果。\n */\n\nimport { ApiHandler, ApiResult, fail, ok } from './registry';\nimport { saveTempFile } from './tempFiles';\n\nexport interface MiscApiOptions {\n realLogin?: boolean;\n /** 真实登录失败时触发,用来在页面上提示开发者;业务代码照常收到 fail */\n onRealLoginFail?: (api: string, reason: string) => void;\n}\n\nexport function createMiscApis(appid: string, options?: MiscApiOptions): Record<string, ApiHandler> {\n const realLogin = async (api: string, url: string) => {\n try {\n return await postDevServer(url);\n } catch (error) {\n options?.onRealLoginFail?.(api, (error as Error).message);\n throw error;\n }\n };\n\n return {\n // canvas 导出图片、拍照、录像的结果都经过这里\n base64ToTempFilePath: async args => {\n const bytes = Uint8Array.from(atob(String(args.base64Data || '')), char => char.charCodeAt(0));\n return { tempFilePath: await saveTempFile(bytes, String(args.fileType || 'png')) };\n },\n\n // 基础库经这两个接口向后台拉各种配置和小程序信息\n operateWXData: (args, { api }) => {\n if (args.data?.api_name === 'webapi_getwxanetwork') return bizDomainUnavailable(api);\n if (args.data?.api_name === 'webapi_getwxauserprivacyauthinfo') return ok(api, { data: { data: JSON.stringify(PRIVACY_AUTH_INFO) } });\n return ok(api);\n },\n getAppContact: (args, { api }) =>\n args.keyPath === 'WxaAppInfo.Network.BizDomain' ? bizDomainUnavailable(api) : ok(api),\n\n // 真实登录失败时明确返回 fail,不退回假数据:配置或登录态的问题要让开发者马上发现\n login: options?.realLogin\n ? async (_args, { api }) => ok(api, { code: (await realLogin(api, '/__wxa__/api/login')).code })\n : (_args, { api }) => ok(api, { code: `wxa_mock_code_${Date.now().toString(36)}` }),\n // 基础库只从 JSON.parse(data) 里取手机号的 code\n getPhoneNumber: options?.realLogin\n ? async (_args, { api }) => ok(api, await realLogin(api, '/__wxa__/api/phone-number'))\n : (_args, { api }) => ok(api, { data: JSON.stringify({ code: `mock_phone_code_${Date.now()}` }), encryptedData: 'mock_encrypted', iv: 'mock_iv' }),\n checkSession: () => undefined,\n authorize: () => undefined,\n getSetting: (_args, { api }) => ok(api, {\n authSetting: { 'scope.userInfo': true, 'scope.userLocation': true }\n }),\n openSetting: (_args, { api }) => ok(api, { authSetting: {} }),\n getUserInfo: (_args, { api }) => ok(api, { userInfo: mockUser(), rawData: JSON.stringify(mockUser()), signature: '', encryptedData: '', iv: '' }),\n getUserProfile: (_args, { api }) => ok(api, { userInfo: mockUser(), rawData: JSON.stringify(mockUser()), signature: '', encryptedData: '', iv: '' }),\n getAccountInfoSync: (_args, { api }) => ok(api, { miniProgram: { appId: appid, envVersion: 'develop', version: '' } }),\n requestPayment: (_args, { api }) => fail(api, '浏览器运行时不支持支付,请在测试中通过 __wxa_test_api__.mock(\"requestPayment\", ...) 模拟'),\n getLocation: (_args, { api }) => ok(api, { latitude: 39.908823, longitude: 116.39747, speed: 0, accuracy: 65, altitude: 0, verticalAccuracy: 65, horizontalAccuracy: 65 }),\n scanCode: (_args, { api }) => fail(api, 'cancel'),\n\n setClipboardData: async (args) => {\n clipboard = String(args.data ?? '');\n await navigator.clipboard?.writeText(clipboard).catch(() => undefined);\n },\n getClipboardData: (_args, { api }) => ok(api, { data: clipboard }),\n makePhoneCall: (args) => console.info(`[wxa-runner] makePhoneCall ${args.phoneNumber}`),\n showShareMenu: () => undefined,\n hideShareMenu: () => undefined,\n updateShareMenu: () => undefined\n };\n}\n\nlet clipboard = '';\n\n/** @throws 开发服务器返回的失败原因(由注册表转成 xxx:fail),返回的不是 JSON 时带上状态码 */\nasync function postDevServer(url: string): Promise<Record<string, any>> {\n const response = await fetch(url, { method: 'POST' });\n const body = await response.json().catch(() => null);\n if (!response.ok || !body) throw new Error(body?.error || `开发服务器返回 HTTP ${response.status}`);\n return body;\n}\n\nfunction mockUser() {\n return { nickName: 'wxa-runner', avatarUrl: '', gender: 0, country: '', province: '', city: '', language: 'zh_CN' };\n}\n\n/**\n * 隐私授权信息:不用弹窗、没有未授权的接口,等于用户已经同意了隐私协议。基础库调用剪贴板、定位、选图等涉及隐私的接口前\n * 先拉取它,从结果的 data 里解析;2.32.3 拿不到时在回调里抛错,这些接口一直不回调。wording 是弹窗的文案,不弹窗也要有\n */\nconst PRIVACY_AUTH_INFO = { action_code: 0, need_popup_scope_list: [], unauth_scope_list: [], wording: {} };\n\n/**\n * 不校验业务域名,等同开发者工具的「不校验合法域名、web-view(业务域名)」:拿到空的业务域名列表时,\n * 基础库会把 web-view 事件里的网页地址清空,只有拉取失败才不校验。不同版本从不同的原生接口拉取\n * (如 3.13.2 用 getAppContact,3.17.3 用 operateWXData),两个都要失败\n */\nfunction bizDomainUnavailable(api: string): ApiResult {\n return fail(api, 'not available in wxa-runner');\n}\n","/**\n * 网络 API:wx.request / downloadFile / uploadFile / connectSocket\n *\n * 基础库 3.x 的协议是「创建任务同步返回 taskId,结果通过 on<Type>TaskStateChange 事件推送」。\n * HTTP 请求经开发服务器的 /__wxa__/proxy 转发:既绕开 CORS,也能携带浏览器禁止设置的\n * cookie / referer 等请求头。\n *\n * 基础库自己的请求(数据上报、配置拉取等)不发出,只放行 InnerAudioContext 下载音频,见 byCaller。\n */\n\nimport type { MockRequest } from '../../../setup';\nimport { ApiHandler, fail, ok } from './registry';\nimport type { RequestRoutes } from './routes';\nimport { saveTempFile, tempFileType } from './tempFiles';\n\nexport interface NetworkApiOptions {\n /** 向逻辑层派发事件 */\n emit: (event: string, data: Record<string, unknown>) => void;\n defaultTimeout: () => number;\n /** 请求拦截,只作用于 wx.request */\n routes?: RequestRoutes;\n /** wx.request 发出时调用,早于拦截和转发 */\n onRequest?: (request: RecordedRequest) => void;\n}\n\n/** 小程序发出的一个 wx.request */\nexport interface RecordedRequest extends MockRequest {\n /** 拦截它的规则(setup 的 network.routes 或测试 API 的 route),经代理发往网络时为 null */\n routedBy: string | null;\n}\n\n/** 最近发出的 wx.request。平时调试不跑测试时也在记录,只保留最近的 limit 个,内存不会一直增长 */\nexport class RequestLog {\n private items: RecordedRequest[] = [];\n\n constructor(private readonly limit = 1000) {}\n\n add(request: RecordedRequest) {\n this.items.push(request);\n if (this.items.length > this.limit) this.items.splice(0, this.items.length - this.limit);\n }\n\n /** 按发出顺序;返回副本,修改它不影响记录 */\n list(): RecordedRequest[] {\n return this.items.map(request => ({ ...request, header: { ...request.header } }));\n }\n\n clear() {\n this.items = [];\n }\n}\n\ninterface ProxyResponse {\n statusCode: number;\n header: Record<string, string>;\n cookies: string[];\n response: Response;\n}\n\nlet taskSeq = 0;\n\nexport function createNetworkApis(options: NetworkApiOptions): Record<string, ApiHandler> {\n const controllers = new Map<string, AbortController>();\n const sockets = new Map<string, WebSocket>();\n const { emit } = options;\n\n const startTask = (args: any, run: (signal: AbortSignal, id: string) => Promise<void>): string => {\n const id = String(++taskSeq);\n const controller = new AbortController();\n const timeout = args.timeout || options.defaultTimeout();\n const timer = timeout > 0 ? setTimeout(() => controller.abort(new Error('timeout')), timeout) : null;\n controllers.set(id, controller);\n // 任务 id 先同步返回给基础库,结果事件之后再推送\n setTimeout(() => {\n run(controller.signal, id).finally(() => {\n if (timer) clearTimeout(timer);\n controllers.delete(id);\n });\n }, 0);\n return id;\n };\n\n const abortTask = (args: any, key: string) => {\n if (args.operationType === 'abort') controllers.get(String(args[key]))?.abort(new Error('abort'));\n };\n\n const createRequestTask: ApiHandler = (args, { api }) => {\n const request: MockRequest = { url: args.url, method: (args.method || 'GET').toUpperCase(), header: { ...args.header }, data: args.data };\n // 发出时就确定是否拦截:记录里能看到命中的规则,之后增删规则不影响已发出的请求\n const route = options.routes?.match(request);\n options.onRequest?.({ ...request, header: { ...request.header }, routedBy: route ? route.pattern : null });\n\n const requestTaskId = startTask(args, async (signal, id) => {\n try {\n const mocked = route && await route.respond(signal);\n const res: ProxyResponse = mocked\n ? { statusCode: mocked.statusCode, header: mocked.header, cookies: [], response: new Response(mocked.body) }\n : await proxyFetch(request.url, { method: request.method, header: args.header, body: args.data, signal });\n emit('onRequestTaskStateChange', {\n requestTaskId: id, state: 'headersReceived', header: res.header, statusCode: res.statusCode, cookies: res.cookies\n });\n // 和真机一样由 responseType 决定拿到文本还是 ArrayBuffer,与响应内容无关,拦截规则给的响应也是\n const data = args.responseType === 'arraybuffer' ? await res.response.arrayBuffer() : await res.response.text();\n emit('onRequestTaskStateChange', {\n requestTaskId: id, state: 'success', data, statusCode: res.statusCode, header: res.header, cookies: res.cookies, profile: {}\n });\n } catch (error) {\n emit('onRequestTaskStateChange', { requestTaskId: id, state: 'fail', errMsg: `request:fail ${reason(error)}` });\n }\n });\n return ok(api, { requestTaskId });\n };\n\n const createDownloadTask: ApiHandler = (args, { api }) => {\n const downloadTaskId = startTask(args, async (signal, id) => {\n try {\n const res = await proxyFetch(args.url, { method: 'GET', header: args.header, signal });\n emit('onDownloadTaskStateChange', { downloadTaskId: id, state: 'headersReceived', header: res.header, cookies: res.cookies });\n const blob = await res.response.blob();\n emit('onDownloadTaskStateChange', {\n downloadTaskId: id, state: 'progressUpdate', progress: 100, totalBytesWritten: blob.size, totalBytesExpectedToWrite: blob.size\n });\n // 不用 blob: 地址:image 组件会把它当成页面相对路径\n const fileName = new URL(args.url).pathname.split('/').pop() || '';\n const tempFilePath = await saveTempFile(blob, tempFileType(fileName, blob.type, 'tmp'));\n emit('onDownloadTaskStateChange', {\n downloadTaskId: id,\n state: 'success',\n tempFilePath,\n statusCode: res.statusCode,\n header: res.header,\n profile: {}\n });\n } catch (error) {\n emit('onDownloadTaskStateChange', { downloadTaskId: id, state: 'fail', errMsg: `downloadFile:fail ${reason(error)}` });\n }\n });\n return ok(api, { downloadTaskId });\n };\n\n const createUploadTask: ApiHandler = (args, { api }) => {\n const uploadTaskId = startTask(args, async (signal, id) => {\n try {\n const file = await (await fetch(args.filePath)).blob();\n const form = new FormData();\n for (const [key, value] of Object.entries(args.formData || {})) form.append(key, String(value));\n form.append(args.name || 'file', file, String(args.filePath).split('/').pop() || 'file');\n\n const res = await proxyFetch(args.url, { method: 'POST', header: args.header, body: form, signal });\n const data = await res.response.text();\n emit('onUploadTaskStateChange', {\n uploadTaskId: id, state: 'progressUpdate', progress: 100, totalBytesSent: file.size, totalBytesExpectedToSend: file.size\n });\n emit('onUploadTaskStateChange', { uploadTaskId: id, state: 'success', data, statusCode: res.statusCode, header: res.header });\n } catch (error) {\n emit('onUploadTaskStateChange', { uploadTaskId: id, state: 'fail', errMsg: `uploadFile:fail ${reason(error)}` });\n }\n });\n return ok(api, { uploadTaskId });\n };\n\n const createSocketTask: ApiHandler = (args, { api }) => {\n const socketTaskId = String(++taskSeq);\n let socket: WebSocket;\n try {\n socket = new WebSocket(args.url, args.protocols && args.protocols.length ? args.protocols : undefined);\n } catch (error) {\n return fail(api, reason(error));\n }\n socket.binaryType = 'arraybuffer';\n sockets.set(socketTaskId, socket);\n socket.onopen = () => emit('onSocketTaskStateChange', { socketTaskId, state: 'open', header: {}, profile: {} });\n socket.onmessage = event => emit('onSocketTaskStateChange', { socketTaskId, state: 'message', data: event.data });\n socket.onerror = () => emit('onSocketTaskStateChange', { socketTaskId, state: 'error', errMsg: 'connectSocket:fail' });\n socket.onclose = event => {\n sockets.delete(socketTaskId);\n emit('onSocketTaskStateChange', { socketTaskId, state: 'close', code: event.code, reason: event.reason });\n };\n return ok(api, { socketTaskId });\n };\n\n const operateSocketTask: ApiHandler = (args, { api }) => {\n const socket = sockets.get(String(args.socketTaskId));\n if (!socket) return fail(api, 'socket task not found');\n if (args.operationType === 'send') {\n if (socket.readyState !== WebSocket.OPEN) return fail(api, 'socket is not open');\n socket.send(args.data);\n } else if (args.operationType === 'close') {\n socket.close(args.code || 1000, args.reason);\n }\n return ok(api);\n };\n\n /** 不是小程序的 wx.request:不记录,也不经拦截规则 */\n const downloadAudio: ApiHandler = (args, { api }) => {\n const requestTaskId = startTask(args, async (signal, id) => {\n try {\n const res = await proxyFetch(args.url, { method: 'GET', header: args.header, signal });\n const meta = { requestTaskId: id, statusCode: res.statusCode, header: res.header, cookies: res.cookies };\n emit('onRequestTaskStateChange', { ...meta, state: 'headersReceived' });\n emit('onRequestTaskStateChange', { ...meta, state: 'success', data: await res.response.arrayBuffer(), profile: {} });\n } catch (error) {\n emit('onRequestTaskStateChange', { requestTaskId: id, state: 'fail', errMsg: `request:fail ${reason(error)}` });\n }\n });\n return ok(api, { requestTaskId });\n };\n\n // 基础库自己的请求只放行下载音频\n const requestTask = byCaller(createRequestTask, (args, context) => (isAudioDownload(args)\n ? downloadAudio(args, context)\n : rejectBaseLib(args, context)));\n const downloadTask = byCaller(createDownloadTask);\n const uploadTask = byCaller(createUploadTask);\n\n return {\n createRequestTask: requestTask,\n createRequestTaskAsync: requestTask,\n createDownloadTask: downloadTask,\n createDownloadTaskAsync: downloadTask,\n createUploadTask: uploadTask,\n createUploadTaskAsync: uploadTask,\n createSocketTask: byCaller(createSocketTask),\n operateRequestTask: args => abortTask(args, 'requestTaskId'),\n operateDownloadTask: args => abortTask(args, 'downloadTaskId'),\n operateUploadTask: args => abortTask(args, 'uploadTaskId'),\n operateSocketTask\n };\n}\n\nconst rejectBaseLib: ApiHandler = (_args, { api }) => fail(api, '基础库内部的网络请求,wxa-runner 不发出');\n\n/**\n * 小程序的请求交给 forApp;基础库自己的网络请求(数据上报、配置拉取等)默认直接按失败返回:不发往网络,也不记入请求记录\n *\n * 它们连的是微信后台,与被测的小程序无关,测试和 CI 里不该因此产生对外请求。基础库通过\n * _requestSkipCheckDomain 一类内部接口发出,带 __skipDomainCheck__ 标记;小程序的 wx.request 不带\n */\nfunction byCaller(forApp: ApiHandler, forBaseLib = rejectBaseLib): ApiHandler {\n return (args, context) => (args?.__skipDomainCheck__ === true ? forBaseLib(args, context) : forApp(args, context));\n}\n\n/**\n * 基础库为 InnerAudioContext 下载音频的请求:用 Web Audio 播放时先把音频地址下载成 ArrayBuffer\n * (3.5.8 起平台是 devtools 时默认用 Web Audio,更早的版本要业务指定 useWebAudioImplement,否则调原生接口,见 audio.ts)。\n * 2.32.3 到 3.17.4 都是这个形状,基础库自己的其他请求不会同时带这两个参数\n */\nfunction isAudioDownload(args: any): boolean {\n return args.responseType === 'arraybuffer' && args.enableCache === true;\n}\n\nexport async function proxyFetch(\n url: string,\n init: { method: string; header?: Record<string, string>; body?: unknown; signal?: AbortSignal }\n): Promise<ProxyResponse> {\n if (!/^https?:\\/\\//i.test(url)) throw new Error(`invalid url \"${url}\"`);\n\n const hasBody = init.body !== undefined && init.body !== '' && !['GET', 'HEAD'].includes(init.method);\n const response = await fetch(`/__wxa__/proxy?url=${encodeURIComponent(url)}`, {\n method: init.method,\n headers: { 'x-wxa-headers': JSON.stringify(init.header || {}) },\n body: hasBody ? init.body as BodyInit : undefined,\n signal: init.signal\n });\n\n if (response.headers.get('x-wxa-proxy-error')) {\n throw new Error(await response.text());\n }\n\n return {\n statusCode: response.status,\n header: JSON.parse(decodeURIComponent(response.headers.get('x-wxa-headers') || '%7B%7D')),\n cookies: JSON.parse(decodeURIComponent(response.headers.get('x-wxa-set-cookie') || '%5B%5D')),\n response\n };\n}\n\nfunction reason(error: unknown): string {\n if (error instanceof DOMException && error.name === 'AbortError') return 'abort';\n return error instanceof Error ? error.message : String(error);\n}\n","/**\n * picker 组件背后的原生选择器\n *\n * 基础库把每列的选项文字交给宿主,宿主弹出选择器,再按基础库约定的格式返回用户的选择:\n * selector showPickerView → { index }\n * multiSelector showMultiPickerView → { current },选择期间用户换列时派发 onMultiPickerViewChange,\n * 页面改了 range 后基础库调 updateMultiPickerView 换掉那一列\n * date / time showDatePickerView → { value: 'YYYY-MM-DD' / 'HH:mm' }\n * region getRegionData 拿省市区数据后自己解析,再走 showMultiPickerView;\n * 指定了 level 时走 showAddressPickerView → { value: { value, code, postcode } }\n *\n * 日期、地区这类列之间有联动的,联动规则在这里实现,选择器界面只负责显示列。\n */\n\nimport type { PickerOptions, PickerSession } from '../ui/Picker';\nimport { ApiHandler, fail, ok } from './registry';\n\nexport type RegionDataKind = 'districts' | 'streets';\n\nexport interface PickerApiOptions {\n showPicker(options: PickerOptions): PickerSession;\n /** 派发给渲染层的原生事件(渲染层里 WeixinJSBridge.on 收到) */\n emitToWebview(webviewId: number, event: string, data: unknown): void;\n /** 开发者工具自带的行政区划数据,districts 到区县,streets 到街道 */\n loadRegionData(kind: RegionDataKind): Promise<string>;\n}\n\nexport async function fetchRegionData(kind: RegionDataKind): Promise<string> {\n const res = await fetch(`/__wxa__/region/${kind}`);\n if (!res.ok) throw new Error('没有找到行政区划数据,地区选择器需要本机微信开发者工具自带的数据');\n return res.text();\n}\n\nexport function createPickerApis({ showPicker, emitToWebview, loadRegionData }: PickerApiOptions): Record<string, ApiHandler> {\n let multiPicker: PickerSession | null = null;\n let regionTree: Promise<RegionNode[]> | null = null;\n\n const loadRegionTree = () => {\n regionTree ??= loadRegionData('streets').then(parseRegionTree);\n // 失败了下次重新加载\n regionTree.catch(() => {\n regionTree = null;\n });\n return regionTree;\n };\n\n /** 弹出列之间有联动的选择器:用户改了某列后,后面各列按 model 重新生成 */\n const showCascade = (model: CascadeModel, headerText?: string) => {\n const session: PickerSession = showPicker({\n columns: model.columns(),\n current: model.current(),\n headerText,\n onColumnChange(column, index) {\n model.select(column, index);\n const columns = model.columns();\n const current = model.current();\n for (let next = column + 1; next < columns.length; next++) session.setColumn(next, columns[next], current[next]);\n }\n });\n return session.result;\n };\n\n return {\n showPickerView: async (args, { api }) => {\n const result = await showPicker({\n columns: [labels(args.array)],\n current: [Number(args.current) || 0],\n headerText: args.headerText\n }).result;\n return result ? ok(api, { index: result[0] }) : fail(api, 'cancel');\n },\n\n showMultiPickerView: async (args, { api, webviewId }) => {\n const session = showPicker({\n columns: (args.array || []).map(labels),\n current: (args.current || []).map((index: unknown) => Number(index) || 0),\n headerText: args.headerText,\n onColumnChange: (column, current) => emitToWebview(webviewId, 'onMultiPickerViewChange', { column, current })\n });\n multiPicker = session;\n const result = await session.result;\n if (multiPicker === session) multiPicker = null;\n return result ? ok(api, { current: result }) : fail(api, 'cancel');\n },\n\n updateMultiPickerView: (args, { api }) => {\n if (!multiPicker) return fail(api, 'no picker is showing');\n multiPicker.setColumn(Number(args.column), labels(args.array), Number(args.current) || 0);\n return ok(api);\n },\n\n showDatePickerView: async (args, { api }) => {\n const model = new DateCascade(args.mode === 'time' ? 'time' : 'date', args.fields, args.range || {}, String(args.current || ''));\n const result = await showCascade(model, args.headerText);\n return result ? ok(api, { value: model.value() }) : fail(api, 'cancel');\n },\n\n showAddressPickerView: async (args, { api }) => {\n let tree: RegionNode[];\n try {\n tree = await loadRegionTree();\n } catch (error) {\n return fail(api, (error as Error).message);\n }\n const model = new RegionCascade(tree, REGION_LEVELS[args.mode] || 3, args.current || []);\n const result = await showCascade(model);\n return result ? ok(api, { value: model.value() }) : fail(api, 'cancel');\n },\n\n getRegionData: async (_args, { api }) => {\n try {\n return ok(api, { data: await loadRegionData('districts') });\n } catch (error) {\n return fail(api, (error as Error).message);\n }\n }\n };\n}\n\nfunction labels(items: unknown): string[] {\n return Array.isArray(items) ? items.map(item => String(item)) : [];\n}\n\ninterface CascadeModel {\n columns(): string[][];\n current(): number[];\n select(column: number, index: number): void;\n}\n\n// -----------------------------------------------------------------------------\n// 日期与时间\n// -----------------------------------------------------------------------------\n\nconst DEFAULT_DATE_RANGE = { start: [1900, 1, 1], end: [2100, 12, 31] };\nconst DATE_DEPTH: Record<string, number> = { year: 1, month: 2, day: 3 };\n\n/**\n * 每列是一段连续的数字(年、月、日或时、分)。某列的取值范围取决于前面各列:\n * 前面各列都落在 start 上时,这一列不能早于 start;end 同理;日的上限还取决于年月。\n * 改了某列后,后面各列保持原值,超出新范围时落到最近的边界(1 月 31 日切到 2 月变成 29 日)。\n */\nclass DateCascade implements CascadeModel {\n private readonly depth: number;\n private readonly min: number[];\n private readonly max: number[];\n private readonly parts: number[] = [];\n\n constructor(private readonly mode: 'date' | 'time', fields: unknown, range: { start?: string; end?: string }, current: string) {\n this.depth = mode === 'time' ? 2 : DATE_DEPTH[String(fields)] || 3;\n const lowest = mode === 'time' ? [0, 0] : DEFAULT_DATE_RANGE.start;\n const highest = mode === 'time' ? [23, 59] : DEFAULT_DATE_RANGE.end;\n this.min = fillParts(parseParts(range.start), lowest);\n this.max = fillParts(parseParts(range.end), highest);\n // 早于 start 或晚于 end 时整体落到那个边界,而不是逐列裁剪(2019-06-01 → 2020-03-15,而非 2020-06-01)\n let initial = fillParts(parseParts(current), lowest);\n if (compareParts(initial, this.min, this.depth) < 0) initial = this.min;\n else if (compareParts(initial, this.max, this.depth) > 0) initial = this.max;\n for (let column = 0; column < this.depth; column++) {\n const [low, high] = this.bounds(column);\n this.parts[column] = clamp(initial[column], low, high);\n }\n }\n\n columns(): string[][] {\n return this.parts.map((_, column) => {\n const [low, high] = this.bounds(column);\n return Array.from({ length: high - low + 1 }, (__, offset) => this.label(column, low + offset));\n });\n }\n\n current(): number[] {\n return this.parts.map((value, column) => value - this.bounds(column)[0]);\n }\n\n select(column: number, index: number) {\n this.parts[column] = this.bounds(column)[0] + index;\n for (let next = column + 1; next < this.depth; next++) {\n const [low, high] = this.bounds(next);\n this.parts[next] = clamp(this.parts[next], low, high);\n }\n }\n\n value(): string {\n if (this.mode === 'time') return this.parts.map(pad).join(':');\n return this.parts.map((value, column) => (column === 0 ? String(value) : pad(value))).join('-');\n }\n\n private bounds(column: number): [number, number] {\n const before = this.parts.slice(0, column);\n let [low, high] = this.naturalBounds(column);\n if (before.every((value, i) => value === this.min[i])) low = Math.max(low, this.min[column]);\n if (before.every((value, i) => value === this.max[i])) high = Math.min(high, this.max[column]);\n return [low, Math.max(low, high)];\n }\n\n private naturalBounds(column: number): [number, number] {\n if (this.mode === 'time') return column === 0 ? [0, 23] : [0, 59];\n if (column === 0) return [this.min[0], this.max[0]];\n if (column === 1) return [1, 12];\n return [1, new Date(this.parts[0], this.parts[1], 0).getDate()];\n }\n\n private label(column: number, value: number): string {\n if (this.mode === 'time') return pad(value);\n return value + ['年', '月', '日'][column];\n }\n}\n\nfunction parseParts(text: string | undefined): number[] {\n return String(text || '').split(/[-:]/).filter(Boolean).map(Number).filter(part => Number.isInteger(part));\n}\n\nfunction fillParts(parts: number[], defaults: number[]): number[] {\n return parts.length ? defaults.map((value, i) => parts[i] ?? value) : defaults;\n}\n\nfunction compareParts(a: number[], b: number[], depth: number): number {\n for (let i = 0; i < depth; i++) {\n if (a[i] !== b[i]) return a[i] - b[i];\n }\n return 0;\n}\n\nfunction clamp(value: number, low: number, high: number): number {\n return Math.min(high, Math.max(low, value));\n}\n\nfunction pad(value: number): string {\n return String(value).padStart(2, '0');\n}\n\n// -----------------------------------------------------------------------------\n// 地区\n// -----------------------------------------------------------------------------\n\nconst REGION_LEVELS: Record<string, number> = { province: 1, city: 2, region: 3, 'sub-district': 4 };\n\ninterface RegionNode {\n name: string;\n code: string;\n postcode: string;\n children: RegionNode[];\n}\n\n/** 数据每行是「编码、名称、邮编」,以 tab 分隔,名称前的 tab 个数就是层级 */\nfunction parseRegionTree(text: string): RegionNode[] {\n const roots: RegionNode[] = [];\n const lastAtDepth: RegionNode[] = [];\n for (const line of text.split('\\n')) {\n const match = /^(\\d+)(\\t+)([^\\t]+)\\t(\\d+)/.exec(line.trimEnd());\n if (!match) continue;\n const depth = match[2].length;\n const node: RegionNode = { code: match[1], name: match[3].trim(), postcode: match[4], children: [] };\n if (depth === 1) roots.push(node);\n else lastAtDepth[depth - 2]?.children.push(node);\n lastAtDepth[depth - 1] = node;\n lastAtDepth.length = depth;\n }\n return roots;\n}\n\n/** 省、市、区、街道逐级联动:改了上级后,下级回到新上级的第一项 */\nclass RegionCascade implements CascadeModel {\n private readonly path: number[];\n\n constructor(private readonly tree: RegionNode[], private readonly levels: number, names: unknown[]) {\n this.path = [];\n for (let level = 0; level < levels; level++) {\n const index = this.options(level).findIndex(node => node.name === names[level]);\n this.path[level] = Math.max(0, index);\n }\n }\n\n columns(): string[][] {\n return this.path.map((_, level) => this.options(level).map(node => node.name));\n }\n\n current(): number[] {\n return [...this.path];\n }\n\n select(column: number, index: number) {\n this.path[column] = index;\n for (let level = column + 1; level < this.levels; level++) this.path[level] = 0;\n }\n\n value(): { value: string[]; code: string[]; postcode: string } {\n const nodes = this.selectedNodes();\n return {\n value: nodes.map(node => node.name),\n code: nodes.map(node => node.code),\n postcode: nodes.at(-1)?.postcode ?? ''\n };\n }\n\n /** 某一级可选的节点:上一级选中节点的下级 */\n private options(level: number): RegionNode[] {\n if (level === 0) return this.tree;\n return this.selectedNodes(level).at(-1)?.children ?? [];\n }\n\n private selectedNodes(levels = this.levels): RegionNode[] {\n const nodes: RegionNode[] = [];\n let options = this.tree;\n for (let level = 0; level < levels; level++) {\n const node = options[this.path[level]];\n if (!node) break;\n nodes.push(node);\n options = node.children;\n }\n return nodes;\n }\n}\n","/**\n * 请求拦截:setup 的 network.routes、测试 API 的 route 声明的接口不发往网络,直接返回给定的响应\n *\n * 规则写法:'[METHOD ]URL',如 'POST https://api.example.com/login'。URL 里 * 匹配一段路径,\n * ** 匹配任意内容(可以不写域名,按路径匹配);查询参数和 hash 不参与匹配。\n */\n\nimport type { MockRequest, MockResponse, RouteHandler } from '../../../setup';\n\nconst METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT'];\n\ninterface Route {\n pattern: string;\n matches: RequestMatcher;\n handler: RouteHandler;\n}\n\ntype RequestMatcher = (request: Pick<MockRequest, 'url' | 'method'>) => boolean;\n\nexport interface MatchedRoute {\n /** 命中的规则,即添加时的写法 */\n pattern: string;\n /**\n * 响应体原样是文本或二进制,小程序拿到哪种由请求的 responseType 决定\n * @throws 延迟期间 signal 被 abort 时,抛出 signal.reason\n */\n respond(signal?: AbortSignal): Promise<{ statusCode: number; header: Record<string, string>; body: string | BufferSource }>;\n}\n\nexport class RequestRoutes {\n private routes: Route[] = [];\n\n /**\n * 后添加的规则优先\n * @throws 规则写法不对时\n */\n add(pattern: string, handler: RouteHandler) {\n const matches = compilePattern(pattern);\n if (typeof handler !== 'function' && (handler === null || typeof handler !== 'object')) {\n throw new Error('拦截规则的值需要是响应对象 { status?, header?, body?, delay? },或按请求返回响应的函数');\n }\n if (typeof handler === 'object') checkDelay(handler.delay);\n this.routes.unshift({ pattern, matches, handler });\n }\n\n /** 删除按这个写法添加的规则,不传时删除全部 */\n remove(pattern?: string) {\n this.routes = pattern === undefined ? [] : this.routes.filter(route => route.pattern !== pattern);\n }\n\n /** 找到匹配的规则,没有时返回 undefined。响应在调用 respond 时才生成 */\n match(request: MockRequest): MatchedRoute | undefined {\n const route = this.routes.find(r => r.matches(request));\n if (!route) return undefined;\n\n return {\n pattern: route.pattern,\n async respond(signal) {\n console.info(`[wxa-runner] 拦截请求 ${request.method} ${request.url}(${route.pattern})`);\n const response: MockResponse = typeof route.handler === 'function' ? (await route.handler(request)) || {} : route.handler;\n checkDelay(response.delay);\n if (response.delay) await sleep(response.delay, signal);\n const { body } = response;\n const isJson = body !== undefined && typeof body !== 'string' && !isBinary(body);\n return {\n statusCode: response.status ?? 200,\n header: { ...(isJson ? { 'Content-Type': 'application/json' } : {}), ...response.header },\n body: body === undefined ? '' : isJson ? JSON.stringify(body) : (body as string | BufferSource)\n };\n }\n };\n }\n}\n\n/**\n * 把 '[METHOD ]URL' 规则编译成匹配函数,查询参数和 hash 不参与匹配\n * @throws 规则写法不对时\n */\nexport function compilePattern(pattern: string): RequestMatcher {\n const parts = pattern.trim().split(/\\s+/);\n if (parts.length > 2 || (parts.length === 2 && !METHODS.includes(parts[0].toUpperCase()))) {\n throw new Error(`拦截规则应写成 \"[请求方法 ]地址\",如 \"POST https://api.example.com/login\"、\"**/auth/login\"`);\n }\n const [method, url] = parts.length === 2 ? [parts[0].toUpperCase(), parts[1]] : [null, parts[0]];\n const regexp = globToRegExp(url);\n return request => (!method || method === request.method) && regexp.test(String(request.url).replace(/[?#].*$/, ''));\n}\n\n/** ArrayBuffer 和 Uint8Array 等视图(Node 的 Buffer 经 Playwright 传进来也是 Uint8Array),不论属于哪个 iframe */\nfunction isBinary(value: unknown): value is BufferSource {\n return ArrayBuffer.isView(value) || Object.prototype.toString.call(value) === '[object ArrayBuffer]';\n}\n\nfunction checkDelay(delay: unknown) {\n if (delay !== undefined && !(typeof delay === 'number' && delay >= 0 && Number.isFinite(delay))) {\n throw new Error(`delay 需要是不小于 0 的毫秒数,实际是 ${String(delay)}`);\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason);\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener('abort', () => {\n clearTimeout(timer);\n reject(signal.reason);\n }, { once: true });\n });\n}\n\nfunction globToRegExp(glob: string): RegExp {\n const source = glob\n .split('**')\n .map(part => part.split('*').map(escapeRegExp).join('[^/]*'))\n .join('.*');\n return new RegExp(`^${source}$`);\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","/**\n * 保存的文件(wx.saveFile 等):文件和临时文件一样存在开发服务器上,保存记录写在 Storage 里\n *\n * 保存记录和 Storage 一样按 appid 隔离、整页刷新后还在。开发服务器重启后文件就没了,对应的记录随之失效,\n * 相当于真机上缓存的文件被清理:Painter 等库查不到缓存时会重新下载。\n */\n\nimport { ApiHandler } from './registry';\nimport type { MiniProgramStorage } from './storage';\nimport { isTempFile, removeTempFile, saveTempFile, tempFileSize, tempFileType } from './tempFiles';\n\nconst NAMESPACE = 'savedFiles';\n\ninterface SavedFile {\n size: number;\n /** 秒 */\n createTime: number;\n}\n\nexport function createSavedFileApis(storage: MiniProgramStorage): Record<string, ApiHandler> {\n const record = (filePath: string) => storage.get(NAMESPACE, filePath)?.data as SavedFile | undefined;\n\n /** 有保存记录、文件也还在时返回记录;文件已经没了就删掉记录 */\n const liveRecord = async (filePath: string) => {\n const saved = record(filePath);\n if (!saved) return undefined;\n if (await tempFileSize(filePath) !== null) return saved;\n storage.remove(NAMESPACE, filePath);\n return undefined;\n };\n\n return {\n // 和真机一样:存成新文件,原来的临时文件随之删除\n saveFile: async args => {\n // FileSystemManager.saveFile 可以指定保存位置,那是内存文件系统,存不了图片等二进制内容\n if (args.filePath) throw new Error('wxa-runner 暂不支持指定 filePath,不传时保存成功后返回 savedFilePath');\n const res = isTempFile(args.tempFilePath) ? await fetch(args.tempFilePath) : null;\n if (!res?.ok) throw new Error(`tempFilePath file not exist ${args.tempFilePath}`);\n const data = await res.blob();\n const savedFilePath = await saveTempFile(data, tempFileType(args.tempFilePath, data.type, 'tmp'));\n await removeTempFile(args.tempFilePath);\n storage.set(NAMESPACE, savedFilePath, { size: data.size, createTime: Math.floor(Date.now() / 1000) });\n return { savedFilePath };\n },\n getSavedFileList: async () => {\n const fileList = [];\n for (const filePath of storage.keys(NAMESPACE)) {\n const saved = await liveRecord(filePath);\n if (saved) fileList.push({ filePath, ...saved });\n }\n return { fileList };\n },\n getSavedFileInfo: async args => {\n const saved = await liveRecord(args.filePath);\n if (!saved) throw new Error(`file not exist ${args.filePath}`);\n return { ...saved };\n },\n removeSavedFile: async args => {\n if (!record(args.filePath)) throw new Error(`file not exist ${args.filePath}`);\n storage.remove(NAMESPACE, args.filePath);\n await removeTempFile(args.filePath);\n }\n };\n}\n","/**\n * Storage:落到浏览器 localStorage,按 appid 和 storageId 隔离\n *\n * 基础库传来的 data 已经序列化成字符串,并附带 dataType(\"Number\"、\"Object\" 等),\n * 读取时原样交回,由基础库反序列化。storageId 0 是业务数据,其他值是基础库内部缓存。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\n\n/** 只用到 localStorage 的这几个方法,便于测试时替换 */\nexport interface KeyValueStore {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n key(index: number): string | null;\n readonly length: number;\n}\n\nconst LIMIT_SIZE_KB = 10 * 1024;\n\nexport class MiniProgramStorage {\n constructor(private readonly store: KeyValueStore, private readonly appid: string) {}\n\n set(namespace: string, key: string, data: unknown, dataType?: string) {\n this.store.setItem(this.prefix(namespace) + key, JSON.stringify([data, dataType]));\n }\n\n get(namespace: string, key: string): { data: unknown; dataType?: string } | null {\n const raw = this.store.getItem(this.prefix(namespace) + key);\n if (raw === null) return null;\n const [data, dataType] = JSON.parse(raw);\n return { data, dataType };\n }\n\n remove(namespace: string, key: string) {\n this.store.removeItem(this.prefix(namespace) + key);\n }\n\n keys(namespace: string): string[] {\n const prefix = this.prefix(namespace);\n const keys: string[] = [];\n for (let i = 0; i < this.store.length; i++) {\n const key = this.store.key(i);\n if (key && key.startsWith(prefix)) keys.push(key.slice(prefix.length));\n }\n return keys;\n }\n\n clear(namespace: string) {\n for (const key of this.keys(namespace)) this.remove(namespace, key);\n }\n\n info(namespace: string) {\n const prefix = this.prefix(namespace);\n const keys = this.keys(namespace);\n let bytes = 0;\n for (const key of keys) {\n bytes += (key.length + (this.store.getItem(prefix + key) || '').length) * 2;\n }\n return { keys, currentSize: Math.ceil(bytes / 1024), limitSize: LIMIT_SIZE_KB };\n }\n\n private prefix(namespace: string) {\n return `wxa:${this.appid}:${namespace}:`;\n }\n}\n\nexport interface StoredValue {\n data: string;\n dataType: string;\n}\n\n/**\n * 按基础库 anyTypeToString 的规则序列化:宿主直接写入的值,wx.getStorageSync 读回来与原值一致\n *\n * @throws 值的类型无法存储(函数、Map 等)时\n */\nexport function encodeStorageValue(value: unknown): StoredValue {\n const dataType = typeOf(value);\n switch (dataType) {\n case 'Array':\n case 'Object':\n return { data: JSON.stringify(value), dataType };\n case 'String':\n case 'Number':\n case 'Boolean':\n return { data: String(value), dataType };\n case 'Date':\n return { data: String((value as Date).getTime()), dataType };\n case 'Undefined':\n case 'Null':\n return { data: dataType.toLowerCase(), dataType };\n default:\n throw new Error(`不支持存储 ${dataType} 类型的值`);\n }\n}\n\n/** encodeStorageValue 的逆过程,与基础库 stringToAnyType 一致;没有 dataType 时原样返回 */\nexport function decodeStorageValue(item: { data: unknown; dataType?: string }): unknown {\n const { data, dataType } = item;\n if (typeof data !== 'string' || !dataType) return data;\n switch (dataType) {\n case 'String':\n return data;\n case 'Array':\n case 'Object':\n return JSON.parse(data);\n case 'Number':\n return parseFloat(data);\n case 'Boolean':\n return data === 'true';\n case 'Date':\n return new Date(parseInt(data, 10));\n case 'Undefined':\n return undefined;\n case 'Null':\n return null;\n default:\n return '';\n }\n}\n\nfunction typeOf(value: unknown): string {\n return Object.prototype.toString.call(value).slice(8, -1);\n}\n\nexport function createStorageApis(storage: MiniProgramStorage): Record<string, ApiHandler> {\n const ns = (args: any) => `s${args.storageId || 0}`;\n\n const get: ApiHandler = (args, { api }) => {\n const item = storage.get(ns(args), args.key);\n return item ? ok(api, item) : fail(api, 'data not found');\n };\n const set: ApiHandler = args => storage.set(ns(args), args.key, args.data, args.dataType);\n const remove: ApiHandler = args => storage.remove(ns(args), args.key);\n const clear: ApiHandler = args => storage.clear(ns(args));\n const info: ApiHandler = args => storage.info(ns(args));\n\n // 渲染层用 global storage 存 cookie 等信息\n const globalGet: ApiHandler = (args, { api }) => {\n const item = storage.get('global', args.key);\n return item ? ok(api, { data: item.data }) : fail(api, 'data not found');\n };\n\n return {\n getStorage: get,\n getStorageSync: get,\n setStorage: set,\n setStorageSync: set,\n removeStorage: remove,\n removeStorageSync: remove,\n clearStorage: clear,\n clearStorageSync: clear,\n getStorageInfo: info,\n getStorageInfoSync: info,\n getGlobalStorage: globalGet,\n getGlobalStorageSync: globalGet,\n setGlobalStorage: args => storage.set('global', args.key, args.data),\n setGlobalStorageSync: args => storage.set('global', args.key, args.data),\n removeGlobalStorage: args => storage.remove('global', args.key),\n clearGlobalStorage: () => storage.clear('global'),\n getGlobalStorageInfo: () => storage.info('global')\n };\n}\n","/**\n * 设备与系统信息:以模拟设备为准,而不是宿主浏览器窗口\n */\n\nimport type { DeviceProfile } from '../../types';\nimport { ApiHandler, ok } from './registry';\n\nexport interface SystemApiOptions {\n device: DeviceProfile;\n baseLibVersion: string;\n /** 当前页面可用高度(扣除导航栏、tabBar) */\n windowHeight: () => number;\n /** 当前页面窗口顶部到屏幕顶部的距离,自定义导航栏时为 0 */\n screenTop: () => number;\n}\n\nexport const NAVIGATION_BAR_HEIGHT = 44;\nexport const TAB_BAR_HEIGHT = 50;\n\n/** 胶囊按钮位置,外壳绘制和 getMenuButtonBoundingClientRect 共用 */\nexport function menuButtonRect(device: DeviceProfile) {\n const width = 87;\n const height = 32;\n const top = device.statusBarHeight + 6;\n const right = device.screenWidth - 7;\n return { width, height, top, right, bottom: top + height, left: right - width };\n}\n\nexport function createSystemApis(options: SystemApiOptions): Record<string, ApiHandler> {\n const { device } = options;\n\n const windowInfo = () => {\n const safeBottom = device.screenHeight - device.safeAreaBottom;\n return {\n pixelRatio: device.pixelRatio,\n screenWidth: device.screenWidth,\n screenHeight: device.screenHeight,\n windowWidth: device.screenWidth,\n windowHeight: options.windowHeight(),\n windowTop: 0,\n windowBottom: 0,\n statusBarHeight: device.statusBarHeight,\n safeArea: {\n left: 0,\n right: device.screenWidth,\n top: device.statusBarHeight,\n bottom: safeBottom,\n width: device.screenWidth,\n height: safeBottom - device.statusBarHeight\n },\n safeAreaInsets: { top: device.statusBarHeight, left: 0, right: 0, bottom: device.safeAreaBottom },\n screenTop: options.screenTop()\n };\n };\n\n const deviceInfo = () => ({\n brand: 'devtools',\n model: device.model,\n system: device.system,\n platform: device.platform,\n benchmarkLevel: 1,\n abi: 'arm64',\n deviceAbi: 'arm64',\n cpuType: 'unknown',\n memorySize: 4096\n });\n\n const appBaseInfo = () => ({\n SDKVersion: options.baseLibVersion,\n enableDebug: false,\n host: { env: 'WeChat', appId: '' },\n language: 'zh_CN',\n version: '8.0.50',\n theme: 'light',\n fontSizeSetting: 16\n });\n\n const authorizeSetting = () => ({\n albumAuthorized: 'authorized',\n bluetoothAuthorized: 'authorized',\n cameraAuthorized: 'authorized',\n locationAuthorized: 'authorized',\n locationReducedAccuracy: false,\n microphoneAuthorized: 'authorized',\n notificationAuthorized: 'authorized',\n phoneCalendarAuthorized: 'authorized'\n });\n\n const systemSetting = () => ({\n bluetoothEnabled: true,\n locationEnabled: true,\n wifiEnabled: true,\n deviceOrientation: 'portrait'\n });\n\n const systemInfo: ApiHandler = (args, { api }) => {\n switch (args.type) {\n case 'windowInfo': return ok(api, windowInfo());\n case 'deviceInfo': return ok(api, deviceInfo());\n case 'appBaseInfo': return ok(api, appBaseInfo());\n case 'appAuthorizeSetting': return ok(api, authorizeSetting());\n case 'systemSetting': return ok(api, systemSetting());\n }\n return ok(api, {\n ...deviceInfo(),\n ...windowInfo(),\n ...appBaseInfo(),\n ...systemSetting(),\n albumAuthorized: true,\n cameraAuthorized: true,\n locationAuthorized: true,\n microphoneAuthorized: true,\n notificationAuthorized: true\n });\n };\n\n return {\n getSystemInfo: systemInfo,\n getSystemInfoSync: systemInfo,\n getSystemInfoAsync: systemInfo,\n getWindowInfo: (_args, { api }) => ok(api, windowInfo()),\n getDeviceInfo: (_args, { api }) => ok(api, deviceInfo()),\n getAppBaseInfo: (_args, { api }) => ok(api, appBaseInfo()),\n getAppAuthorizeSetting: (_args, { api }) => ok(api, authorizeSetting()),\n getSystemSetting: (_args, { api }) => ok(api, systemSetting()),\n getNetworkType: (_args, { api }) => ok(api, { networkType: 'wifi', signalStrength: 100, hasSystemProxy: false }),\n getBatteryInfo: (_args, { api }) => ok(api, { level: 100, isCharging: true }),\n getBatteryInfoSync: (_args, { api }) => ok(api, { level: 100, isCharging: true }),\n getMenuButtonBoundingClientRect: (_args, { api }) => ok(api, menuButtonRect(device)),\n getScreenBrightness: (_args, { api }) => ok(api, { value: 0.8 }),\n setScreenBrightness: () => undefined,\n setKeepScreenOn: () => undefined,\n vibrateShort: () => undefined,\n vibrateLong: () => undefined\n };\n}\n","/**\n * 界面 API:toast / loading / modal / actionSheet / 导航栏\n */\n\nimport type { NavigationState, PhoneShell } from '../ui/PhoneShell';\nimport { ApiHandler, fail, ok } from './registry';\n\nexport interface UiApiOptions {\n shell: PhoneShell;\n /** 修改当前页面的导航栏状态(随页面保存,返回时恢复) */\n updateNavigation: (state: Partial<NavigationState>) => void;\n}\n\nexport function createUiApis({ shell, updateNavigation }: UiApiOptions): Record<string, ApiHandler> {\n return {\n showToast: args => shell.showToast(args),\n hideToast: () => shell.hideToast(),\n showLoading: args => shell.showToast({ ...args, icon: 'loading', duration: 0 }),\n hideLoading: () => shell.hideToast(),\n showModal: async (args, { api }) => ok(api, await shell.showModal(args)),\n showActionSheet: async (args, { api }) => {\n const tapIndex = await shell.showActionSheet(args);\n return tapIndex === null ? fail(api, 'cancel') : ok(api, { tapIndex });\n },\n\n setNavigationBarTitle: args => updateNavigation({ title: String(args.title ?? '') }),\n setNavigationBarColor: args => updateNavigation({\n backgroundColor: args.backgroundColor,\n textStyle: String(args.frontColor).toLowerCase() === '#000000' ? 'black' : 'white'\n }),\n showNavigationBarLoading: () => shell.setNavigationLoading(true),\n hideNavigationBarLoading: () => shell.setNavigationLoading(false),\n hideHomeButton: () => undefined,\n setBackgroundColor: () => undefined,\n setBackgroundTextStyle: () => undefined,\n startPullDownRefresh: () => undefined,\n stopPullDownRefresh: () => undefined\n };\n}\n","/**\n * web-view 组件背后的原生网页视图\n *\n * 渲染层的 web-view 组件调 insertHTMLWebView 占位,updateHTMLWebView 设置地址和位置,\n * 销毁时 removeHTMLWebView;加载进度通过渲染层的 onWebviewStartLoad / onWebviewFinishLoad\n * 告诉组件,组件据此触发 bindload。\n *\n * 网页放在所在页面渲染层里的 iframe 中,跟着页面显示、隐藏和关闭。\n * 设置了 X-Frame-Options 或 CSP frame-ancestors 的网站不允许被嵌入,这类网页显示不出来。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\n\nexport interface WebViewApiOptions {\n /** 页面渲染层的 document,页面已关闭时为 undefined */\n documentOf(webviewId: number): Document | undefined;\n /** 派发给渲染层的原生事件(渲染层里 WeixinJSBridge.on 收到) */\n emitToWebview(webviewId: number, event: string, data: unknown): void;\n}\n\ninterface Position {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\nexport function createWebViewApis({ documentOf, emitToWebview }: WebViewApiOptions): Record<string, ApiHandler> {\n // 三个接口都由网页所在的渲染层调用,到那个文档里按 htmlId 找;不另存引用,页面关闭时随文档一起释放\n const find = (webviewId: number, htmlId: unknown) =>\n documentOf(webviewId)?.querySelector<HTMLIFrameElement>(`iframe[data-wxa-html-id=\"${Number(htmlId)}\"]`) ?? null;\n\n const reportStart = (webviewId: number, htmlId: number, src: string) =>\n emitToWebview(webviewId, 'onWebviewStartLoad', { htmlId, src, isMainFrame: true });\n const reportFinish = (webviewId: number, htmlId: number, src: string) =>\n emitToWebview(webviewId, 'onWebviewFinishLoad', { htmlId, src });\n\n const place = (frame: HTMLIFrameElement, position?: Partial<Position>) => {\n if (!position) return;\n for (const side of ['left', 'top', 'width', 'height'] as const) {\n if (typeof position[side] === 'number') frame.style[side] = `${position[side]}px`;\n }\n };\n\n return {\n insertHTMLWebView: (args, { api, webviewId }) => {\n const doc = documentOf(webviewId);\n if (!doc) return fail(api, 'page not found');\n\n const htmlId = Number(args.htmlId);\n const frame = doc.createElement('iframe');\n frame.dataset.wxaHtmlId = String(htmlId);\n frame.style.cssText = 'position:fixed;z-index:2147483647;border:0;background:#fff';\n place(frame, args.position);\n frame.addEventListener('load', () => {\n const requested = frame.dataset.wxaLoading;\n if (requested) {\n delete frame.dataset.wxaLoading;\n reportFinish(webviewId, htmlId, requested);\n return;\n }\n // 网页里自己跳转的:同源时报告新地址;跨域读不到地址就不报,免得拿旧地址冒充\n const src = readableUrl(frame);\n if (!src || src === 'about:blank') return;\n reportStart(webviewId, htmlId, src);\n reportFinish(webviewId, htmlId, src);\n });\n doc.body.appendChild(frame);\n return ok(api);\n },\n\n updateHTMLWebView: (args, { api, webviewId }) => {\n const frame = find(webviewId, args.htmlId);\n if (!frame) return fail(api, 'web-view not found');\n place(frame, args.position);\n if (args.src) {\n const src = String(args.src);\n frame.dataset.wxaLoading = src;\n reportStart(webviewId, Number(args.htmlId), src);\n frame.src = src;\n }\n return ok(api);\n },\n\n removeHTMLWebView: (args, { api, webviewId }) => {\n find(webviewId, args.htmlId)?.remove();\n return ok(api);\n }\n };\n}\n\nfunction readableUrl(frame: HTMLIFrameElement): string | null {\n try {\n return frame.contentWindow?.location.href ?? null;\n } catch {\n return null;\n }\n}\n","/**\n * 页面栈:只管顺序和上限,页面的创建与销毁由调用方处理\n */\n\nexport const MAX_PAGE_STACK = 10;\n\nexport class PageStack<T> {\n private items: T[] = [];\n\n constructor(private readonly max = MAX_PAGE_STACK) {}\n\n get size(): number {\n return this.items.length;\n }\n\n current(): T | undefined {\n return this.items[this.items.length - 1];\n }\n\n entries(): T[] {\n return [...this.items];\n }\n\n canPush(): boolean {\n return this.items.length < this.max;\n }\n\n push(item: T) {\n if (!this.canPush()) throw new Error('webview count limit exceed');\n this.items.push(item);\n }\n\n /** 至少保留栈底页面;返回被弹出的页面(栈顶在前) */\n pop(delta = 1): T[] {\n const count = Math.max(0, Math.min(Math.floor(delta) || 1, this.items.length - 1));\n return this.items.splice(this.items.length - count, count).reverse();\n }\n\n /** 替换栈顶,返回原栈顶 */\n replaceTop(item: T): T | undefined {\n const previous = this.items.pop();\n this.items.push(item);\n return previous;\n }\n\n /** 清空并放入新页面,返回原有页面 */\n reset(item: T): T[] {\n const previous = this.items;\n this.items = [item];\n return previous.filter(existing => existing !== item);\n }\n}\n","/**\n * 一个页面对应一个渲染层 iframe\n */\n\nimport type { FrameBridge } from '../types';\nimport type { NavigationState, SafeAreaInsets } from './ui/PhoneShell';\n\ntype PendingDispatch = (bridge: FrameBridge, win: Window) => void;\n\nexport class PageView {\n readonly frame: HTMLIFrameElement;\n readonly ready: Promise<void>;\n win: Window | null = null;\n bridge: FrameBridge | null = null;\n navigation: NavigationState;\n private markReady!: () => void;\n private pending: PendingDispatch[] = [];\n\n constructor(\n readonly id: number,\n readonly path: string,\n readonly query: Record<string, string>,\n container: HTMLElement,\n version: number,\n navigation: NavigationState\n ) {\n this.navigation = navigation;\n this.ready = new Promise(resolve => {\n this.markReady = resolve;\n });\n\n this.frame = document.createElement('iframe');\n this.frame.name = `wxa-webview-${id}`;\n this.frame.dataset.webviewId = String(id);\n this.frame.dataset.path = path;\n this.frame.style.visibility = 'hidden';\n this.frame.src = `/__wxa__/webview/${path}.html?id=${id}&v=${version}`;\n container.appendChild(this.frame);\n }\n\n get url(): string {\n const query = new URLSearchParams(this.query).toString();\n return query ? `${this.path}?${query}` : this.path;\n }\n\n attach(win: Window, bridge: FrameBridge) {\n this.win = win;\n this.bridge = bridge;\n const pending = this.pending;\n this.pending = [];\n pending.forEach(dispatch => dispatch(bridge, win));\n }\n\n /** 渲染层脚本全部执行完(含 generateFuncReady)后调用 */\n loaded() {\n this.markReady();\n }\n\n /** 渲染层还没注册桥时先缓存,注册后按顺序补发 */\n dispatch(fn: PendingDispatch) {\n if (this.bridge && this.win) fn(this.bridge, this.win);\n else this.pending.push(fn);\n }\n\n /** 页面样式里的 env(safe-area-inset-*) 构建时已改写成这些变量,见 rewriteSafeAreaInsets */\n setSafeAreaInsets(insets: SafeAreaInsets) {\n this.dispatch((_bridge, win) => {\n const style = win.document.documentElement.style;\n for (const [side, value] of Object.entries(insets)) {\n style.setProperty(`--wxa-safe-area-inset-${side}`, `${value}px`);\n }\n });\n }\n\n /** data-current 是给测试用的公开契约:iframe[data-current] 始终指向当前页 */\n show() {\n this.frame.style.visibility = 'visible';\n this.frame.style.zIndex = '1';\n this.frame.dataset.current = '';\n }\n\n hide() {\n this.frame.style.visibility = 'hidden';\n this.frame.style.zIndex = '0';\n delete this.frame.dataset.current;\n }\n\n destroy() {\n this.frame.remove();\n this.win = null;\n this.bridge = null;\n }\n}\n","/**\n * 宿主交给 iframe 的值,在目标 iframe 的全局环境(realm)里重建\n *\n * 宿主、逻辑层、渲染层是不同的 iframe,各有一套 Object / Array / ArrayBuffer。属于别的 iframe 的值,\n * 在目标 iframe 里 instanceof 不成立,基础库的 setData 也会把这样的数组当成普通对象。\n */\n\n/** 在目标 iframe 的 realm 中重建数据,避免跨 realm 的 instanceof 判断失效 */\nexport function cloneInto<T>(win: Window, value: T): T {\n if (value === undefined) return value;\n return (win as any).JSON.parse(JSON.stringify(value));\n}\n\nconst BUFFER_KEY = '__wxa_array_buffer__';\n\n/**\n * 原生接口的结果和事件交给 iframe:同 cloneInto,另外把 ArrayBuffer(readFile 读到的文件、按 arraybuffer 请求到的数据、\n * WebSocket 的二进制消息)复制成目标 realm 的。\n * 只有原生接口会给出 ArrayBuffer;setData 等消息数据量大,仍走 cloneInto,省掉逐个字段的检查\n */\nexport function cloneNativeInto<T>(win: Window, value: T): T {\n if (value === undefined) return value;\n const buffers: ArrayBuffer[] = [];\n const json = JSON.stringify(value, (_key, item) => {\n if (Object.prototype.toString.call(item) !== '[object ArrayBuffer]') return item;\n buffers.push(item);\n return { [BUFFER_KEY]: buffers.length - 1 };\n });\n const targetJson: JSON = (win as any).JSON;\n if (!buffers.length) return targetJson.parse(json);\n return targetJson.parse(json, (_key, item) => (item?.[BUFFER_KEY] === undefined ? item : copyBuffer(win, buffers[item[BUFFER_KEY]])));\n}\n\nfunction copyBuffer(win: Window, source: ArrayBuffer): ArrayBuffer {\n const copy: ArrayBuffer = new (win as any).ArrayBuffer(source.byteLength);\n new Uint8Array(copy).set(new Uint8Array(source));\n return copy;\n}\n","/**\n * 浏览器的文件选择框\n */\n\nexport interface FileChooserOptions {\n /** 如 image/* */\n accept: string;\n multiple: boolean;\n /** 手机浏览器上直接打开相机;桌面浏览器忽略,照常打开文件选择框 */\n capture: boolean;\n}\n\n/**\n * 只能在用户点击后的短时间内调用(见 hasUserActivation),否则浏览器不打开选择框,返回的 Promise 也不会结束\n * @returns 用户关掉选择框时为 null\n */\nexport function chooseFiles(options: FileChooserOptions): Promise<File[] | null> {\n return new Promise(resolve => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = options.accept;\n input.multiple = options.multiple;\n if (options.capture) input.setAttribute('capture', 'environment');\n input.style.display = 'none';\n\n const finish = (files: File[] | null) => {\n input.remove();\n resolve(files);\n };\n input.addEventListener('change', () => finish(input.files?.length ? Array.from(input.files) : null));\n input.addEventListener('cancel', () => finish(null));\n document.body.appendChild(input);\n input.click();\n });\n}\n\n/**\n * 用户刚点击过、可以打开文件选择框。用户在页面里点击也算:点击会传到宿主页。\n * 不支持查询的浏览器当作可以\n */\nexport function hasUserActivation(): boolean {\n return navigator.userActivation?.isActive ?? true;\n}\n","export function element(tag: string, className: string, text?: string): HTMLElement {\n const el = document.createElement(tag);\n el.className = className;\n if (text !== undefined) el.textContent = text;\n return el;\n}\n","/**\n * 图片预览层:黑底全屏显示一张图片,左右切换;和真机一样点一下关闭\n */\n\nimport { element } from './dom';\n\n/** @param current 先显示的图片下标 */\nexport function openImagePreview(container: HTMLElement, urls: string[], current: number) {\n const layer = element('div', 'wxa-preview');\n layer.setAttribute('role', 'dialog');\n layer.setAttribute('aria-label', '图片预览');\n const image = document.createElement('img');\n image.className = 'wxa-preview-image';\n const position = element('div', 'wxa-preview-position');\n const prev = element('button', 'wxa-preview-prev', '‹');\n prev.setAttribute('aria-label', '上一张');\n const next = element('button', 'wxa-preview-next', '›');\n next.setAttribute('aria-label', '下一张');\n\n let shown = 0;\n const show = (index: number) => {\n shown = Math.min(Math.max(index, 0), urls.length - 1);\n image.src = urls[shown];\n position.textContent = `${shown + 1}/${urls.length}`;\n prev.style.visibility = shown > 0 ? '' : 'hidden';\n next.style.visibility = shown < urls.length - 1 ? '' : 'hidden';\n };\n prev.addEventListener('click', () => show(shown - 1));\n next.addEventListener('click', () => show(shown + 1));\n layer.addEventListener('click', event => {\n if (event.target !== prev && event.target !== next) layer.remove();\n });\n\n layer.append(image, position, prev, next);\n container.appendChild(layer);\n show(current);\n}\n","/** 外壳边框(box-shadow 最外圈)宽度,缩放时计入手机外框尺寸 */\nexport const DEVICE_BEZEL = 13;\nexport const STAGE_PADDING = 24;\nexport const STAGE_GAP = 16;\n/** 选择器每一行的高度,一列显示 5 行,选中项在中间 */\nexport const PICKER_ITEM_HEIGHT = 34;\n\nexport const SHELL_CSS = `\nhtml, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50% 0%, #f6f7f9 0%, #e6e9ee 100%); font-family: -apple-system, BlinkMacSystemFont, \"SF Pro Text\", \"PingFang SC\", \"Helvetica Neue\", sans-serif; -webkit-font-smoothing: antialiased; }\n.wxa-stage { min-height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: ${STAGE_GAP}px; padding: ${STAGE_PADDING}px; box-sizing: border-box; }\n.wxa-device-slot { position: relative; flex: none; }\n.wxa-device { position: absolute; transform-origin: 0 0; overflow: hidden; background: #fff; border-radius: 6px; display: flex; flex-direction: column; box-shadow: 0 0 0 ${DEVICE_BEZEL - 2}px #111214, 0 0 0 ${DEVICE_BEZEL - 1}px #3a3b3f, 0 0 0 ${DEVICE_BEZEL}px #1b1c1f, 0 32px 64px -12px rgba(15,23,42,.35), 0 14px 28px -8px rgba(15,23,42,.18); }\n.wxa-device.has-notch { border-radius: 40px; }\n.wxa-notch { position: absolute; top: 0; left: 50%; z-index: 30; width: 209px; height: 30px; transform: translateX(-50%); background: #000; border-radius: 0 0 20px 20px; pointer-events: none; }\n.wxa-notch::before, .wxa-notch::after { content: ''; position: absolute; top: 0; width: 6px; height: 6px; }\n.wxa-notch::before { left: -6px; background: radial-gradient(circle at 0 100%, transparent 5.5px, #000 6px); }\n.wxa-notch::after { right: -6px; background: radial-gradient(circle at 100% 100%, transparent 5.5px, #000 6px); }\n.wxa-home-indicator { position: absolute; bottom: 8px; left: 50%; z-index: 30; width: 134px; height: 5px; transform: translateX(-50%); border-radius: 3px; background: rgba(0,0,0,.85); pointer-events: none; }\n.wxa-statusbar { flex: none; display: flex; align-items: center; justify-content: space-between; padding: 0 8px; font-size: 12px; font-weight: 600; box-sizing: border-box; user-select: none; }\n.wxa-statusbar-icons { display: flex; align-items: center; gap: 5px; }\n.wxa-statusbar svg { display: block; }\n.has-notch .wxa-statusbar { display: grid; grid-template-columns: 1fr 209px 1fr; align-items: start; padding: 15px 0 0; font-size: 15px; letter-spacing: -.2px; }\n.has-notch .wxa-statusbar-time { grid-column: 1; justify-self: center; line-height: 20px; }\n.has-notch .wxa-statusbar-icons { grid-column: 3; justify-self: center; height: 20px; }\n.wxa-navbar { flex: none; height: 44px; position: relative; display: flex; align-items: center; justify-content: center; box-sizing: border-box; }\n.wxa-navbar.is-hidden, .wxa-statusbar.is-hidden { display: none; }\n.wxa-navbar-title { font-size: 17px; font-weight: 600; max-width: calc(100% - 204px); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }\n.wxa-navbar-back { position: absolute; left: 4px; top: 0; height: 44px; width: 44px; padding: 0; border: 0; background: none; color: inherit; cursor: pointer; display: flex; align-items: center; justify-content: center; }\n.wxa-navbar-loading { width: 14px; height: 14px; margin-right: 6px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: wxa-spin .8s linear infinite; display: none; }\n.wxa-navbar.is-loading .wxa-navbar-loading { display: inline-block; }\n.wxa-capsule { position: absolute; z-index: 6; display: flex; align-items: center; box-sizing: border-box; border-radius: 16px; border: .5px solid rgba(0,0,0,.12); background: rgba(255,255,255,.62); color: #000; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); user-select: none; }\n.wxa-capsule.is-light { border-color: rgba(255,255,255,.28); background: rgba(0,0,0,.18); color: #fff; }\n.wxa-capsule > span { flex: 1; height: 100%; display: flex; align-items: center; justify-content: center; }\n.wxa-capsule > span + span { position: relative; }\n.wxa-capsule > span + span::before { content: ''; position: absolute; left: 0; top: 8px; bottom: 8px; width: 1px; background: currentColor; opacity: .25; transform: scaleX(.5); }\n.wxa-capsule svg { display: block; }\n.wxa-pages { flex: 1; position: relative; overflow: hidden; }\n.wxa-pages iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: #fff; }\n.wxa-tabbar { flex: none; height: calc(50px + var(--wxa-safe-bottom, 0px)); padding-bottom: var(--wxa-safe-bottom, 0px); display: flex; border-top: .5px solid rgba(0,0,0,.1); box-sizing: border-box; }\n.wxa-tabbar.is-hidden { display: none; }\n.wxa-tabbar-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: 10px; cursor: pointer; user-select: none; gap: 2px; }\n.wxa-tabbar-item img { width: 24px; height: 24px; }\n.wxa-overlay { position: absolute; inset: 0; pointer-events: none; z-index: 10; }\n.wxa-mask { position: absolute; inset: 0; pointer-events: auto; }\n.wxa-mask.is-dim { background: rgba(0,0,0,.5); }\n.wxa-toast { position: absolute; left: 50%; top: 45%; transform: translate(-50%, -50%); min-width: 120px; max-width: 70%; padding: 14px 16px; border-radius: 8px; background: rgba(17,17,17,.75); color: #fff; font-size: 14px; text-align: center; box-sizing: border-box; pointer-events: none; }\n.wxa-toast.has-icon { width: 136px; min-height: 120px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; }\n.wxa-toast-icon { font-size: 36px; line-height: 1; }\n.wxa-toast-spinner { width: 34px; height: 34px; border: 3px solid #fff; border-right-color: transparent; border-radius: 50%; animation: wxa-spin .8s linear infinite; }\n.wxa-modal { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 80%; background: #fff; border-radius: 12px; overflow: hidden; pointer-events: auto; text-align: center; }\n.wxa-modal-title { padding: 24px 20px 8px; font-size: 17px; font-weight: 600; }\n.wxa-modal-content { padding: 8px 20px 24px; font-size: 15px; color: #666; white-space: pre-wrap; word-break: break-word; }\n.wxa-modal-input { width: calc(100% - 40px); margin: 0 20px 20px; padding: 8px; font-size: 15px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 4px; }\n.wxa-modal-actions { display: flex; border-top: 1px solid rgba(0,0,0,.1); }\n.wxa-modal-actions button { flex: 1; height: 50px; border: 0; background: none; font-size: 17px; font-weight: 600; cursor: pointer; }\n.wxa-modal-actions button + button { border-left: 1px solid rgba(0,0,0,.1); }\n.wxa-actionsheet { position: absolute; left: 0; right: 0; bottom: 0; background: #f7f7f7; border-radius: 12px 12px 0 0; overflow: hidden; pointer-events: auto; }\n.wxa-actionsheet-alert { padding: 16px; font-size: 13px; color: #888; text-align: center; background: #fff; }\n.wxa-actionsheet button { display: block; width: 100%; height: 56px; border: 0; border-top: 1px solid rgba(0,0,0,.06); background: #fff; font-size: 17px; cursor: pointer; }\n.wxa-actionsheet .wxa-actionsheet-cancel { margin-top: 8px; border-top: 0; }\n.wxa-picker { position: absolute; left: 0; right: 0; bottom: 0; padding-bottom: var(--wxa-safe-bottom, 0px); background: #fff; border-radius: 12px 12px 0 0; pointer-events: auto; user-select: none; }\n.wxa-picker-header { display: flex; align-items: center; height: 56px; padding: 0 8px; }\n.wxa-picker-header button { flex: none; border: 0; background: none; padding: 8px 12px; font-size: 17px; cursor: pointer; }\n.wxa-picker-cancel { color: rgba(0,0,0,.9); }\n.wxa-picker-confirm { color: #07c160; font-weight: 600; }\n.wxa-picker-title { flex: 1; overflow: hidden; font-size: 17px; font-weight: 600; text-align: center; white-space: nowrap; text-overflow: ellipsis; }\n.wxa-picker-body { position: relative; display: flex; height: ${PICKER_ITEM_HEIGHT * 5}px; margin: 0 16px 24px; }\n.wxa-picker-column { flex: 1; min-width: 0; overflow-y: auto; padding: ${PICKER_ITEM_HEIGHT * 2}px 0; box-sizing: border-box; scroll-snap-type: y mandatory; overscroll-behavior: contain; scrollbar-width: none; }\n.wxa-picker-column::-webkit-scrollbar { display: none; }\n.wxa-picker-item { height: ${PICKER_ITEM_HEIGHT}px; line-height: ${PICKER_ITEM_HEIGHT}px; padding: 0 4px; overflow: hidden; font-size: 17px; color: rgba(0,0,0,.4); text-align: center; white-space: nowrap; text-overflow: ellipsis; scroll-snap-align: center; cursor: pointer; }\n.wxa-picker-item.is-selected { color: rgba(0,0,0,.9); }\n.wxa-picker-indicator { position: absolute; left: 0; right: 0; top: ${PICKER_ITEM_HEIGHT * 2}px; height: ${PICKER_ITEM_HEIGHT}px; border-radius: 8px; background: rgba(0,0,0,.05); pointer-events: none; }\n.wxa-preview { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: #000; pointer-events: auto; }\n.wxa-preview-image { max-width: 100%; max-height: 100%; object-fit: contain; }\n.wxa-preview-position { position: absolute; top: 60px; left: 0; right: 0; color: #fff; font-size: 15px; text-align: center; pointer-events: none; }\n.wxa-preview button { position: absolute; top: 50%; width: 40px; height: 56px; margin-top: -28px; border: 0; border-radius: 8px; background: rgba(255,255,255,.15); color: #fff; font-size: 28px; cursor: pointer; }\n.wxa-preview .wxa-preview-prev { left: 8px; }\n.wxa-preview .wxa-preview-next { right: 8px; }\n.wxa-error { position: absolute; inset: 0; z-index: 20; overflow: auto; padding: 20px; background: #fff5f5; color: #c00; font: 12px/1.6 Menlo, monospace; white-space: pre-wrap; }\n.wxa-toolbar { display: flex; align-items: center; gap: 10px; padding: 4px 4px 4px 12px; border-radius: 999px; background: rgba(255,255,255,.7); box-shadow: 0 1px 2px rgba(15,23,42,.08); font-size: 12px; color: #555; }\n.wxa-toolbar button { border: 0; background: #111214; color: #fff; border-radius: 999px; padding: 4px 12px; font-size: 12px; cursor: pointer; }\n.wxa-toolbar .wxa-scale { min-width: 52px; background: #fff; color: #333; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); font-variant-numeric: tabular-nums; }\n.wxa-route { font-family: Menlo, monospace; }\n.wxa-notice { position: fixed; top: 16px; right: 16px; z-index: 100; display: flex; align-items: flex-start; gap: 10px; width: max-content; max-width: min(320px, calc(100vw - 32px)); padding: 12px 10px 12px 14px; box-sizing: border-box; border-radius: 12px; background: #fff; box-shadow: 0 0 0 1px rgba(15,23,42,.06), 0 12px 32px -8px rgba(15,23,42,.28); font-size: 13px; line-height: 20px; color: #555; animation: wxa-notice-in .18s ease-out; }\n.wxa-notice-icon { flex: none; width: 18px; height: 18px; margin-top: 1px; border-radius: 50%; background: #fa5151; color: #fff; font-size: 12px; font-weight: 700; line-height: 18px; text-align: center; }\n.wxa-notice-text { flex: 1; min-width: 0; word-break: break-word; text-wrap: pretty; }\n.wxa-notice-title { font-weight: 600; color: #111214; }\n.wxa-notice-close { flex: none; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%; background: none; color: #999; font-size: 16px; line-height: 20px; cursor: pointer; }\n.wxa-notice-close:hover { background: rgba(0,0,0,.06); color: #111214; }\n@keyframes wxa-spin { to { transform: rotate(360deg); } }\n@keyframes wxa-notice-in { from { opacity: 0; transform: translateY(-8px); } }\n`;\n","/**\n * 选择器弹层:从底部弹出,若干列可滚动的选项,中间一行是选中项\n *\n * 用户可以滚动到某一项,也可以直接点它。列之间的联动(日期的天数、省市区)不在这里,\n * 由调用方在 onColumnChange 里用 setColumn 换掉后面的列。\n */\n\nimport { element } from './dom';\nimport { PICKER_ITEM_HEIGHT } from './styles';\n\nexport interface PickerOptions {\n /** 每列的选项文字 */\n columns: string[][];\n /** 每列初始选中的下标 */\n current: number[];\n headerText?: string;\n /** 用户改变某列的选中项后调用;setColumn 引起的变化不会触发 */\n onColumnChange?: (column: number, index: number) => void;\n}\n\nexport interface PickerSession {\n /** 确定时为各列选中的下标,取消时为 null */\n result: Promise<number[] | null>;\n /** 替换某列的选项和选中项 */\n setColumn(column: number, items: string[], current: number): void;\n}\n\n/** 滚动停下多久后按位置确定选中项 */\nconst SCROLL_SETTLE_DELAY = 100;\n\nexport function openPicker(container: HTMLElement, options: PickerOptions): PickerSession {\n let resolve!: (value: number[] | null) => void;\n const result = new Promise<number[] | null>(done => {\n resolve = done;\n });\n\n const layer = element('div', 'wxa-picker-layer');\n const mask = element('div', 'wxa-mask is-dim');\n const sheet = element('div', 'wxa-picker');\n sheet.setAttribute('role', 'dialog');\n const header = element('div', 'wxa-picker-header');\n const cancel = element('button', 'wxa-picker-cancel', '取消');\n const confirm = element('button', 'wxa-picker-confirm', '确定');\n header.append(cancel, element('div', 'wxa-picker-title', options.headerText || ''), confirm);\n const body = element('div', 'wxa-picker-body');\n const columns = options.columns.map((_, index) => new PickerColumn(next => options.onColumnChange?.(index, next)));\n body.append(...columns.map(column => column.el), element('div', 'wxa-picker-indicator'));\n sheet.append(header, body);\n layer.append(mask, sheet);\n container.appendChild(layer);\n // 滚动位置要在元素进入文档后才能设置\n columns.forEach((column, index) => column.setItems(options.columns[index], options.current[index] ?? 0));\n\n const close = (value: number[] | null) => {\n layer.remove();\n resolve(value);\n };\n cancel.addEventListener('click', () => close(null));\n mask.addEventListener('click', () => close(null));\n confirm.addEventListener('click', () => {\n // 还在滚动中的列先按当前位置定下来,联动的列随之更新\n columns.forEach(column => column.settle());\n close(columns.map(column => column.index));\n });\n\n return {\n result,\n setColumn(column, items, current) {\n columns[column]?.setItems(items, current);\n }\n };\n}\n\nclass PickerColumn {\n readonly el = element('div', 'wxa-picker-column');\n index = 0;\n private items: HTMLElement[] = [];\n private settleTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(private readonly onUserChange: (index: number) => void) {\n this.el.addEventListener('scroll', () => {\n clearTimeout(this.settleTimer);\n this.settleTimer = setTimeout(() => this.settle(), SCROLL_SETTLE_DELAY);\n });\n this.el.addEventListener('click', event => {\n const item = (event.target as HTMLElement).closest<HTMLElement>('.wxa-picker-item');\n if (item) this.choose(Number(item.dataset.index));\n });\n }\n\n setItems(labels: string[], current: number) {\n this.items = labels.map((label, index) => {\n const item = element('div', 'wxa-picker-item', label);\n item.dataset.index = String(index);\n return item;\n });\n this.el.replaceChildren(...this.items);\n this.show(Math.min(Math.max(0, current), Math.max(0, labels.length - 1)));\n }\n\n /** 滚动停下后,选中停在中间那一行的项 */\n settle() {\n clearTimeout(this.settleTimer);\n if (!this.items.length) return;\n const index = Math.min(this.items.length - 1, Math.max(0, Math.round(this.el.scrollTop / PICKER_ITEM_HEIGHT)));\n this.choose(index);\n }\n\n private choose(index: number) {\n const changed = index !== this.index;\n this.show(index);\n if (changed) this.onUserChange(index);\n }\n\n private show(index: number) {\n this.items[this.index]?.classList.remove('is-selected');\n this.index = index;\n this.items[index]?.classList.add('is-selected');\n this.el.scrollTo({ top: index * PICKER_ITEM_HEIGHT, behavior: 'instant' });\n }\n}\n","/**\n * 模拟手机外壳:刘海、状态栏、导航栏、胶囊按钮、页面容器、tabBar 和系统弹层\n */\n\nimport type { DeviceProfile } from '../../types';\nimport { menuButtonRect, NAVIGATION_BAR_HEIGHT, TAB_BAR_HEIGHT } from '../api/system';\nimport { element } from './dom';\nimport { openImagePreview } from './ImagePreview';\nimport { openPicker, PickerOptions, PickerSession } from './Picker';\nimport { DEVICE_BEZEL, SHELL_CSS, STAGE_GAP, STAGE_PADDING } from './styles';\n\nexport interface NavigationState {\n title: string;\n backgroundColor: string;\n textStyle: string;\n showBack: boolean;\n custom: boolean;\n}\n\nexport interface TabBarConfig {\n color?: string;\n selectedColor?: string;\n backgroundColor?: string;\n borderStyle?: string;\n custom?: boolean;\n list: Array<{ pagePath: string; text?: string; iconPath?: string; selectedIconPath?: string }>;\n}\n\nexport interface SafeAreaInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport interface ToastOptions {\n title?: string;\n icon?: 'success' | 'error' | 'loading' | 'none';\n image?: string;\n duration?: number;\n mask?: boolean;\n}\n\nexport interface ModalOptions {\n title?: string;\n content?: string;\n showCancel?: boolean;\n cancelText?: string;\n cancelColor?: string;\n confirmText?: string;\n confirmColor?: string;\n editable?: boolean;\n placeholderText?: string;\n}\n\nexport interface ActionSheetOptions {\n alertText?: string;\n itemList: string[];\n itemColor?: string;\n}\n\ntype ScaleMode = 'fit' | '1';\n\nconst SCALE_STORAGE_KEY = 'wxa-runner:scale';\nconst MIN_SCALE = 0.5;\nconst NOTICE_DURATION = 6000;\n\n/** 手动打开时默认适应窗口;自动化环境默认 1:1,截图和视觉基线不随窗口大小变化 */\nfunction loadScaleMode(): ScaleMode {\n try {\n const saved = localStorage.getItem(SCALE_STORAGE_KEY);\n if (saved === 'fit' || saved === '1') return saved;\n } catch {\n // 存储不可用时用默认值\n }\n return navigator.webdriver ? '1' : 'fit';\n}\n\nexport class PhoneShell {\n readonly pages: HTMLElement;\n private readonly stage: HTMLElement;\n private readonly slot: HTMLElement;\n private readonly device: HTMLElement;\n private readonly toolbar: HTMLElement;\n private readonly scaleButton: HTMLButtonElement;\n private scaleMode = loadScaleMode();\n private readonly statusBar: HTMLElement;\n private readonly navBar: HTMLElement;\n private readonly capsule: HTMLElement;\n private readonly navTitle: HTMLElement;\n private readonly backButton: HTMLButtonElement;\n private readonly tabBar: HTMLElement;\n private readonly overlay: HTMLElement;\n private readonly routeLabel: HTMLElement;\n private toastEl: HTMLElement | null = null;\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n private noticeEl: HTMLElement | null = null;\n private noticeTimer: ReturnType<typeof setTimeout> | null = null;\n private tabBarConfig: TabBarConfig | null = null;\n private onTabTap: (pagePath: string, index: number) => void = () => undefined;\n private navigation: NavigationState = { title: '', backgroundColor: '#000', textStyle: 'white', showBack: false, custom: false };\n private tabBarVisible = false;\n\n constructor(root: HTMLElement, private readonly profile: DeviceProfile) {\n const style = document.createElement('style');\n style.textContent = SHELL_CSS;\n document.head.appendChild(style);\n\n // 刘海屏的状态栏比传统机型(20px)高,以此区分是否绘制刘海\n const hasNotch = profile.statusBarHeight > 20;\n const capsule = menuButtonRect(profile);\n root.innerHTML = `\n <div class=\"wxa-stage\">\n <div class=\"wxa-device-slot\">\n <div class=\"wxa-device${hasNotch ? ' has-notch' : ''}\" style=\"width:${profile.screenWidth}px;height:${profile.screenHeight}px;--wxa-safe-bottom:${profile.safeAreaBottom}px\">\n <div class=\"wxa-statusbar\" style=\"height:${profile.statusBarHeight}px\">\n <span class=\"wxa-statusbar-time\">9:41</span>\n <span class=\"wxa-statusbar-icons\">${STATUS_ICONS}</span>\n </div>\n <div class=\"wxa-navbar\">\n <button class=\"wxa-navbar-back\" title=\"返回\" aria-label=\"返回\">${BACK_ICON}</button>\n <span class=\"wxa-navbar-loading\"></span><span class=\"wxa-navbar-title\"></span>\n </div>\n <div class=\"wxa-pages\"></div>\n <div class=\"wxa-tabbar is-hidden\"></div>\n <div class=\"wxa-capsule\" style=\"top:${capsule.top}px;left:${capsule.left}px;width:${capsule.width}px;height:${capsule.height}px\">\n <span class=\"wxa-capsule-more\">${MORE_ICON}</span><span class=\"wxa-capsule-close\">${CLOSE_ICON}</span>\n </div>\n <div class=\"wxa-overlay\"></div>\n ${hasNotch ? '<div class=\"wxa-notch\"></div>' : ''}\n ${profile.safeAreaBottom ? '<div class=\"wxa-home-indicator\"></div>' : ''}\n </div>\n </div>\n <div class=\"wxa-toolbar\">\n <span class=\"wxa-route\"></span><button class=\"wxa-scale\"></button><button class=\"wxa-reload\">刷新</button>\n </div>\n </div>`;\n\n this.stage = root.querySelector('.wxa-stage')!;\n this.slot = root.querySelector('.wxa-device-slot')!;\n this.device = root.querySelector('.wxa-device')!;\n this.toolbar = root.querySelector('.wxa-toolbar')!;\n this.scaleButton = root.querySelector('.wxa-scale')!;\n this.statusBar = root.querySelector('.wxa-statusbar')!;\n this.navBar = root.querySelector('.wxa-navbar')!;\n this.capsule = root.querySelector('.wxa-capsule')!;\n this.navTitle = root.querySelector('.wxa-navbar-title')!;\n this.backButton = root.querySelector('.wxa-navbar-back')!;\n this.pages = root.querySelector('.wxa-pages')!;\n this.tabBar = root.querySelector('.wxa-tabbar')!;\n this.overlay = root.querySelector('.wxa-overlay')!;\n this.routeLabel = root.querySelector('.wxa-route')!;\n root.querySelector('.wxa-reload')!.addEventListener('click', () => location.reload());\n\n this.scaleButton.addEventListener('click', () => {\n this.scaleMode = this.scaleMode === 'fit' ? '1' : 'fit';\n try {\n localStorage.setItem(SCALE_STORAGE_KEY, this.scaleMode);\n } catch {\n // 只影响记住选择\n }\n this.applyScale();\n });\n window.addEventListener('resize', () => this.applyScale());\n this.applyScale();\n }\n\n /**\n * 窗口放不下时整体缩小手机。只用 transform:iframe 内的布局、字号、坐标都不变,\n * Playwright 也能正确换算点击位置;CSS zoom 会让 Playwright 点击错位。\n * transform 不改变占位,所以由外层 slot 按缩放后的尺寸占位。\n */\n private applyScale() {\n const width = this.profile.screenWidth + DEVICE_BEZEL * 2;\n const height = this.profile.screenHeight + DEVICE_BEZEL * 2;\n let scale = 1;\n if (this.scaleMode === 'fit') {\n const availableWidth = window.innerWidth - STAGE_PADDING * 2;\n const availableHeight = window.innerHeight - STAGE_PADDING * 2 - STAGE_GAP - this.toolbar.offsetHeight;\n const fit = Math.floor(Math.min(availableWidth / width, availableHeight / height) * 100) / 100;\n scale = Math.min(1, Math.max(MIN_SCALE, fit));\n }\n this.slot.style.width = `${width * scale}px`;\n this.slot.style.height = `${height * scale}px`;\n this.device.style.left = this.device.style.top = `${DEVICE_BEZEL * scale}px`;\n this.device.style.transform = scale === 1 ? '' : `scale(${scale})`;\n this.scaleButton.textContent = `${Math.round(scale * 100)}%`;\n this.scaleButton.title = this.scaleMode === 'fit' ? '适应窗口,点击切换为实际大小' : '实际大小,点击切换为适应窗口';\n }\n\n onBack(handler: () => void) {\n this.backButton.addEventListener('click', handler);\n }\n\n setTabBar(config: TabBarConfig | undefined, onTap: (pagePath: string, index: number) => void) {\n this.tabBarConfig = config && config.list?.length && !config.custom ? config : null;\n this.onTabTap = onTap;\n }\n\n setRoute(route: string) {\n this.routeLabel.textContent = route;\n }\n\n setNavigation(state: Partial<NavigationState>) {\n this.navigation = { ...this.navigation, ...state };\n const { title, backgroundColor, textStyle, showBack, custom } = this.navigation;\n const color = textStyle === 'black' ? '#000' : '#fff';\n\n this.navTitle.textContent = title;\n this.backButton.style.visibility = showBack ? 'visible' : 'hidden';\n this.navBar.classList.toggle('is-hidden', custom);\n this.navBar.style.background = backgroundColor;\n this.navBar.style.color = color;\n // 自定义导航栏时页面从屏幕顶部开始绘制,状态栏浮在页面上;\n // 与微信一致,状态栏文字和胶囊配色仍跟随 navigationBarTextStyle\n this.statusBar.style.background = custom ? 'transparent' : backgroundColor;\n this.statusBar.style.color = color;\n this.capsule.classList.toggle('is-light', textStyle !== 'black');\n this.statusBar.style.position = custom ? 'absolute' : '';\n this.statusBar.style.left = this.statusBar.style.right = custom ? '0' : '';\n this.statusBar.style.zIndex = custom ? '5' : '';\n }\n\n getNavigation(): NavigationState {\n return { ...this.navigation };\n }\n\n setNavigationLoading(loading: boolean) {\n this.navBar.classList.toggle('is-loading', loading);\n }\n\n /** 该页面是否显示原生 tabBar(自定义 tabBar 不算) */\n hasTabBar(pagePath: string): boolean {\n return !!this.tabBarConfig?.list.some(item => item.pagePath === pagePath);\n }\n\n /**\n * 页面窗口里 env(safe-area-inset-*) 的取值:窗口贴着屏幕边缘的一侧才有安全区。\n * 默认导航栏下窗口在导航栏下方,tabBar 页面的窗口止于 tabBar 上方。\n */\n safeAreaInsetsFor(pagePath: string, navigation: Pick<NavigationState, 'custom'>): SafeAreaInsets {\n return {\n top: navigation.custom ? this.profile.statusBarHeight : 0,\n right: 0,\n bottom: this.hasTabBar(pagePath) ? 0 : this.profile.safeAreaBottom,\n left: 0\n };\n }\n\n /** 当前页面是 tabBar 页面时传入它的路径,否则传 null */\n renderTabBar(selectedPath: string | null) {\n const config = this.tabBarConfig;\n this.tabBarVisible = selectedPath !== null && this.hasTabBar(selectedPath);\n this.tabBar.classList.toggle('is-hidden', !this.tabBarVisible);\n if (!config || !this.tabBarVisible) return;\n\n this.tabBar.style.background = config.backgroundColor || '#f7f7f7';\n this.tabBar.style.borderTopColor = config.borderStyle === 'white' ? 'rgba(255,255,255,.3)' : 'rgba(0,0,0,.1)';\n this.tabBar.innerHTML = '';\n config.list.forEach((item, index) => {\n const selected = item.pagePath === selectedPath;\n const el = document.createElement('div');\n el.className = 'wxa-tabbar-item' + (selected ? ' is-selected' : '');\n el.dataset.pagePath = item.pagePath;\n el.style.color = selected ? (config.selectedColor || '#07c160') : (config.color || '#7a7e83');\n const icon = selected ? item.selectedIconPath || item.iconPath : item.iconPath;\n if (icon) {\n const img = document.createElement('img');\n img.src = '/' + icon.replace(/^\\//, '');\n el.appendChild(img);\n }\n const text = document.createElement('span');\n text.textContent = item.text || '';\n el.appendChild(text);\n el.addEventListener('click', () => this.onTabTap(item.pagePath, index));\n this.tabBar.appendChild(el);\n });\n }\n\n /** 页面可用高度,与 getSystemInfo().windowHeight 对应;tabBar 会连同底部安全区一起占掉 */\n windowHeight(): number {\n return this.profile.screenHeight\n - this.screenTop()\n - (this.tabBarVisible ? TAB_BAR_HEIGHT + this.profile.safeAreaBottom : 0);\n }\n\n /** 页面窗口顶部到屏幕顶部的距离,与 getWindowInfo().screenTop 对应 */\n screenTop(): number {\n return this.navigation.custom ? 0 : this.profile.statusBarHeight + NAVIGATION_BAR_HEIGHT;\n }\n\n showToast(options: ToastOptions) {\n this.hideToast();\n const icon = options.image ? 'image' : options.icon || 'success';\n const wrapper = document.createElement('div');\n if (options.mask) wrapper.appendChild(maskElement(false));\n\n const toast = document.createElement('div');\n toast.className = 'wxa-toast' + (icon === 'none' ? '' : ' has-icon');\n toast.setAttribute('role', 'alert');\n if (icon === 'loading') {\n toast.appendChild(element('div', 'wxa-toast-spinner'));\n } else if (icon === 'image') {\n const img = document.createElement('img');\n img.src = options.image!;\n img.width = img.height = 40;\n toast.appendChild(img);\n } else if (icon !== 'none') {\n toast.appendChild(element('div', 'wxa-toast-icon', icon === 'error' ? '✕' : '✓'));\n }\n toast.appendChild(element('div', 'wxa-toast-title', options.title || ''));\n wrapper.appendChild(toast);\n\n this.overlay.appendChild(wrapper);\n this.toastEl = wrapper;\n if (icon !== 'loading' || options.duration) {\n this.toastTimer = setTimeout(() => this.hideToast(), options.duration ?? 1500);\n }\n }\n\n hideToast() {\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toastTimer = null;\n this.toastEl?.remove();\n this.toastEl = null;\n }\n\n showModal(options: ModalOptions): Promise<{ confirm: boolean; cancel: boolean; content?: string }> {\n return new Promise(resolve => {\n const wrapper = document.createElement('div');\n wrapper.appendChild(maskElement(true));\n const modal = element('div', 'wxa-modal');\n modal.setAttribute('role', 'dialog');\n if (options.title) modal.appendChild(element('div', 'wxa-modal-title', options.title));\n if (options.content && !options.editable) modal.appendChild(element('div', 'wxa-modal-content', options.content));\n\n let input: HTMLInputElement | null = null;\n if (options.editable) {\n input = document.createElement('input');\n input.className = 'wxa-modal-input';\n input.value = options.content || '';\n input.placeholder = options.placeholderText || '';\n modal.appendChild(input);\n }\n\n const actions = element('div', 'wxa-modal-actions');\n const close = (confirm: boolean) => {\n wrapper.remove();\n resolve({ confirm, cancel: !confirm, ...(options.editable ? { content: input!.value } : {}) });\n };\n if (options.showCancel !== false) {\n const cancel = element('button', 'wxa-modal-cancel', options.cancelText || '取消');\n cancel.style.color = options.cancelColor || '#000';\n cancel.addEventListener('click', () => close(false));\n actions.appendChild(cancel);\n }\n const confirm = element('button', 'wxa-modal-confirm', options.confirmText || '确定');\n confirm.style.color = options.confirmColor || '#576b95';\n confirm.addEventListener('click', () => close(true));\n actions.appendChild(confirm);\n modal.appendChild(actions);\n\n wrapper.appendChild(modal);\n this.overlay.appendChild(wrapper);\n });\n }\n\n showActionSheet(options: ActionSheetOptions): Promise<number | null> {\n return new Promise(resolve => {\n const wrapper = document.createElement('div');\n const mask = maskElement(true);\n const sheet = element('div', 'wxa-actionsheet');\n const close = (index: number | null) => {\n wrapper.remove();\n resolve(index);\n };\n\n if (options.alertText) sheet.appendChild(element('div', 'wxa-actionsheet-alert', options.alertText));\n options.itemList.forEach((text, index) => {\n const button = element('button', 'wxa-actionsheet-item', text);\n button.style.color = options.itemColor || '#000';\n button.addEventListener('click', () => close(index));\n sheet.appendChild(button);\n });\n const cancel = element('button', 'wxa-actionsheet-cancel', '取消');\n cancel.addEventListener('click', () => close(null));\n sheet.appendChild(cancel);\n mask.addEventListener('click', () => close(null));\n\n wrapper.append(mask, sheet);\n this.overlay.appendChild(wrapper);\n });\n }\n\n showPicker(options: PickerOptions): PickerSession {\n return openPicker(this.overlay, options);\n }\n\n showImagePreview(urls: string[], current: number) {\n openImagePreview(this.overlay, urls, current);\n }\n\n /**\n * 在手机外面提示 wxa-runner 自身的问题(如真实登录失败),不混进小程序的界面。\n * 同一时间只显示一条,新的替换旧的:业务代码反复重试时不会堆满屏幕\n */\n showNotice(title: string, message: string) {\n this.hideNotice();\n const notice = element('div', 'wxa-notice');\n notice.setAttribute('role', 'alert');\n const text = element('div', 'wxa-notice-text');\n text.append(element('div', 'wxa-notice-title', title), element('div', 'wxa-notice-message', message));\n const close = element('button', 'wxa-notice-close', '×');\n close.setAttribute('aria-label', '关闭');\n close.addEventListener('click', () => this.hideNotice());\n notice.append(element('span', 'wxa-notice-icon', '!'), text, close);\n\n this.stage.appendChild(notice);\n this.noticeEl = notice;\n this.noticeTimer = setTimeout(() => this.hideNotice(), NOTICE_DURATION);\n }\n\n hideNotice() {\n if (this.noticeTimer) clearTimeout(this.noticeTimer);\n this.noticeTimer = null;\n this.noticeEl?.remove();\n this.noticeEl = null;\n }\n\n showError(message: string) {\n this.clearError();\n const el = element('div', 'wxa-error', message);\n this.device.appendChild(el);\n }\n\n clearError() {\n this.device.querySelector('.wxa-error')?.remove();\n }\n}\n\nfunction maskElement(dim: boolean): HTMLElement {\n return element('div', 'wxa-mask' + (dim ? ' is-dim' : ''));\n}\n\nconst BACK_ICON = '<svg width=\"12\" height=\"20\" viewBox=\"0 0 12 20\"><path d=\"M10 2 2 10l8 8\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>';\n\nconst MORE_ICON = '<svg width=\"22\" height=\"8\" viewBox=\"0 0 22 8\" fill=\"currentColor\"><circle cx=\"3.5\" cy=\"4\" r=\"2.3\"/><circle cx=\"11\" cy=\"4\" r=\"3.3\"/><circle cx=\"18.5\" cy=\"4\" r=\"2.3\"/></svg>';\n\nconst CLOSE_ICON = '<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\"><circle cx=\"10\" cy=\"10\" r=\"8.2\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"/><circle cx=\"10\" cy=\"10\" r=\"3.4\" fill=\"currentColor\"/></svg>';\n\nconst STATUS_ICONS = [\n // 信号\n '<svg width=\"17\" height=\"11\" viewBox=\"0 0 17 11\" fill=\"currentColor\"><rect x=\"0\" y=\"7\" width=\"3\" height=\"4\" rx=\".8\"/><rect x=\"4.6\" y=\"5\" width=\"3\" height=\"6\" rx=\".8\"/><rect x=\"9.2\" y=\"2.6\" width=\"3\" height=\"8.4\" rx=\".8\"/><rect x=\"13.8\" y=\"0\" width=\"3\" height=\"11\" rx=\".8\"/></svg>',\n // Wi-Fi\n '<svg width=\"16\" height=\"12\" viewBox=\"0 0 16 12\" fill=\"currentColor\"><path d=\"M8 11.2L5.45 8.65A3.6 3.6 0 0 1 10.55 8.65ZM2.77 5.97A7.4 7.4 0 0 1 13.23 5.97L11.68 7.52A5.2 5.2 0 0 0 4.32 7.52ZM0.08 3.28A11.2 11.2 0 0 1 15.92 3.28L14.36 4.84A9 9 0 0 0 1.64 4.84Z\"/></svg>',\n // 电池\n '<svg width=\"25\" height=\"12\" viewBox=\"0 0 25 12\"><rect x=\".5\" y=\".5\" width=\"21.5\" height=\"11\" rx=\"3.2\" fill=\"none\" stroke=\"currentColor\" stroke-opacity=\".4\"/><rect x=\"2\" y=\"2\" width=\"18.5\" height=\"8\" rx=\"1.8\" fill=\"currentColor\"/><path d=\"M23.4 4v4a2.2 2.2 0 0 0 0-4z\" fill=\"currentColor\" fill-opacity=\".45\"/></svg>'\n].join('');\n","/**\n * 宿主:管理逻辑层 iframe 和各页面的渲染层 iframe\n *\n * 宿主不实现页面生命周期——它只维护页面栈并在路由变化时派发 onAppRoute,\n * App/Page 的生命周期全部由官方基础库根据这个事件驱动。\n */\n\nimport type { AppInfo, FrameBridge, FrameKind, HostApi, InvokeCallback } from '../types';\nimport { ApiContext, ApiRegistry, ApiResult, fail, ok } from './api/registry';\nimport { createAudioApis } from './api/audio';\nimport { createFileSystemApis } from './api/fs';\nimport { createLibFileApis } from './api/libFiles';\nimport { createMapApis, MapOperations } from './api/map';\nimport { createMediaApis } from './api/media';\nimport { createMiscApis } from './api/misc';\nimport { createNetworkApis, RequestLog } from './api/network';\nimport { createPickerApis, fetchRegionData } from './api/picker';\nimport { RequestRoutes } from './api/routes';\nimport { createSavedFileApis } from './api/savedFiles';\nimport { createStorageApis, MiniProgramStorage } from './api/storage';\nimport { createSystemApis } from './api/system';\nimport { tempFileRootPath } from './api/tempFiles';\nimport { createUiApis } from './api/ui';\nimport { createWebViewApis } from './api/webView';\nimport { PageStack } from './PageStack';\nimport { PageView } from './PageView';\nimport { cloneInto, cloneNativeInto } from './realm';\nimport { chooseFiles, hasUserActivation } from './ui/fileChooser';\nimport { NavigationState, PhoneShell } from './ui/PhoneShell';\n\nexport type OpenType = 'appLaunch' | 'navigateTo' | 'navigateBack' | 'redirectTo' | 'reLaunch' | 'switchTab';\n\nexport interface LaunchTarget {\n path: string;\n query: Record<string, string>;\n}\n\nexport interface FrameError {\n kind: FrameKind;\n webviewId: number;\n message: string;\n stack?: string;\n /** 调用了未实现的原生 API 时为 API 名称 */\n api?: string;\n}\n\nconst ROUTE_DONE_DELAY = 300;\nconst PAGE_LOAD_TIMEOUT = 15000;\n\nexport class Host implements HostApi {\n readonly device;\n readonly errors: FrameError[] = [];\n /** 小程序发出的 wx.request */\n readonly requests = new RequestLog();\n readonly api = new ApiRegistry(context => this.reportUnimplemented(context));\n readonly shell: PhoneShell;\n readonly storage: MiniProgramStorage;\n /** setup 和测试 API 声明的请求拦截 */\n readonly routes = new RequestRoutes();\n private readonly mapOperations = new MapOperations((webviewId, event, data) => this.publishToPages(event, data, [webviewId]));\n private service: { win: Window; bridge: FrameBridge } | null = null;\n /** 新版基础库的业务子上下文;旧版基础库业务代码直接在逻辑层 iframe 里 */\n private appContext: Window | null = null;\n private serviceLoaded!: () => void;\n private readonly serviceReady = new Promise<void>(resolve => {\n this.serviceLoaded = resolve;\n });\n private readonly pages = new Map<number, PageView>();\n private readonly tabPages = new Map<string, PageView>();\n private readonly stack = new PageStack<PageView>();\n private readonly tabPaths: Set<string>;\n private nextWebviewId = 1;\n private routeChain: Promise<unknown> = Promise.resolve();\n private routeListeners: Array<(page: PageView, openType: OpenType) => void> = [];\n\n constructor(readonly info: AppInfo, root: HTMLElement) {\n this.device = info.device;\n this.shell = new PhoneShell(root, info.device);\n this.tabPaths = new Set((info.wxConfig.tabBar?.list || []).map((item: any) => stripHtml(item.pagePath)));\n this.storage = new MiniProgramStorage(window.localStorage, info.appid);\n\n const tabBar = info.wxConfig.tabBar\n ? { ...info.wxConfig.tabBar, list: info.wxConfig.tabBar.list.map((item: any) => ({ ...item, pagePath: stripHtml(item.pagePath) })) }\n : undefined;\n this.shell.setTabBar(tabBar, pagePath => this.enqueueRoute(() => this.switchTab(pagePath)));\n this.shell.onBack(() => this.enqueueRoute(() => this.navigateBack(1)));\n\n this.registerApis();\n }\n\n async start(target: LaunchTarget) {\n const frame = document.createElement('iframe');\n frame.name = 'wxa-appservice';\n frame.style.display = 'none';\n const params = new URLSearchParams({ v: String(this.info.version), path: target.path, query: new URLSearchParams(target.query).toString() });\n frame.src = `/__wxa__/appservice.html?${params}`;\n document.body.appendChild(frame);\n\n document.addEventListener('visibilitychange', () => {\n const page = this.currentPage();\n if (!page) return;\n const event = document.hidden ? 'onAppEnterBackground' : 'onAppEnterForeground';\n this.emitToService(event, { path: page.path, query: page.query, scene: 1001, referrerInfo: {} });\n });\n\n await this.serviceReady;\n await this.enqueueRoute(() => this.launch(target));\n }\n\n // ---------------------------------------------------------------------------\n // HostApi:供 iframe 内的桥调用\n // ---------------------------------------------------------------------------\n\n registerFrame(kind: FrameKind, win: Window, bridge: FrameBridge, webviewId: number) {\n if (kind === 'service') {\n this.service = { win, bridge };\n } else {\n this.pages.get(webviewId)?.attach(win, bridge);\n }\n }\n\n registerAppContext(win: Window | null) {\n this.appContext = win;\n }\n\n frameLoaded(kind: FrameKind, webviewId: number) {\n if (kind === 'service') this.serviceLoaded();\n else this.pages.get(webviewId)?.loaded();\n }\n\n invoke(kind: FrameKind, win: Window, api: string, args: unknown, callback?: InvokeCallback) {\n const webviewId = kind === 'webview' ? this.webviewIdOf(win) : this.currentPage()?.id ?? 0;\n const result = this.api.invoke(api, args, { api, from: kind, webviewId });\n const deliver = (res: ApiResult | string) => {\n if (callback) callback(cloneNativeInto(kind === 'service' ? this.serviceWindow()! : win, res));\n };\n\n if (result && typeof (result as Promise<ApiResult>).then === 'function') {\n (result as Promise<ApiResult | string>).then(deliver);\n } else {\n deliver(result as ApiResult | string);\n }\n }\n\n publish(kind: FrameKind, win: Window, event: string, data: unknown, webviewIds?: number[]) {\n if (kind === 'service') {\n this.publishToPages(event, data, webviewIds);\n return;\n }\n if (event === 'operateMapCallback' && this.mapOperations.receive(data)) return;\n\n const fromId = this.webviewIdOf(win);\n const service = this.service;\n if (!service) return;\n const payload = this.cloneForService(data);\n queueMicrotask(() => service.bridge.__dispatchSub(event, payload, fromId));\n }\n\n /** 不指定目标时发给所有页面:旧版 canvas 的绘制指令就是这样发的,由 canvasNumber 找到对应画布 */\n private publishToPages(event: string, data: unknown, webviewIds?: number[]) {\n const targets = webviewIds?.length ? webviewIds.map(id => this.pages.get(Number(id))) : this.livePages();\n const message = event === 'canvasActionsChanged' ? withDrawableImages(data) : data;\n for (const page of targets) {\n page?.dispatch((bridge, target) => {\n const payload = cloneInto(target, message);\n queueMicrotask(() => bridge.__dispatchSub(event, payload, 0));\n });\n }\n }\n\n reportError(kind: FrameKind, webviewId: number, error: unknown) {\n // 错误对象来自 iframe,跨 realm 的 instanceof Error 不成立;DOMException 等也不是 Error 的实例\n const err = typeof (error as Error | null)?.message === 'string' ? error as Error : null;\n this.errors.push({\n kind,\n webviewId,\n message: err ? err.message : String(error),\n stack: typeof err?.stack === 'string' ? err.stack : undefined\n });\n }\n\n /**\n * 业务代码只运行在逻辑层,所以只记逻辑层调用、名字在 wx 上的 API,每个 API 一次。\n * 其余是基础库内部调用的原生接口(如 getPermissionBytes),业务既没调用也 mock 不了\n */\n private reportUnimplemented({ api, from }: ApiContext) {\n const wx = (this.serviceWindow() as any)?.wx;\n if (from !== 'service' || typeof wx?.[api] !== 'function') return;\n if (this.errors.some(error => error.api === api)) return;\n this.errors.push({\n kind: 'service',\n webviewId: 0,\n api,\n message: `wx.${api} 尚未实现,返回了默认成功。可以用 mock 覆盖,启动阶段就调用的要在 setup 里 mock`\n });\n }\n\n // ---------------------------------------------------------------------------\n // 路由\n // ---------------------------------------------------------------------------\n\n currentPage(): PageView | undefined {\n return this.stack.current();\n }\n\n pageStack(): PageView[] {\n return this.stack.entries();\n }\n\n /** 所有活着的页面:页面栈加上隐藏中的 tabBar 页面 */\n livePages(): PageView[] {\n return [...this.pages.values()];\n }\n\n /** 业务代码所在的 window:getCurrentPages / wx 等在它上面 */\n serviceWindow(): Window | null {\n return this.appContext ?? this.service?.win ?? null;\n }\n\n /**\n * 交给逻辑层的值属于业务代码所在的全局环境,而不是逻辑层 iframe:新版基础库不一定在业务子上下文里\n * 重建这些值,属于别的 iframe 的对象在业务代码里 instanceof 不成立,setData 也会把这样的数组当成普通对象\n */\n private cloneForService<T>(value: T): T {\n return cloneInto(this.serviceWindow()!, value);\n }\n\n onRoute(listener: (page: PageView, openType: OpenType) => void) {\n this.routeListeners.push(listener);\n }\n\n /** 路由操作串行执行,避免连续跳转时页面栈错乱 */\n enqueueRoute<T>(operation: () => Promise<T>): Promise<T> {\n const run = this.routeChain.then(operation, operation);\n this.routeChain = run.catch(() => undefined);\n return run;\n }\n\n private async launch(target: LaunchTarget) {\n const page = await this.openPage(target.path, target.query);\n this.stack.reset(page);\n this.activate(page, 'appLaunch');\n }\n\n async navigateTo(url: string): Promise<ApiResult> {\n if (!this.stack.canPush()) return fail('navigateTo', 'webview count limit exceed');\n const { path, query } = this.resolveUrl(url);\n if (this.tabPaths.has(path)) return fail('navigateTo', 'can not navigateTo a tabbar page');\n if (!this.hasPage(path)) return fail('navigateTo', `page \"${path}\" is not found`);\n\n const page = await this.openPage(path, query);\n this.stack.push(page);\n this.activate(page, 'navigateTo');\n return ok('navigateTo', { webviewId: page.id });\n }\n\n async navigateBack(delta: number): Promise<ApiResult> {\n if (this.stack.size <= 1) return fail('navigateBack', 'cannot navigate back at first page.');\n this.stack.pop(delta).forEach(page => this.closePage(page));\n this.activate(this.currentPage()!, 'navigateBack');\n return ok('navigateBack');\n }\n\n async redirectTo(url: string): Promise<ApiResult> {\n const { path, query } = this.resolveUrl(url);\n if (this.tabPaths.has(path)) return fail('redirectTo', 'can not redirectTo a tabbar page');\n if (!this.hasPage(path)) return fail('redirectTo', `page \"${path}\" is not found`);\n\n const page = await this.openPage(path, query);\n const previous = this.stack.replaceTop(page);\n if (previous) this.closePage(previous);\n this.activate(page, 'redirectTo');\n return ok('redirectTo');\n }\n\n async reLaunch(url: string): Promise<ApiResult> {\n const { path, query } = this.resolveUrl(url);\n if (!this.hasPage(path)) return fail('reLaunch', `page \"${path}\" is not found`);\n\n const page = await this.openPage(path, query, { reuseTab: false });\n this.stack.reset(page).forEach(previous => this.closePage(previous, { keepTab: false }));\n for (const [tabPath, tabPage] of this.tabPages) {\n if (tabPage !== page) {\n this.closePage(tabPage, { keepTab: false });\n this.tabPages.delete(tabPath);\n }\n }\n this.activate(page, 'reLaunch');\n return ok('reLaunch');\n }\n\n async switchTab(url: string): Promise<ApiResult> {\n const { path } = this.resolveUrl(url);\n if (!this.tabPaths.has(path)) return fail('switchTab', 'can not switch to no-tabBar page');\n if (this.currentPage()?.path === path && this.stack.size === 1) return ok('switchTab');\n\n const page = await this.openPage(path, {});\n this.stack.reset(page).forEach(previous => this.closePage(previous));\n this.activate(page, 'switchTab');\n return ok('switchTab');\n }\n\n private async openPage(path: string, query: Record<string, string>, options = { reuseTab: true }): Promise<PageView> {\n const isTab = this.tabPaths.has(path);\n if (isTab && options.reuseTab && this.tabPages.has(path)) {\n return this.tabPages.get(path)!;\n }\n\n const page = new PageView(\n this.nextWebviewId++,\n path,\n query,\n this.shell.pages,\n this.info.version,\n this.navigationFor(path)\n );\n // 渲染层注册桥时(基础库加载前)写入,首屏就按正确的安全区排版\n page.setSafeAreaInsets(this.shell.safeAreaInsetsFor(path, page.navigation));\n this.pages.set(page.id, page);\n if (isTab) this.tabPages.set(path, page);\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<void>(resolve => {\n timer = setTimeout(() => {\n console.error(`[wxa-runner] 页面 ${path} 的渲染层 ${PAGE_LOAD_TIMEOUT}ms 内没有加载完成,请检查控制台报错`);\n resolve();\n }, PAGE_LOAD_TIMEOUT);\n });\n await Promise.race([page.ready, timedOut]);\n clearTimeout(timer);\n return page;\n }\n\n private closePage(page: PageView, options = { keepTab: true }) {\n if (options.keepTab && this.tabPaths.has(page.path) && this.tabPages.get(page.path) === page) {\n page.hide();\n return;\n }\n if (this.tabPages.get(page.path) === page) this.tabPages.delete(page.path);\n this.pages.delete(page.id);\n page.destroy();\n }\n\n private activate(page: PageView, openType: OpenType) {\n for (const other of this.pages.values()) {\n if (other !== page) other.hide();\n }\n page.show();\n\n page.navigation = { ...page.navigation, showBack: this.stack.size > 1 };\n this.shell.setNavigation(page.navigation);\n this.shell.renderTabBar(this.tabPaths.has(page.path) ? page.path : null);\n this.shell.setRoute(page.url);\n this.updateLocation(page);\n\n const data = { path: page.path, query: page.query, openType, webviewId: page.id };\n this.emitToService('onAppRoute', data, page.id);\n setTimeout(() => {\n // 期间又发生了路由时,基础库会把迟到的 routeDone 当作错误\n if (this.currentPage() === page) this.emitToService('onAppRouteDone', data, page.id);\n }, ROUTE_DONE_DELAY);\n this.routeListeners.forEach(listener => listener(page, openType));\n }\n\n /** 宿主地址栏同步为当前页面,刷新后可回到同一页面 */\n private updateLocation(page: PageView) {\n const params = new URLSearchParams(location.search);\n params.set('path', page.path);\n for (const key of [...params.keys()]) {\n if (key !== 'path') params.delete(key);\n }\n for (const [key, value] of Object.entries(page.query)) params.set(key, value);\n history.replaceState(null, '', `${location.pathname}?${params}`);\n }\n\n private navigationFor(path: string): NavigationState {\n const window = {\n ...this.info.wxConfig.global?.window,\n ...this.info.wxConfig.page?.[path + '.html']?.window\n };\n return {\n title: window.navigationBarTitleText || '',\n backgroundColor: window.navigationBarBackgroundColor || '#000000',\n textStyle: window.navigationBarTextStyle === 'black' ? 'black' : 'white',\n showBack: false,\n custom: window.navigationStyle === 'custom'\n };\n }\n\n private hasPage(path: string): boolean {\n return this.info.pages.includes(path);\n }\n\n /**\n * 基础库调用路由 API 前已经把相对路径解析成根路径并加上 .html(如 \"pages/a/a.html?id=1\"),\n * 这里只做格式归一。\n */\n resolveUrl(url: string): { path: string; query: Record<string, string> } {\n const [rawPath, rawQuery = ''] = String(url || '').split('?');\n const path = stripHtml(rawPath.replace(/^\\/+/, ''));\n return { path, query: Object.fromEntries(new URLSearchParams(rawQuery)) };\n }\n\n // ---------------------------------------------------------------------------\n // 事件\n // ---------------------------------------------------------------------------\n\n emitToService(event: string, data: unknown, webviewId?: number) {\n const service = this.service;\n if (!service) return;\n const payload = cloneNativeInto(this.serviceWindow()!, data);\n queueMicrotask(() => service.bridge.__dispatchOn(event, payload, webviewId));\n }\n\n /** 派发给渲染层的原生事件(渲染层里 WeixinJSBridge.on 收到) */\n emitToWebview(webviewId: number, event: string, data: unknown) {\n this.pages.get(webviewId)?.dispatch((bridge, target) => {\n const payload = cloneNativeInto(target, data);\n queueMicrotask(() => bridge.__dispatchOn(event, payload, webviewId));\n });\n }\n\n private webviewIdOf(win: Window): number {\n for (const page of this.pages.values()) {\n if (page.win === win) return page.id;\n }\n return 0;\n }\n\n private updateNavigation(state: Partial<NavigationState>) {\n const page = this.currentPage();\n if (!page) return;\n page.navigation = { ...page.navigation, ...Object.fromEntries(Object.entries(state).filter(([, v]) => v !== undefined)) };\n this.shell.setNavigation(page.navigation);\n }\n\n private registerApis() {\n const routeApi = (handler: (args: any) => Promise<ApiResult>) =>\n (args: any) => this.enqueueRoute(() => handler(args));\n\n this.api.register({\n navigateTo: routeApi(args => this.navigateTo(args.url)),\n navigateBack: routeApi(args => this.navigateBack(args.delta || 1)),\n redirectTo: routeApi(args => this.redirectTo(args.url)),\n reLaunch: routeApi(args => this.reLaunch(args.url)),\n switchTab: routeApi(args => this.switchTab(args.url)),\n ...createStorageApis(this.storage),\n ...createSavedFileApis(this.storage),\n ...createFileSystemApis(),\n ...createSystemApis({\n device: this.device,\n baseLibVersion: this.info.baseLibVersion,\n windowHeight: () => this.shell.windowHeight(),\n screenTop: () => this.shell.screenTop()\n }),\n ...createNetworkApis({\n emit: (event, data) => this.emitToService(event, data),\n defaultTimeout: () => this.info.wxConfig.networkTimeout?.request || 60000,\n routes: this.routes,\n onRequest: request => this.requests.add(request)\n }),\n ...createAudioApis({ emit: (event, data) => this.emitToService(event, data) }),\n ...createMapApis({ registry: this.api, operations: this.mapOperations }),\n ...createLibFileApis({ windowOf: webviewId => this.pages.get(webviewId)?.win }),\n ...createUiApis({ shell: this.shell, updateNavigation: state => this.updateNavigation(state) }),\n ...createMediaApis({\n showActionSheet: options => this.shell.showActionSheet(options),\n chooseFiles,\n hasUserActivation,\n showImagePreview: (urls, current) => this.shell.showImagePreview(urls, current)\n }),\n ...createPickerApis({\n showPicker: options => this.shell.showPicker(options),\n emitToWebview: (webviewId, event, data) => this.emitToWebview(webviewId, event, data),\n loadRegionData: fetchRegionData\n }),\n ...createWebViewApis({\n documentOf: webviewId => this.pages.get(webviewId)?.win?.document,\n emitToWebview: (webviewId, event, data) => this.emitToWebview(webviewId, event, data)\n }),\n ...createMiscApis(this.info.appid, {\n realLogin: this.info.realLogin,\n onRealLoginFail: (api, reason) => this.shell.showNotice(`wx.${api} 真实登录失败`, reason)\n })\n });\n }\n}\n\n/**\n * 旧版 canvas 的绘制指令里,drawImage 用到的临时文件换成根路径。基础库的网页实现把 http(s) 地址\n * 都当成网络图片直接跳过(只放行开发者工具的 http://tmp/ 等),不报错,画布上什么也没有\n */\nfunction withDrawableImages(message: any): unknown {\n const actions = message?.data?.actions;\n if (!Array.isArray(actions)) return message;\n return {\n ...message,\n data: {\n ...message.data,\n actions: actions.map(action => {\n const [src, ...rest] = action.data ?? [];\n return action.method === 'drawImage' && typeof src === 'string'\n ? { ...action, data: [tempFileRootPath(src), ...rest] }\n : action;\n })\n }\n };\n}\n\nfunction stripHtml(path: string): string {\n return path.replace(/\\.html$/, '');\n}\n","/**\n * 热更新:不刷新宿主,应用样式、模板和页面逻辑的改动,保留页面状态(哪些改动能热更新见 server/hmr.ts)\n *\n * 样式在每个渲染层里原地替换(见 updateStyles);模板和逻辑借助基础库为开发者工具准备的接口\n * __virtualDOM__.updateWxAppCode(开关见 server/html.ts):\n * - 模板:按模板路径更新,基础库用实例当前的 data 重新渲染\n * - Page() 构造的页面:不走基础库按 .js 路径的更新——那会重新挂载页面(onUnload → onLoad),data 回到初始值。\n * 这里把新方法换到活着的页面实例上,再重新注册 Page,之后新打开的页面用新代码\n * - Component() 构造的页面和组件(uni-app 的页面也是):状态常在框架自己的实例里(如 Vue 的 setup),\n * 换方法保不住,交给基础库按 .js 路径重新挂载这些实例;页面栈、globalData、其他页面不受影响\n */\n\nimport type { Host } from './Host';\n\nexport interface HotUpdate {\n version: number;\n templates: string[];\n scripts: string[];\n styles: string[];\n}\n\n/**\n * @throws 拿不到新代码、新代码执行出错、模块没有调用 Page() / Component() 等无法热更新的情况;调用方应整页刷新\n */\nexport async function applyHotUpdate(host: Host, update: HotUpdate): Promise<void> {\n const hasTemplates = update.templates.length > 0;\n const hasStyles = update.styles.length > 0;\n const v = `?v=${update.version}`;\n const [pageStyles, pageTemplates, serviceTemplates, moduleScripts] = await Promise.all([\n hasStyles ? fetchText(`/__wxa__/page-styles.js${v}`) : '',\n hasTemplates ? fetchText(`/__wxa__/page-templates.js${v}`) : '',\n hasTemplates ? fetchText(`/__wxa__/service-templates.js${v}`) : '',\n Promise.all(update.scripts.map(id => fetchText(`/__wxa__/module/${encodeURI(id)}.js${v}`)))\n ]);\n\n // 与路由串行:跳转进行到一半时页面列表和实例都不稳定\n await host.enqueueRoute(async () => {\n const service = host.serviceWindow() as any;\n if (!service?.__virtualDOM__?.updateWxAppCode) throw new Error('基础库的热更新开关没有打开');\n\n if (hasStyles) {\n for (const page of host.livePages()) {\n if (page.win) updateStyles(page.win as any, pageStyles);\n }\n }\n\n if (hasTemplates) {\n // 渲染层先换上新模板,逻辑层随后发出的重新渲染指令才能对上\n for (const page of host.livePages()) {\n if (page.win) updateTemplates(page.win as any, pageTemplates, update.templates);\n }\n updateTemplates(service, serviceTemplates, update.templates);\n }\n\n update.scripts.forEach((id, index) => updateScript(service, host, id, moduleScripts[index]));\n });\n}\n\n/**\n * 重新执行公共样式(app.wxss、被 @import 的文件),再重放这个渲染层用过的页面和组件样式。\n * 不区分改了哪个文件:没改的样式写回相同的内容\n *\n * 基础库按「路径:组件 class 前缀」登记样式表,同一个 key 再次写入时原地替换 <style> 的内容。\n * 每次写入会多登记一个 rpx 重算回调(窗口尺寸变化时重新生成样式),回调按登记顺序执行,最新的样式最后写入\n *\n * 不用基础库为 .wxss 登记的 updateWxAppCode 回调:它按组件的方式注入页面样式,页面里合法的 ID、标签选择器\n * 每次都会报「组件中不允许」的警告,page-isolated 的页面还会换成带组件前缀的另一份样式、旧样式留在原处\n */\nfunction updateStyles(win: any, code: string) {\n const sheets: Record<string, StyleSheetEntry> | undefined = win.__styleSheetManager2__?._pathMap;\n if (!sheets) throw new Error('基础库没有样式表管理器,无法热替换样式');\n const applied = Object.keys(sheets);\n runScript(win, code);\n\n for (const key of applied) {\n const [, file, classPrefix] = /^\\.\\/(.+\\.wxss):(.*)$/.exec(key) || [];\n // app.wxss 等公共样式没有注册到 __wxAppCode__,执行 code 时已经替换\n const inject = file && win.__wxAppCode__[file];\n if (typeof inject === 'function') inject(classPrefix);\n }\n restoreSheetOrder(Object.values(sheets));\n // 与基础库自己更新样式后一样通知组件重新布局,如 movable-area 重新计算尺寸\n win.wx.triggerPageReRender();\n}\n\ninterface StyleSheetEntry {\n inserted: boolean;\n style: HTMLStyleElement;\n}\n\n/**\n * 加载时为空的样式表只登记、不插入页面,第一次写入内容时追加在 head 末尾,排到了本该在它后面的样式之后。\n * 按登记顺序(即加载时的注入顺序)挪回原位,层叠结果才与刷新后一致\n */\nfunction restoreSheetOrder(sheets: StyleSheetEntry[]) {\n let next: HTMLStyleElement | null = null;\n for (const { inserted, style } of sheets.reverse()) {\n // 被基础库移出页面的不参与排序,如 page-isolated 页面里的 app.wxss\n if (!inserted || !style.isConnected) continue;\n if (next && style.compareDocumentPosition(next) & Node.DOCUMENT_POSITION_PRECEDING) next.before(style);\n next = style;\n }\n}\n\nfunction updateTemplates(win: any, code: string, units: string[]) {\n // wcc 生成的模板把编译结果缓存在 __WXML_GLOBAL__ 上,不清掉的话新代码会读到旧缓存。\n // 保留 wxs_nf_init:WXS 运行时只能初始化一次,重复执行会因改写内置对象原型而报错\n const cache = win.__WXML_GLOBAL__;\n if (cache) Object.assign(cache, { ops_cached: {}, ops_set: {}, ops_init: {}, debuginfo_set: {}, modules: {} });\n runScript(win, code);\n\n for (const id of units) {\n const generate = win.__wxAppCode__[id + '.wxml'];\n if (generate) win.__virtualDOM__.updateWxAppCode(id + '.wxml', generate);\n }\n}\n\n/** 每次热更新的模块 id 都不同:同一个构建版本也可能被应用两次 */\nlet hotModuleSeq = 0;\n\nfunction updateScript(service: any, host: Host, id: string, moduleScript: string) {\n // 基础库忽略对已有模块的重复 define,新代码换个同目录的模块 id 执行:相对路径的 require 解析结果不变,\n // 它依赖的模块直接取缓存,不会重新执行\n const registration = loadModule(service, moduleScript, `${id}.hot-${++hotModuleSeq}.js`);\n if (!registration) throw new Error(`${id}.js 没有调用 Page() 或 Component(),无法热更新`);\n\n if (registration.constructor === service.Page) {\n for (const page of host.livePages()) {\n if (page.path !== id) continue;\n const instance = service.__virtualDOM__.getRootNode(page.id)?.__methodCaller;\n if (!instance) throw new Error(`找不到页面 ${id}(webviewId ${page.id})的实例`);\n swapMethods(instance, registration.options);\n }\n register(service, id, registration);\n return;\n }\n\n // 回调由基础库在注册时登记;没被调用说明没登记上,这次更新不会生效\n let registered = false;\n service.__virtualDOM__.updateWxAppCode(`${id}.js`, () => {\n register(service, id, registration);\n registered = true;\n });\n if (!registered) throw new Error(`基础库没有登记 ${id}.js 的热更新回调`);\n}\n\ninterface Registration {\n constructor: (options: Record<string, any>) => unknown;\n options: Record<string, any>;\n}\n\n/** 按 bootstrap 里 require 页面和组件时的方式设置当前文件,再真正注册 */\nfunction register(service: any, id: string, { constructor, options }: Registration) {\n service.__wxRoute = id;\n service.__wxRouteBegin = true;\n service.__wxAppCurrentFile__ = id + '.js';\n constructor(options);\n}\n\n/**\n * 以新模块 id 执行模块,拦下 Page() / Component() 的参数而不注册\n *\n * 逻辑层的 define 不可改写,这里把模块脚本包进以 define 为参数的函数来取出模块函数。\n * Page / Component 要改全局:uni-app 等框架在自己的 vendor 模块里调用它们,包一层参数拦不到\n */\nfunction loadModule(service: any, script: string, hotId: string): Registration | undefined {\n let factory: unknown;\n service.__wxaHotDefine__ = (_id: string, fn: unknown) => {\n factory = fn;\n };\n try {\n runScript(service, `(function (define) {\\n${script}\\n})(__wxaHotDefine__);`);\n } finally {\n delete service.__wxaHotDefine__;\n }\n if (typeof factory !== 'function') throw new Error('模块脚本没有 define 模块');\n service.define(hotId, factory);\n\n const { Page, Component } = service;\n let registration: Registration | undefined;\n service.Page = (options: Record<string, any>) => {\n registration = { constructor: Page, options };\n };\n service.Component = (options: Record<string, any>) => {\n registration = { constructor: Component, options };\n };\n try {\n if (service.Page === Page || service.Component === Component) throw new Error('无法拦截 Page / Component');\n service.require(hotId);\n } finally {\n service.Page = Page;\n service.Component = Component;\n }\n return registration;\n}\n\n/**\n * 方法一律换新;data 和其他非函数字段(如 pageSize)可能已被运行时改过,属于状态:\n * 已有的保持不动,只补上新增的,改了初始值的对当前实例不生效\n */\nfunction swapMethods(instance: any, definition: Record<string, any>) {\n for (const [key, value] of Object.entries(definition)) {\n if (typeof value === 'function') instance[key] = value;\n else if (key !== 'data' && !(key in instance)) instance[key] = value;\n }\n const data = definition.data || {};\n const added = Object.keys(data).filter(key => !(key in instance.data));\n if (added.length) instance.setData(Object.fromEntries(added.map(key => [key, data[key]])));\n}\n\n/**\n * 在 win 的全局作用域执行代码,出错时抛出(不记入宿主的错误列表)\n *\n * 不用 win.eval:新版基础库会删掉所在上下文的 eval。内联脚本同步执行,\n * 出错时在 win 上派发 error 事件,捕获阶段先于 frame.ts 的错误上报拦下\n */\nfunction runScript(win: any, code: string) {\n let failed = false;\n let error: unknown;\n const onError = (event: ErrorEvent) => {\n failed = true;\n error = event.error ?? new Error(event.message);\n event.stopImmediatePropagation();\n event.preventDefault();\n };\n const script = win.document.createElement('script');\n script.text = code;\n win.addEventListener('error', onError, true);\n try {\n win.document.head.appendChild(script);\n } finally {\n win.removeEventListener('error', onError, true);\n script.remove();\n }\n if (failed) throw error;\n}\n\nasync function fetchText(url: string): Promise<string> {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`${url} ${response.status}`);\n return response.text();\n}\n","/**\n * wxa-runner 触发的整页刷新(改了无法热更新的文件、热更新失败)保留页面栈:\n * 刷新前记下每一页的路径和参数,启动后依次重新打开\n *\n * 开发者手动刷新不经过这里,只按地址栏恢复当前页——手动刷新通常就是想从头来过。\n * 为此记录在启动时就取出并删掉;恢复完成之前又被 wxa-runner 刷新时,再原样写回去。\n */\n\nimport type { Host, LaunchTarget } from './Host';\n\nexport class PageStackRestore {\n private readonly key: string;\n /** 本次启动要恢复的页面栈 */\n private saved: LaunchTarget[];\n /** 恢复完成前(包括编译、setup 出错没能启动)自动刷新,要把 saved 原样记回去 */\n private restoring: boolean;\n\n /** 按 appid 区分:同一个标签页换了项目时不会串用 */\n constructor(appid: string) {\n this.key = `wxa-runner:reload-page-stack:${appid}`;\n this.saved = read(this.key);\n this.restoring = this.saved.length > 0;\n }\n\n /** 启动页:记下的第一页;记下的页面已经不存在时,从它开始往后都不恢复 */\n launchTarget(pages: string[], fallback: LaunchTarget): LaunchTarget {\n const invalid = this.saved.findIndex(entry => !pages.includes(entry.path));\n if (invalid >= 0) this.saved = this.saved.slice(0, invalid);\n return this.saved[0] ?? fallback;\n }\n\n /**\n * 在已启动的第一页之上依次 navigateTo 其余页面;某一页打不开就停下\n *\n * 整段放进同一个路由任务:恢复期间开发者点返回、切 tab 会排在恢复完成之后\n */\n async reopen(host: Host) {\n try {\n await host.enqueueRoute(async () => {\n for (const { path, query } of this.saved.slice(1)) {\n const search = new URLSearchParams(query).toString();\n const result = await host.navigateTo(search ? `${path}?${search}` : path);\n if (!String(result.errMsg).endsWith(':ok')) {\n console.warn(`[wxa-runner] 恢复页面栈时打不开 ${path}:${result.errMsg}`);\n return;\n }\n }\n });\n } finally {\n this.restoring = false;\n }\n }\n\n /** 记下当前页面栈后整页刷新 */\n reload(host: Host | undefined) {\n const stack = this.restoring ? this.saved : host?.pageStack().map(page => ({ path: page.path, query: page.query })) ?? [];\n if (stack.length) {\n try {\n sessionStorage.setItem(this.key, JSON.stringify(stack));\n } catch {\n // 存不了就只恢复当前页\n }\n }\n location.reload();\n }\n}\n\nfunction read(key: string): LaunchTarget[] {\n try {\n const saved = JSON.parse(sessionStorage.getItem(key) || '[]');\n sessionStorage.removeItem(key);\n if (!Array.isArray(saved)) return [];\n return saved\n .filter(entry => entry && typeof entry.path === 'string')\n .map(entry => ({ path: entry.path, query: { ...entry.query } }));\n } catch {\n return [];\n }\n}\n","/**\n * 执行 setup:在逻辑层创建之前预置存储、覆盖原生 API\n *\n * 必须早于小程序启动:基础库会把读过的存储缓存在内存里,启动后再从宿主写入,\n * wx.getStorageSync 读不到新值。\n */\n\nimport type { MockValue, RouteHandler, SetupApi, SetupConfig, SetupEnv } from '../../setup';\nimport { proxyFetch } from './api/network';\nimport type { ApiRegistry } from './api/registry';\nimport type { RequestRoutes } from './api/routes';\nimport { decodeStorageValue, encodeStorageValue, MiniProgramStorage } from './api/storage';\n\nexport interface SetupTarget {\n storage: MiniProgramStorage;\n api: ApiRegistry;\n routes: RequestRoutes;\n}\n\nexport interface SetupSummary {\n storage: string[];\n mock: string[];\n network: string[];\n}\n\nconst CONFIG_KEYS = ['storage', 'mock', 'network', 'run'];\nconst NETWORK_KEYS = ['routes'];\nconst STORAGE_NAMESPACE = 's0';\n\n/** 基础库里这些 API 不经同名 invoke 实现,按 wx 的名字 mock 不会生效 */\nexport const TASK_APIS = new Set(['request', 'downloadFile', 'uploadFile', 'connectSocket']);\nconst STORAGE_API = /^(get|set|remove|clear)Storage(Info)?(Sync)?$/;\n\n/**\n * @param definition setup 文件的默认导出\n * @param env 暴露给 setup 的环境变量\n * @throws 配置写错或 setup 自身执行出错时;此时已应用的部分不会回滚,调用方不应继续启动小程序\n */\nexport async function applySetup(definition: unknown, target: SetupTarget, env: SetupEnv): Promise<SetupSummary> {\n const summary: SetupSummary = { storage: [], mock: [], network: [] };\n const record = (list: string[], name: string) => {\n if (!list.includes(name)) list.push(name);\n };\n\n const setStorage = (key: string, value: unknown, label = key) => {\n let encoded;\n try {\n encoded = encodeStorageValue(value);\n } catch (error) {\n throw new Error(`storage.${label}:${(error as Error).message}`);\n }\n target.storage.set(STORAGE_NAMESPACE, key, encoded.data, encoded.dataType);\n record(summary.storage, key);\n };\n\n const mock = (api: string, impl: MockValue) => {\n checkMock(api, impl);\n target.api.mock(api, impl);\n record(summary.mock, api);\n };\n\n const route = (pattern: string, handler: RouteHandler) => {\n try {\n target.routes.add(pattern, handler);\n } catch (error) {\n throw new Error(`network.routes[${JSON.stringify(pattern)}]:${(error as Error).message}`);\n }\n record(summary.network, pattern);\n };\n\n const config = await resolveConfig(definition, env);\n\n for (const [key, value] of Object.entries(config.storage || {})) setStorage(key, value);\n for (const [api, impl] of Object.entries(config.mock || {})) mock(api, impl);\n for (const [pattern, handler] of Object.entries(config.network?.routes || {})) route(pattern, handler);\n\n if (config.run) {\n const wxa: SetupApi = {\n env,\n storage: {\n get: key => {\n const item = target.storage.get(STORAGE_NAMESPACE, key);\n return item ? decodeStorageValue(item) : undefined;\n },\n set: (key, value) => setStorage(key, value),\n remove: key => target.storage.remove(STORAGE_NAMESPACE, key),\n clear: () => target.storage.clear(STORAGE_NAMESPACE)\n },\n mock: (api, impl) => mock(api, impl as MockValue),\n route,\n fetch: (url, init = {}) => proxyFetch(url, { method: (init.method || 'GET').toUpperCase(), header: init.header, body: init.body })\n .then(res => new Response(NULL_BODY_STATUS.has(res.statusCode) ? null : res.response.body, {\n status: res.statusCode,\n headers: res.header\n }))\n };\n await config.run(wxa);\n }\n\n return summary;\n}\n\nexport function formatSetupSummary(summary: SetupSummary): string {\n const lines = ['[wxa-runner] setup 已应用'];\n if (summary.storage.length) lines.push(` storage ${summary.storage.join(', ')}`);\n if (summary.mock.length) lines.push(` mock ${summary.mock.join(', ')}`);\n if (summary.network.length) lines.push(` network ${summary.network.join(', ')}`);\n return lines.join('\\n');\n}\n\nconst NULL_BODY_STATUS = new Set([101, 204, 205, 304]);\n\nasync function resolveConfig(definition: unknown, env: SetupEnv): Promise<SetupConfig> {\n const config = typeof definition === 'function' ? await definition({ env }) : definition;\n if (!isPlainObject(config)) {\n throw new Error('setup 文件需要 export default 一个配置对象,或返回配置对象的函数(可用 defineSetup 包一层获得类型提示)');\n }\n\n const unknown = Object.keys(config).filter(key => !CONFIG_KEYS.includes(key));\n if (unknown.length) {\n throw new Error(`未知的配置项 ${unknown.join(', ')},可用的配置项:${CONFIG_KEYS.join(', ')}`);\n }\n if (config.storage !== undefined && !isPlainObject(config.storage)) throw new Error('storage 需要是 { key: 值 } 形式的对象');\n if (config.mock !== undefined && !isPlainObject(config.mock)) throw new Error('mock 需要是 { API 名: 返回值或函数 } 形式的对象');\n if (config.network !== undefined) {\n if (!isPlainObject(config.network)) throw new Error('network 需要是 { routes: { 规则: 响应 } } 形式的对象');\n const unknownNetwork = Object.keys(config.network).filter(key => !NETWORK_KEYS.includes(key));\n if (unknownNetwork.length) throw new Error(`network 下未知的配置项 ${unknownNetwork.join(', ')},可用的配置项:${NETWORK_KEYS.join(', ')}`);\n if (config.network.routes !== undefined && !isPlainObject(config.network.routes)) {\n throw new Error('network.routes 需要是 { 规则: 响应 } 形式的对象');\n }\n }\n if (config.run !== undefined && typeof config.run !== 'function') throw new Error('run 需要是函数');\n return config as SetupConfig;\n}\n\nfunction checkMock(api: string, impl: unknown) {\n if (TASK_APIS.has(api)) {\n throw new Error(`mock.${api}:wx.${api} 由基础库内部的任务实现,mock 无法覆盖;拦截 wx.request 请用 network.routes(请求拦截)`);\n }\n if (STORAGE_API.test(api)) {\n throw new Error(`mock.${api}:存储数据请用 storage 预置,不要覆盖存储 API`);\n }\n if (typeof impl !== 'function' && !isPlainObject(impl)) {\n throw new Error(`mock.${api}:需要是作为调用结果的对象,或按调用参数返回结果的函数`);\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, any> {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n","/**\n * window.__wxa_test_api__:给 E2E 测试(Playwright 等)使用的钩子\n */\n\nimport type { RouteHandler } from '../../setup';\nimport type { RecordedRequest } from './api/network';\nimport type { ApiHandler, ApiResult } from './api/registry';\nimport { compilePattern } from './api/routes';\nimport { decodeStorageValue } from './api/storage';\nimport type { FrameError, Host } from './Host';\nimport { cloneInto } from './realm';\nimport { TASK_APIS } from './setup';\n\nexport type { RecordedRequest };\n\nexport interface PageSnapshot {\n webviewId: number;\n /** 页面路径,如 pages/index/index,不带开头的 / */\n path: string;\n query: Record<string, string>;\n /** 渲染层 iframe 的 name,可用于 page.frame({ name }) */\n frameName: string;\n}\n\nexport interface WxaTestApi {\n /** 小程序启动完成(首页加载完、整页刷新后页面栈恢复完)后 resolve。setup 或启动前的准备出错时不会 resolve,模拟器显示错误 */\n ready: Promise<void>;\n /** 当前页,即页面栈顶;小程序启动前为 null */\n currentPage(): PageSnapshot | null;\n /** 整个页面栈,栈底在前 */\n pageStack(): PageSnapshot[];\n /**\n * 等到指定页面成为当前页,已经是当前页时立即返回\n * @param path 页面路径,如 pages/index/index,开头的 / 可有可无\n * @param timeout 毫秒,默认 10000\n * @throws 超时\n */\n waitForPage(path: string, timeout?: number): Promise<PageSnapshot>;\n /**\n * 页面的 data,是一份拷贝,修改它不影响页面\n * @param path 不传时读当前页;传页面路径时读页面栈里离栈顶最近的这个页面\n * @returns 页面不在页面栈里,或逻辑层还没创建它(刚跳转时)时为 null\n */\n pageData(path?: string): Record<string, unknown> | null;\n /**\n * 调用当前页的方法,如 callPageMethod('onPullDownRefresh')。方法返回 Promise 时等它完成\n * @param args 要能 JSON 序列化\n * @returns 方法的返回值\n * @throws 当前页还没创建、没有这个方法,或者方法抛错时\n */\n callPageMethod(name: string, ...args: unknown[]): Promise<unknown>;\n /**\n * 覆盖原生 API,同名的 setup mock 也被覆盖。整页刷新后失效\n * @param api 与 wx 上的名字相同,如 login、getLocation\n * @param impl 对象作为调用结果;函数按调用参数返回结果,可以返回 Promise,抛错即调用失败\n * @throws api 是 request、downloadFile 等由基础库任务实现的 API 时:mock 不会生效,wx.request 要用 route 拦截\n */\n mock(api: string, impl: ApiHandler | ApiResult): void;\n /** 撤销 mock,恢复内置实现;不传 api 时撤销全部,包括 setup 声明的 */\n unmock(api?: string): void;\n /**\n * 拦截 wx.request:命中的请求不发往网络,直接返回给定的响应。写法与 setup 的 network.routes 相同,后添加的规则优先。整页刷新后失效\n * @param pattern '[请求方法 ]地址',如 'POST https://api.example.com/login';* 匹配一段路径,** 匹配任意内容(可以不写域名)\n * @param handler 响应 { status?, header?, body?, delay? },或按请求返回响应的函数\n * @throws 规则写法不对时\n */\n route(pattern: string, handler: RouteHandler): void;\n /** 删除按这个写法添加的拦截规则;不传时删除全部,包括 setup 声明的 */\n unroute(pattern?: string): void;\n /**\n * 小程序发出的 wx.request,按发出顺序,被拦截的和经代理转发的都有。只保留最近 1000 个,整页刷新后清空\n * @param pattern 只返回匹配的请求,写法同 route\n * @throws pattern 写法不对时\n */\n requests(pattern?: string): RecordedRequest[];\n /** 清空已记录的请求,常用于只关心某个操作之后发出的请求 */\n clearRequests(): void;\n /**\n * 打开新页面,同 wx.navigateTo\n * @param url 从小程序根目录写起,如 /pages/detail/detail?id=1\n * @returns 调用结果;失败时不抛错,errMsg 以 navigateTo:fail 开头说明原因\n */\n navigateTo(url: string): Promise<ApiResult>;\n /**\n * 返回上一页或多级页面,同 wx.navigateBack\n * @param delta 返回的层数,默认 1\n * @returns 调用结果;失败时不抛错,errMsg 说明原因\n */\n navigateBack(delta?: number): Promise<ApiResult>;\n /**\n * 关闭当前页,打开新页面,同 wx.redirectTo\n * @returns 调用结果;失败时不抛错,errMsg 说明原因\n */\n redirectTo(url: string): Promise<ApiResult>;\n /**\n * 关闭所有页面,打开新页面,同 wx.reLaunch\n * @returns 调用结果;失败时不抛错,errMsg 说明原因\n */\n reLaunch(url: string): Promise<ApiResult>;\n /**\n * 切换到 tabBar 页面,同 wx.switchTab\n * @returns 调用结果;失败时不抛错,errMsg 说明原因\n */\n switchTab(url: string): Promise<ApiResult>;\n /** 读取小程序的 Storage,值保持写入时的类型;没有这个 key 时为 undefined */\n getStorage(key: string): unknown;\n /** 清空小程序的 Storage。基础库会缓存读过的值,小程序启动后再清空,已读过的 key 可能仍读到旧值 */\n clearStorage(): void;\n /**\n * 逻辑层、渲染层的运行时错误,以及业务代码调用过的未实现 wx API(api 为 API 名称,每个 API 记一次)。\n * 这些都不会让测试失败,需要自己检查\n */\n errors(): FrameError[];\n}\n\nexport function installTestApi(host: Host, ready: Promise<void>): WxaTestApi {\n const snapshot = (page: ReturnType<Host['currentPage']>): PageSnapshot | null =>\n page ? { webviewId: page.id, path: page.path, query: { ...page.query }, frameName: page.frame.name } : null;\n\n /** 逻辑层里的页面实例;同一页面打开多次时取离栈顶最近的 */\n const pageInstance = (path: string | undefined): any => {\n if (!path) return undefined;\n const pages: any[] = (host.serviceWindow() as any)?.getCurrentPages?.() || [];\n return [...pages].reverse().find(page => page.route === path);\n };\n\n const api: WxaTestApi = {\n ready,\n currentPage: () => snapshot(host.currentPage()),\n pageStack: () => host.pageStack().map(page => snapshot(page)!),\n waitForPage(path, timeout = 10000) {\n const target = path.replace(/^\\//, '');\n return new Promise((resolve, reject) => {\n const current = host.currentPage();\n if (current?.path === target) return resolve(snapshot(current)!);\n const timer = setTimeout(() => reject(new Error(`等待页面 ${target} 超时`)), timeout);\n host.onRoute(page => {\n if (page.path === target) {\n clearTimeout(timer);\n resolve(snapshot(page)!);\n }\n });\n });\n },\n pageData(path) {\n const instance = pageInstance(path === undefined ? host.currentPage()?.path : host.resolveUrl(path).path);\n if (!instance) return null;\n // __webviewId__ 是基础库加进 data 的内部字段\n const { __webviewId__: _webviewId, ...data } = JSON.parse(JSON.stringify(instance.data));\n return data;\n },\n async callPageMethod(name, ...args) {\n const current = host.currentPage();\n if (!current) throw new Error('小程序还没有启动');\n const instance = pageInstance(current.path);\n if (!instance) throw new Error(`页面 ${current.path} 的逻辑层还没有创建`);\n if (typeof instance[name] !== 'function') throw new Error(`页面 ${current.path} 没有方法 ${name}`);\n return instance[name](...cloneInto(host.serviceWindow()!, args));\n },\n mock(name, impl) {\n if (TASK_APIS.has(name)) {\n throw new Error(`wx.${name} 由基础库内部的任务实现,mock 不会生效;wx.request 请用 route 拦截`);\n }\n host.api.mock(name, impl);\n },\n unmock: name => host.api.unmock(name),\n route: (pattern, handler) => host.routes.add(pattern, handler),\n unroute: pattern => host.routes.remove(pattern),\n requests(pattern) {\n const matches = pattern === undefined ? () => true : compilePattern(pattern);\n return host.requests.list().filter(matches);\n },\n clearRequests: () => host.requests.clear(),\n navigateTo: url => host.enqueueRoute(() => host.navigateTo(url)),\n navigateBack: (delta = 1) => host.enqueueRoute(() => host.navigateBack(delta)),\n redirectTo: url => host.enqueueRoute(() => host.redirectTo(url)),\n reLaunch: url => host.enqueueRoute(() => host.reLaunch(url)),\n switchTab: url => host.enqueueRoute(() => host.switchTab(url)),\n getStorage(key) {\n const item = host.storage.get('s0', key);\n return item ? decodeStorageValue(item) : undefined;\n },\n clearStorage: () => host.storage.clear('s0'),\n errors: () => [...host.errors]\n };\n\n (window as any).__wxa_test_api__ = api;\n return api;\n}\n","/**\n * 宿主页面入口(打包为 /__wxa__/runtime/host.js)\n */\n\nimport type { AppInfo } from '../types';\nimport { Host, LaunchTarget } from './Host';\nimport { applyHotUpdate, HotUpdate } from './hmr';\nimport { PageStackRestore } from './pageStackRestore';\nimport { applySetup, formatSetupSummary } from './setup';\nimport { installTestApi, WxaTestApi } from './testApi';\nimport { PhoneShell } from './ui/PhoneShell';\n\nasync function main() {\n const root = document.getElementById('wxa-root')!;\n const info: AppInfo = await (await fetch('/__wxa__/app-info.json')).json();\n const restore = new PageStackRestore(info.appid);\n\n connectDevServer(restore);\n\n if (info.buildError) {\n new PhoneShell(root, info.device).showError(`编译失败\\n\\n${info.buildError}`);\n return;\n }\n\n const host = new Host(info, root);\n (window as any).__wxaHost = host;\n\n let markReady!: () => void;\n const ready = new Promise<void>(resolve => {\n markReady = resolve;\n });\n const testApi = installTestApi(host, ready);\n\n if (info.setup && !(await runSetup(host, info.setup))) return;\n if (!(await runBeforeLaunch(host, testApi))) return;\n await host.start(restore.launchTarget(info.pages, launchTarget(info)));\n await restore.reopen(host);\n markReady();\n}\n\n/**\n * 在逻辑层创建前执行 setup;失败时显示错误并返回 false——带着一半的预置状态启动,\n * 小程序的表现会让人误以为是业务代码的问题\n */\nasync function runSetup(host: Host, setup: NonNullable<AppInfo['setup']>): Promise<boolean> {\n try {\n if (setup.error) throw new Error(setup.error);\n // 地址是变量:esbuild 不会尝试在打包时解析它\n const url = '/__wxa__/setup.js';\n const module = await import(url);\n console.info(formatSetupSummary(await applySetup(module.default, host, setup.env)));\n return true;\n } catch (error) {\n console.error('[wxa-runner] setup 执行失败', error);\n host.shell.showError(`setup 执行失败\\n\\n${(error as Error).message}`);\n return false;\n }\n}\n\n/**\n * 执行测试工具在页面脚本之前定义的 window.__wxa_before_launch__。排在 setup 之后,\n * 这里声明的 mock 覆盖 setup 的同名 mock;失败时同 setup,显示错误、不启动小程序\n */\nasync function runBeforeLaunch(host: Host, testApi: WxaTestApi): Promise<boolean> {\n const hook = window.__wxa_before_launch__;\n if (typeof hook !== 'function') return true;\n try {\n await hook(testApi);\n return true;\n } catch (error) {\n console.error('[wxa-runner] __wxa_before_launch__ 执行失败', error);\n host.shell.showError(`启动前的测试准备(__wxa_before_launch__)执行失败\\n\\n${(error as Error).message}`);\n return false;\n }\n}\n\n/** ?path=pages/detail/detail&id=1 可以直接打开指定页面 */\nfunction launchTarget(info: AppInfo): LaunchTarget {\n const params = new URLSearchParams(location.search);\n const path = (params.get('path') || '').replace(/^\\//, '').replace(/\\.html$/, '');\n params.delete('path');\n if (path && info.pages.includes(path)) {\n return { path, query: Object.fromEntries(params) };\n }\n const entry = String(info.wxConfig.entryPagePath || info.pages[0]).replace(/\\.html$/, '');\n return { path: entry, query: {} };\n}\n\n/** 文件变化后热更新或整页刷新;编译出错时显示错误 */\nfunction connectDevServer(restore: PageStackRestore) {\n const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';\n const socket = new WebSocket(`${protocol}//${location.host}/__wxa__/ws`);\n // 连续保存时按顺序应用\n let hotChain = Promise.resolve();\n socket.onmessage = event => {\n const message = JSON.parse(event.data);\n if (message.type === 'reload') restore.reload(currentHost());\n if (message.type === 'hot') hotChain = hotChain.then(() => hotUpdate(message, restore));\n if (message.type === 'error') {\n const host = currentHost();\n if (host) host.shell.showError(`编译失败\\n\\n${message.message}`);\n else restore.reload(host);\n }\n };\n}\n\nfunction currentHost(): Host | undefined {\n return (window as any).__wxaHost;\n}\n\nasync function hotUpdate(update: HotUpdate, restore: PageStackRestore) {\n const host = currentHost();\n const files = [\n ...update.styles.map(id => id + '.wxss'),\n ...update.templates.map(id => id + '.wxml'),\n ...update.scripts.map(id => id + '.js')\n ].join(', ');\n try {\n if (!host) throw new Error('宿主尚未启动');\n await applyHotUpdate(host, update);\n console.info(`[wxa-runner] 热更新完成:${files}`);\n } catch (error) {\n console.warn(`[wxa-runner] ${files} 无法热更新,整页刷新:`, error);\n restore.reload(host);\n }\n}\n\nmain().catch(error => {\n console.error('[wxa-runner] 启动失败', error);\n document.body.textContent = `wxa-runner 启动失败:${error.message}`;\n});\n"],"mappings":"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","names":["reason","location","chooseFiles","hasUserActivation","source","labels","confirm","window","reason","runScript"]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/host/api/registry.ts","../../src/runtime/host/api/audio.ts","../../src/runtime/host/api/tempFiles.ts","../../src/runtime/host/api/fs.ts","../../src/runtime/syncScript.ts","../../src/runtime/host/api/libFiles.ts","../../src/runtime/host/api/map.ts","../../src/runtime/host/api/media.ts","../../src/runtime/host/api/misc.ts","../../src/runtime/host/api/network.ts","../../src/runtime/host/api/picker.ts","../../src/runtime/host/api/routes.ts","../../src/runtime/host/api/savedFiles.ts","../../src/runtime/host/api/storage.ts","../../src/runtime/host/api/subpackages.ts","../../src/runtime/host/api/system.ts","../../src/runtime/host/api/ui.ts","../../src/runtime/host/api/webView.ts","../../src/runtime/host/PageStack.ts","../../src/runtime/host/PageView.ts","../../src/runtime/host/realm.ts","../../src/runtime/host/ui/fileChooser.ts","../../src/runtime/host/ui/dom.ts","../../src/runtime/host/ui/ImagePreview.ts","../../src/runtime/host/ui/styles.ts","../../src/runtime/host/ui/Picker.ts","../../src/runtime/host/ui/PhoneShell.ts","../../src/runtime/host/Host.ts","../../src/runtime/host/hmr.ts","../../src/runtime/host/pageStackRestore.ts","../../src/runtime/host/setup.ts","../../src/runtime/host/testApi.ts","../../src/runtime/host/index.ts"],"sourcesContent":["/**\n * 原生 API 注册表\n *\n * 处理函数返回结果对象(可以是 Promise)。结果能同步得到时同步回调——\n * 基础库在一些非 Sync 结尾的 API(如带 type 参数的 getSystemInfo)上也依赖同步回调。\n * 少数原生接口的结果是字符串,由基础库自己解析(如地图的 private_geolocation),原样交回。\n */\n\nimport type { FrameKind } from '../../types';\n\nexport type ApiResult = Record<string, any>;\n\nexport interface ApiContext {\n api: string;\n from: FrameKind;\n /** 发起调用的渲染层 id,逻辑层调用时为当前页面 */\n webviewId: number;\n}\n\nexport type ApiHandler = (args: any, context: ApiContext) => ApiResult | string | void | Promise<ApiResult | string | void>;\n\n/** 基础库内部频繁调用、无需提示的 API */\nconst SILENT_APIS = new Set([\n 'reportKeyValue', 'reportIDKey', 'reportRealtimeAction', 'reportPerformance', 'systemLog', 'traceEvent',\n 'getPermissionBytes', 'getABTestConfig', 'initRenderDone', 'saveInitialRenderingCache',\n 'setKeyValue', 'invokeMiniProgramAPI', 'updatePerfData', 'reportSubmitForm',\n 'initReady', 'noticePerformanceMetrics'\n]);\n\nexport class ApiRegistry {\n private handlers = new Map<string, ApiHandler>();\n private mocks = new Map<string, ApiHandler>();\n private warned = new Set<string>();\n\n /** @param onUnimplemented 调用了没有实现、也没有 mock 的 API 时触发,每次调用都触发;基础库内部的上报类接口不触发 */\n constructor(private readonly onUnimplemented?: (context: ApiContext) => void) {}\n\n register(handlers: Record<string, ApiHandler>) {\n for (const [name, handler] of Object.entries(handlers)) {\n this.handlers.set(name, handler);\n }\n }\n\n has(api: string): boolean {\n return this.handlers.has(api) || this.mocks.has(api);\n }\n\n /** 测试用:覆盖某个 API;传入对象时直接作为结果返回 */\n mock(api: string, impl: ApiHandler | ApiResult) {\n this.mocks.set(api, typeof impl === 'function' ? impl as ApiHandler : () => impl as ApiResult);\n }\n\n unmock(api?: string) {\n if (api) this.mocks.delete(api);\n else this.mocks.clear();\n }\n\n invoke(api: string, args: any, context: ApiContext): ApiResult | string | Promise<ApiResult | string> {\n const handler = this.mocks.get(api) || this.handlers.get(api);\n\n if (!handler) {\n if (!SILENT_APIS.has(api)) {\n this.onUnimplemented?.(context);\n if (!this.warned.has(api)) {\n this.warned.add(api);\n console.warn(`[wxa-runner] wx.${api} 尚未实现,返回默认成功`, args);\n }\n }\n return { errMsg: `${api}:ok` };\n }\n\n try {\n const result = handler(args || {}, context);\n if (result && typeof (result as Promise<ApiResult>).then === 'function') {\n return (result as Promise<ApiResult | string | void>).then(\n value => normalize(api, value),\n error => failure(api, error)\n );\n }\n return normalize(api, result as ApiResult | string | void);\n } catch (error) {\n return failure(api, error);\n }\n }\n}\n\nexport function ok(api: string, extra: ApiResult = {}): ApiResult {\n return { ...extra, errMsg: `${api}:ok` };\n}\n\nexport function fail(api: string, reason: string, extra: ApiResult = {}): ApiResult {\n return { ...extra, errMsg: `${api}:fail ${reason}` };\n}\n\nfunction normalize(api: string, result: ApiResult | string | void): ApiResult | string {\n if (typeof result === 'string') return result;\n if (!result) return { errMsg: `${api}:ok` };\n return result.errMsg ? result : { ...result, errMsg: `${api}:ok` };\n}\n\nfunction failure(api: string, error: unknown): ApiResult {\n const message = error instanceof Error ? error.message : String(error);\n return { errMsg: `${api}:fail ${message}` };\n}\n","/**\n * 原生音频接口:基础库 3.3.x 及更早版本的 InnerAudioContext 调这些接口播放,宿主用 <audio> 实现\n *\n * 3.5.8 起平台是 devtools 时基础库改用 Web Audio,不再调这些接口(下载音频见 network.ts 的 isAudioDownload)。\n * 与基础库的约定:时间都以毫秒为单位;基础库每次改属性都带上全部状态调 setAudioState;\n * timeupdate 由基础库轮询 getAudioState 自己产生,这里只推送 onAudioStateChange。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\n\nexport interface AudioApiOptions {\n /** 向逻辑层派发事件 */\n emit: (event: string, data: Record<string, unknown>) => void;\n createAudio?: () => HTMLAudioElement;\n}\n\ninterface AudioInstance {\n audio: HTMLAudioElement;\n /** 基础库设置的 src。audio.src 是浏览器解析后的完整地址,比较不出有没有变 */\n src: string;\n /** 毫秒,还没播放过时从这里开始 */\n startTime: number;\n played: boolean;\n /** stop 之后到下一次播放、跳转或换 src 之前:stop 把进度归零引起的 seeking、seeked 等不转给基础库 */\n stopped: boolean;\n report: (state: string, extra?: Record<string, unknown>) => void;\n destroy: () => void;\n}\n\n/**\n * 浏览器事件 → 基础库的状态。play 用 playing:缓冲(waiting)后浏览器只派发 playing,\n * 基础库收到 waiting 就当作暂停、停止轮询进度,要再收到 play 才恢复\n */\nconst STATES: Record<string, string> = {\n canplay: 'canplay',\n playing: 'play',\n ended: 'ended',\n waiting: 'waiting',\n seeking: 'seeking',\n seeked: 'seeked'\n};\n\n/** HTMLMediaElement.HAVE_METADATA,单元测试的 Node 环境里没有 HTMLMediaElement */\nconst HAVE_METADATA = 1;\n\n/** MediaError.code → 基础库的 errCode:10002 网络错误,10004 格式错误,其余为 -1 未知错误 */\nconst ERROR_CODES: Record<number, number> = { 2: 10002, 3: 10004, 4: 10004 };\n\nlet audioSeq = 0;\n\nexport function createAudioApis(options: AudioApiOptions): Record<string, ApiHandler> {\n const { emit, createAudio = () => new Audio() } = options;\n const instances = new Map<number, AudioInstance>();\n\n const createAudioInstance: ApiHandler = (_args, { api }) => {\n const audioId = ++audioSeq;\n const audio = createAudio();\n const listening = new AbortController();\n const instance: AudioInstance = {\n audio,\n src: '',\n startTime: 0,\n played: false,\n stopped: false,\n report: (state, extra) => emit('onAudioStateChange', { audioId, state, ...extra }),\n destroy: () => {\n listening.abort();\n audio.pause();\n audio.removeAttribute('src');\n audio.load();\n }\n };\n const on = (type: string, listener: () => void) => audio.addEventListener(type, listener, { signal: listening.signal });\n\n for (const [type, state] of Object.entries(STATES)) {\n on(type, () => {\n if (!instance.stopped) instance.report(state);\n });\n }\n on('loadedmetadata', () => {\n if (!instance.played && instance.startTime > 0) audio.currentTime = instance.startTime / 1000;\n });\n on('error', () => {\n const code = audio.error?.code ?? 0;\n instance.report('error', { errCode: ERROR_CODES[code] ?? -1, errMsg: audio.error?.message || `MediaError ${code}` });\n });\n\n instances.set(audioId, instance);\n return ok(api, { audioId });\n };\n\n /** @returns 找不到时为失败结果 */\n const withInstance = (args: any, api: string, action: (instance: AudioInstance) => Record<string, unknown> | void) => {\n const instance = instances.get(args.audioId);\n return instance ? ok(api, action(instance) || {}) : fail(api, `audio instance ${args.audioId} not found`);\n };\n\n return {\n createAudioInstance,\n createAudioInstanceAsync: createAudioInstance,\n\n // 状态里的 paused、currentTime 等是基础库缓存的旧值,只取能设置的属性\n setAudioState: (args, { api }) => withInstance(args, api, instance => {\n const { audio } = instance;\n if (typeof args.autoplay === 'boolean') audio.autoplay = args.autoplay;\n if (typeof args.loop === 'boolean') audio.loop = args.loop;\n if (typeof args.volume === 'number') audio.volume = args.volume;\n if (typeof args.playbackRate === 'number') audio.playbackRate = args.playbackRate;\n // 重新赋值 src 会从头加载\n if (typeof args.src === 'string' && args.src !== instance.src) {\n Object.assign(instance, { src: args.src, played: false, stopped: false });\n audio.src = args.src;\n }\n // 和基础库的 Web Audio 实现一致:还没播放过时立即跳过去,没加载好的等 loadedmetadata\n if (typeof args.startTime === 'number' && args.startTime !== instance.startTime) {\n instance.startTime = args.startTime;\n if (!instance.played && audio.readyState >= HAVE_METADATA) audio.currentTime = args.startTime / 1000;\n }\n }),\n\n getAudioState: (args, { api }) => withInstance(args, api, ({ audio, src, startTime }) => ({\n src,\n startTime,\n paused: audio.paused,\n currentTime: Math.round(audio.currentTime * 1000),\n duration: Number.isFinite(audio.duration) ? Math.round(audio.duration * 1000) : 0,\n buffered: audio.buffered.length ? Math.round(audio.buffered.end(audio.buffered.length - 1) * 1000) : 0,\n volume: audio.volume,\n autoplay: audio.autoplay,\n loop: audio.loop,\n playbackRate: audio.playbackRate\n })),\n\n operateAudio: (args, { api }) => withInstance(args, api, instance => {\n const { audio } = instance;\n switch (args.operationType) {\n case 'play':\n Object.assign(instance, { played: true, stopped: false });\n // 被随后的 pause 打断(AbortError)不算错;音频本身加载失败由 error 事件报告\n audio.play().catch((error: DOMException) => {\n if (error.name === 'NotAllowedError') instance.report('error', { errCode: -1, errMsg: `${error.name}: ${error.message}` });\n });\n break;\n // 浏览器的 pause 事件不转发:它在 stop 之后才异步派发,播到结尾时也会先派发一次\n case 'pause':\n if (!audio.paused) instance.report('pause');\n audio.pause();\n break;\n case 'stop':\n instance.stopped = true;\n audio.pause();\n audio.currentTime = 0;\n instance.report('stop');\n break;\n case 'seek':\n instance.stopped = false;\n audio.currentTime = Number(args.currentTime) / 1000;\n break;\n default:\n throw new Error(`unknown operationType ${args.operationType}`);\n }\n }),\n\n destroyAudioInstance: (args, { api }) => {\n instances.get(args.audioId)?.destroy();\n instances.delete(args.audioId);\n return ok(api);\n }\n };\n}\n","/**\n * 临时文件:canvas 导出、拍照、选图、下载的结果都存在开发服务器上\n *\n * 返回的是 http 地址:image、video 组件只原样使用 http(s) 地址,其余的会被当成页面相对路径;\n * uploadFile 也能直接读取。\n */\n\nconst TEMP_DIR = '/__wxa__/tmp';\n\n/**\n * @param type 扩展名(如 png),读取时按它返回 Content-Type\n * @throws 开发服务器拒绝保存时,带上它给出的原因(如扩展名不合法)\n */\nexport async function saveTempFile(data: BodyInit, type: string): Promise<string> {\n const res = await fetch(`${TEMP_DIR}?type=${encodeURIComponent(type)}`, { method: 'POST', body: data });\n if (!res.ok) throw new Error(await res.text());\n const { url } = await res.json();\n return url;\n}\n\n/**\n * 临时文件的地址换成根路径(/__wxa__/tmp/…),其他地址原样返回。\n * 根路径在页面和组件里都按开发服务器的根目录解析,指向的还是同一个文件\n */\nexport function tempFileRootPath(url: string): string {\n const prefix = `${location.origin}${TEMP_DIR}/`;\n return url.startsWith(prefix) ? url.slice(location.origin.length) : url;\n}\n\n/** 临时文件的扩展名:优先用原文件名的,其次按 MIME 类型(如 image/png),都看不出来时用 fallback */\nexport function tempFileType(name: string, mimeType: string, fallback: string): string {\n const fromName = /\\.([a-z\\d]+)$/i.exec(name)?.[1];\n const fromType = /^[a-z]+\\/([a-z\\d]+)\\s*(;|$)/i.exec(mimeType)?.[1];\n return (fromName || fromType || fallback).toLowerCase();\n}\n\n/** 是不是开发服务器上的临时文件,保存的文件(wx.saveFile)也存在这里 */\nexport function isTempFile(filePath: unknown): filePath is string {\n return typeof filePath === 'string' && filePath.startsWith(`${location.origin}${TEMP_DIR}/`);\n}\n\n/** @returns 文件大小(字节),文件不存在时为 null */\nexport async function tempFileSize(url: string): Promise<number | null> {\n const res = await fetch(url, { method: 'HEAD' });\n return res.ok ? Number(res.headers.get('content-length')) : null;\n}\n\n/** 文件不存在时什么也不做 */\nexport async function removeTempFile(url: string): Promise<void> {\n await fetch(url, { method: 'DELETE' });\n}\n","/**\n * 文件系统 API:内存文件系统,以及读取代码包里的文件\n *\n * 带协议的路径(如 http://usr/)在内存文件系统里;不带协议的是代码包里的文件,由开发服务器提供。\n * 临时文件和保存的文件见 tempFiles.ts、savedFiles.ts。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\nimport { isTempFile, tempFileSize } from './tempFiles';\n\nconst DIR_MODE = 0o40755;\nconst FILE_MODE = 0o100644;\n\ninterface FsNode {\n dir: boolean;\n data: string;\n mtime: number;\n}\n\n/** 基础库会往 http://usr/ 写运行日志;业务代码也可以通过 FileSystemManager 读写 */\nexport class MemoryFileSystem {\n private nodes = new Map<string, FsNode>([['/', { dir: true, data: '', mtime: Date.now() }]]);\n\n normalize(filePath: string): string {\n const stripped = String(filePath || '').replace(/^[a-z]+:\\/\\/[^/]*/i, '');\n const parts: string[] = [];\n for (const part of stripped.split('/')) {\n if (!part || part === '.') continue;\n if (part === '..') parts.pop();\n else parts.push(part);\n }\n return '/' + parts.join('/');\n }\n\n stat(filePath: string): FsNode | undefined {\n return this.nodes.get(this.normalize(filePath));\n }\n\n mkdir(dirPath: string, recursive = false) {\n const target = this.normalize(dirPath);\n if (this.nodes.has(target)) throw new Error(`file already exists ${dirPath}`);\n const parent = target.slice(0, target.lastIndexOf('/')) || '/';\n if (!this.nodes.get(parent)?.dir) {\n if (!recursive) throw new Error(`no such file or directory ${dirPath}`);\n this.mkdir(parent, true);\n }\n this.nodes.set(target, { dir: true, data: '', mtime: Date.now() });\n }\n\n write(filePath: string, data: string, append = false) {\n const target = this.normalize(filePath);\n const parent = target.slice(0, target.lastIndexOf('/')) || '/';\n if (!this.nodes.get(parent)?.dir) throw new Error(`no such file or directory ${filePath}`);\n const existing = this.nodes.get(target);\n if (existing?.dir) throw new Error(`illegal operation on a directory ${filePath}`);\n this.nodes.set(target, { dir: false, data: append && existing ? existing.data + data : data, mtime: Date.now() });\n }\n\n read(filePath: string): string {\n const node = this.stat(filePath);\n if (!node) throw new Error(`no such file or directory, open ${filePath}`);\n if (node.dir) throw new Error(`illegal operation on a directory ${filePath}`);\n return node.data;\n }\n\n readdir(dirPath: string): string[] {\n const target = this.normalize(dirPath);\n if (!this.nodes.get(target)?.dir) throw new Error(`no such file or directory ${dirPath}`);\n const prefix = target === '/' ? '/' : target + '/';\n return [...this.nodes.keys()]\n .filter(key => key.startsWith(prefix) && key !== target && !key.slice(prefix.length).includes('/'))\n .map(key => key.slice(prefix.length));\n }\n\n remove(filePath: string, options: { dir: boolean; recursive?: boolean }) {\n const target = this.normalize(filePath);\n const node = this.nodes.get(target);\n if (!node) throw new Error(`no such file or directory ${filePath}`);\n if (node.dir !== options.dir) throw new Error(options.dir ? `not a directory ${filePath}` : `operation not permitted ${filePath}`);\n if (node.dir) {\n const children = this.readdir(target);\n if (children.length && !options.recursive) throw new Error(`directory not empty ${filePath}`);\n for (const key of [...this.nodes.keys()]) if (key.startsWith(target + '/')) this.nodes.delete(key);\n }\n this.nodes.delete(target);\n }\n}\n\nexport function createFileSystemApis(): Record<string, ApiHandler> {\n const fs = new MemoryFileSystem();\n\n const guard = (api: string, action: () => Record<string, unknown> | void) => {\n try {\n return ok(api, action() || {});\n } catch (error) {\n return fail(api, (error as Error).message);\n }\n };\n\n const statResult = (node: FsNode) => {\n const stats = {\n mode: node.dir ? DIR_MODE : FILE_MODE,\n size: node.data.length,\n lastAccessedTime: Math.floor(node.mtime / 1000),\n lastModifiedTime: Math.floor(node.mtime / 1000)\n };\n return { stats, ...stats };\n };\n\n const readMemoryFile: ApiHandler = (args, { api }) => guard(api, () => ({ data: fs.read(args.filePath) }));\n\n const apis: Record<string, ApiHandler> = {\n access: (args, { api }) => (fs.stat(args.path) ? ok(api) : fail(api, `no such file or directory ${args.path}`)),\n stat: (args, { api }) => {\n const node = fs.stat(args.path);\n return node ? ok(api, statResult(node)) : fail(api, `no such file or directory ${args.path}`);\n },\n mkdir: (args, { api }) => guard(api, () => fs.mkdir(args.dirPath, !!args.recursive)),\n writeFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ''))),\n appendFile: (args, { api }) => guard(api, () => fs.write(args.filePath, String(args.data ?? ''), true)),\n readdir: (args, { api }) => guard(api, () => ({ files: fs.readdir(args.dirPath) })),\n unlink: (args, { api }) => guard(api, () => fs.remove(args.filePath, { dir: false })),\n rmdir: (args, { api }) => guard(api, () => fs.remove(args.dirPath, { dir: true, recursive: !!args.recursive })),\n getFileInfo: (args, { api }) => {\n if (isTempFile(args.filePath)) {\n return tempFileSize(args.filePath).then(size => (size === null ? fail(api, 'file not exist') : ok(api, { size })));\n }\n const node = fs.stat(args.filePath);\n return node ? ok(api, { size: node.data.length }) : fail(api, 'file not exist');\n }\n };\n for (const name of Object.keys(apis)) apis[name + 'Sync'] = apis[name];\n\n return {\n ...apis,\n fs_appendFile: apis.appendFile,\n // 不带协议的是代码包里的文件,要向开发服务器取;readFileSync 同步返回不了,只读内存文件系统。\n // 内存文件系统的路径去掉了协议,不能先在里面找:用户目录下的同名文件会顶替代码包里的\n readFile: (args, context) => (/^[a-z]+:\\/\\//i.test(String(args.filePath))\n ? readMemoryFile(args, context)\n : readPackageFile(fs.normalize(args.filePath), args.encoding).then(\n data => ok(context.api, { data }),\n error => fail(context.api, error.message)\n )),\n readFileSync: readMemoryFile\n };\n}\n\n/**\n * 开发服务器以项目目录为根目录提供代码包里的文件\n * @param filePath 以 / 开头、相对代码包根目录的路径\n * @param encoding 不指定时得到 ArrayBuffer\n * @throws 文件不存在,或 encoding 不是 utf8\n */\nasync function readPackageFile(filePath: string, encoding: unknown): Promise<string | ArrayBuffer> {\n if (encoding !== undefined && encoding !== 'utf8' && encoding !== 'utf-8') {\n throw new Error(`读取代码包里的文件只支持 utf8 编码,或不指定编码得到 ArrayBuffer,不支持 ${encoding}`);\n }\n // encodeURI 不编码 # 和 ?,文件名里有的话会被当成地址的片段和查询\n const response = await fetch(filePath.split('/').map(encodeURIComponent).join('/'));\n if (!response.ok) throw new Error(`no such file or directory, open ${filePath}`);\n return encoding ? response.text() : response.arrayBuffer();\n}\n","/**\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 * 渲染层按需加载基础库文件:3.3.x、3.5.x 的 video 等组件不在 WAWebview.js 里,用到时才经 loadLibFilesSync 加载\n *\n * 脚本在调用返回前执行完:基础库在调用前后设置、清理 window.__Behaviour 等全局变量。\n * 各文件的内容按顺序放在 __codes 里交回,基础库从这里取 CSS 自己插入页面,所以 CSS 不当脚本执行。\n */\n\nimport { readSync, runScript } from '../../syncScript';\nimport { ApiHandler, ok } from './registry';\n\nexport interface LibFileApiOptions {\n windowOf: (webviewId: number) => Window | null | undefined;\n}\n\nexport function createLibFileApis(options: LibFileApiOptions): Record<string, ApiHandler> {\n const loadLibFiles: ApiHandler = (args, { api, from, webviewId }) => {\n const win = from === 'webview' ? options.windowOf(webviewId) : null;\n // 逻辑层也会调(加载广告、云开发等伴生 SDK),由 sdkStubs 在 wx 这一层接住,这里照旧返回成功\n if (!win) return ok(api);\n const codes = (args.paths as string[]).map(file => {\n const url = `/__baselib__/${file}`;\n const code = readSync(url);\n if (file.endsWith('.js')) runScript(win, url, code);\n return code;\n });\n return ok(api, { __codes: codes });\n };\n\n return { loadLibFiles, loadLibFilesSync: loadLibFiles };\n}\n","/**\n * map 组件用到的原生接口\n *\n * 平台是 devtools 时,基础库用腾讯地图网页 SDK 实现 map 组件,MapContext 的方法大多经 operateMap 消息发给它。\n * 有两处要原生接口配合:\n * - 要用户的当前位置时(moveToLocation、show-location),map 组件在渲染层调 private_geolocation,把结果当作\n * 腾讯位置服务定位接口返回的 JSON 文本解析,没有位置就按定位失败处理,带着经纬度的 moveToLocation 也会因此失败\n * - 3.10.1 起,带经纬度的 moveToLocation 不再经 operateMap 发给 map 组件,改调原生的 moveToMapLocation\n */\n\nimport type { ApiHandler, ApiRegistry, ApiResult } from './registry';\n\nexport interface MapApiOptions {\n /** 当前位置取这里 getLocation 的结果:和真机一样,地图上的当前位置就是 getLocation 的位置,mock 了也跟着变 */\n registry: ApiRegistry;\n operations: MapOperations;\n}\n\nexport function createMapApis({ registry, operations }: MapApiOptions): Record<string, ApiHandler> {\n return {\n private_geolocation: async (_args, context) => {\n const location = await registry.invoke('getLocation', { type: 'gcj02' }, { ...context, api: 'getLocation' }) as ApiResult;\n if (location.errMsg !== 'getLocation:ok') return JSON.stringify({ message: location.errMsg });\n return JSON.stringify({ result: { location: { lat: location.latitude, lng: location.longitude } } });\n },\n // 开发者工具上没有原生地图,照基础库的格式转给当前页的 map 组件\n moveToMapLocation: (args, { webviewId }) => operations.send(webviewId, { ...args, method: 'moveToMapLocation' })\n };\n}\n\n/**\n * 宿主替基础库发给 map 组件的操作:按 callbackId 收下 map 组件发回的 operateMapCallback。\n * 消息格式同基础库,包一层 { data, options }\n */\nexport class MapOperations {\n private readonly pending = new Map<string, (result: ApiResult) => void>();\n private seq = 0;\n\n /** @param publish 发给渲染层,渲染层的 WeixinJSBridge.subscribe 收到 */\n constructor(private readonly publish: (webviewId: number, event: string, data: unknown) => void) {}\n\n /** map 组件做完才返回;页面上没有这个 map 时一直不返回,同基础库自己发的操作 */\n send(webviewId: number, operation: Record<string, unknown>): Promise<ApiResult> {\n const callbackId = `wxa_${++this.seq}`;\n return new Promise(resolve => {\n this.pending.set(callbackId, resolve);\n this.publish(webviewId, 'operateMap', { data: { ...operation, callbackId }, options: { timestamp: Date.now() } });\n });\n }\n\n /** map 组件发回的 operateMapCallback:是宿主发的操作时收下并返回 true,不再交给逻辑层 */\n receive(message: any): boolean {\n const reply = message?.data;\n const resolve = this.pending.get(reply?.callbackId);\n if (!resolve) return false;\n this.pending.delete(reply.callbackId);\n resolve({ errMsg: reply.errMsg });\n return true;\n }\n}\n","/**\n * 媒体 API:选图(chooseImage / chooseMedia)、预览、读取图片信息、保存到相册\n *\n * 浏览器拿不到相册和相机,「从手机相册选择」和「拍摄」都打开文件选择框(手机浏览器上拍摄会打开相机)。\n * 选中的文件存成临时文件,路径可以直接作为 image 的 src,也可以直接 uploadFile。\n */\n\nimport type { FileChooserOptions } from '../ui/fileChooser';\nimport type { ActionSheetOptions } from '../ui/PhoneShell';\nimport { ApiHandler, fail, ok } from './registry';\nimport { saveTempFile, tempFileType } from './tempFiles';\n\nexport interface MediaApiOptions {\n /** @returns 用户点的下标,取消时为 null */\n showActionSheet: (options: ActionSheetOptions) => Promise<number | null>;\n /** @returns 用户关掉文件选择框时为 null */\n chooseFiles: (options: FileChooserOptions) => Promise<File[] | null>;\n /** 用户刚点击过、浏览器允许打开文件选择框 */\n hasUserActivation: () => boolean;\n showImagePreview: (urls: string[], current: number) => void;\n}\n\ntype Source = 'camera' | 'album';\n\n/** 菜单里的顺序和真机一致 */\nconst SOURCES: Source[] = ['camera', 'album'];\nconst SOURCE_LABELS: Record<Source, string> = { camera: '拍摄', album: '从手机相册选择' };\nconst DEFAULT_COUNT = 9;\n\nexport function createMediaApis(\n { showActionSheet, chooseFiles, hasUserActivation, showImagePreview }: MediaApiOptions\n): Record<string, ApiHandler> {\n /**\n * 和真机一样,相册和拍摄都可选时先弹菜单。浏览器只允许在用户点击后的几秒内打开文件选择框,\n * 没有经过点击、或者离点击已经太久时也先弹菜单,用户点菜单就是一次点击\n * @returns 用户取消时为 null;选的比 count 多时只取前 count 个\n */\n async function chooseImages(args: { count?: number; sourceType?: string[] }): Promise<File[] | null> {\n const allowed = SOURCES.filter(source => args.sourceType?.includes(source));\n const sources = allowed.length ? allowed : SOURCES;\n let source = sources[0];\n if (sources.length > 1 || !hasUserActivation()) {\n const index = await showActionSheet({ itemList: sources.map(item => SOURCE_LABELS[item]) });\n if (index === null) return null;\n source = sources[index];\n }\n\n const count = Math.max(1, Number(args.count) || DEFAULT_COUNT);\n const files = await chooseFiles({ accept: 'image/*', multiple: count > 1, capture: source === 'camera' });\n return files && files.slice(0, count);\n }\n\n const saveAll = (files: File[]) => Promise.all(files.map(file => saveTempFile(file, tempFileType(file.name, file.type, 'jpg'))));\n\n return {\n chooseImage: async (args, { api }) => {\n const files = await chooseImages(args);\n if (!files) return fail(api, 'cancel');\n const paths = await saveAll(files);\n return ok(api, { tempFilePaths: paths, tempFiles: files.map((file, i) => ({ path: paths[i], size: file.size })) });\n },\n\n chooseMedia: async (args, { api }) => {\n const mediaType: string[] = args.mediaType?.length ? args.mediaType : ['image', 'video'];\n if (!mediaType.includes('image') && !mediaType.includes('mix')) return fail(api, 'wxa-runner 暂不支持选择视频');\n const files = await chooseImages(args);\n if (!files) return fail(api, 'cancel');\n const paths = await saveAll(files);\n return ok(api, {\n type: 'image',\n tempFiles: files.map((file, i) => ({ tempFilePath: paths[i], size: file.size, fileType: 'image' }))\n });\n },\n\n // 基础库已经把 current 换成了 urls 里的地址;也兼容直接传下标\n previewImage: args => {\n const urls: string[] = (args.urls || []).map(String);\n if (!urls.length) return;\n const current = typeof args.current === 'number' ? args.current : urls.indexOf(args.current);\n showImagePreview(urls, Math.max(current, 0));\n },\n\n // 网络图片基础库已先下载成本地地址,包内图片已换成相对小程序根目录的路径\n getImageInfo: async args => {\n const src = String(args.src || '');\n const blob = await fetchFile(src);\n const bitmap = await createImageBitmap(blob);\n const info = { width: bitmap.width, height: bitmap.height, type: imageType(blob), orientation: 'up' };\n bitmap.close();\n return info;\n },\n\n // 浏览器没有相册,保存到相册就是下载这张图片\n saveImageToPhotosAlbum: async args => {\n const filePath = String(args.filePath || '');\n const link = document.createElement('a');\n link.href = URL.createObjectURL(await fetchFile(filePath));\n link.download = filePath.split(/[?#]/)[0].split('/').pop() || 'image';\n link.click();\n // 立即释放会让还没开始的下载失败\n setTimeout(() => URL.revokeObjectURL(link.href), 60_000);\n }\n };\n}\n\n/** @throws 文件不存在时 */\nasync function fetchFile(path: string): Promise<Blob> {\n const url = /^[a-z][a-z\\d+.-]*:/i.test(path) ? path : '/' + path.replace(/^\\//, '');\n const res = await fetch(url);\n if (!res.ok) throw new Error(`file not exist ${path}`);\n return res.blob();\n}\n\n/** 与真机一致的格式名:png、jpeg、gif 等,看不出来时为 unknown */\nfunction imageType(blob: Blob): string {\n return /^image\\/([a-z\\d]+)/i.exec(blob.type)?.[1].toLowerCase() || 'unknown';\n}\n","/**\n * 其余 API:开放接口 Mock、剪贴板等\n *\n * 开放接口(登录、用户信息、支付)在浏览器里无法真实调用,返回可预测的假数据,\n * 测试中可以用 __wxa_test_api__.mock() 覆盖。开启 --real-login 时,登录和手机号经开发服务器向微信换取真实结果。\n */\n\nimport { ApiHandler, ApiResult, fail, ok } from './registry';\nimport { saveTempFile } from './tempFiles';\n\nexport interface MiscApiOptions {\n realLogin?: boolean;\n /** 真实登录失败时触发,用来在页面上提示开发者;业务代码照常收到 fail */\n onRealLoginFail?: (api: string, reason: string) => void;\n}\n\nexport function createMiscApis(appid: string, options?: MiscApiOptions): Record<string, ApiHandler> {\n const realLogin = async (api: string, url: string) => {\n try {\n return await postDevServer(url);\n } catch (error) {\n options?.onRealLoginFail?.(api, (error as Error).message);\n throw error;\n }\n };\n\n return {\n // canvas 导出图片、拍照、录像的结果都经过这里\n base64ToTempFilePath: async args => {\n const bytes = Uint8Array.from(atob(String(args.base64Data || '')), char => char.charCodeAt(0));\n return { tempFilePath: await saveTempFile(bytes, String(args.fileType || 'png')) };\n },\n\n // 基础库经这两个接口向后台拉各种配置和小程序信息\n operateWXData: (args, { api }) => {\n if (args.data?.api_name === 'webapi_getwxanetwork') return bizDomainUnavailable(api);\n if (args.data?.api_name === 'webapi_getwxauserprivacyauthinfo') return ok(api, { data: { data: JSON.stringify(PRIVACY_AUTH_INFO) } });\n return ok(api);\n },\n getAppContact: (args, { api }) =>\n args.keyPath === 'WxaAppInfo.Network.BizDomain' ? bizDomainUnavailable(api) : ok(api),\n\n // 真实登录失败时明确返回 fail,不退回假数据:配置或登录态的问题要让开发者马上发现\n login: options?.realLogin\n ? async (_args, { api }) => ok(api, { code: (await realLogin(api, '/__wxa__/api/login')).code })\n : (_args, { api }) => ok(api, { code: `wxa_mock_code_${Date.now().toString(36)}` }),\n // 基础库只从 JSON.parse(data) 里取手机号的 code\n getPhoneNumber: options?.realLogin\n ? async (_args, { api }) => ok(api, await realLogin(api, '/__wxa__/api/phone-number'))\n : (_args, { api }) => ok(api, { data: JSON.stringify({ code: `mock_phone_code_${Date.now()}` }), encryptedData: 'mock_encrypted', iv: 'mock_iv' }),\n checkSession: () => undefined,\n authorize: () => undefined,\n getSetting: (_args, { api }) => ok(api, {\n authSetting: { 'scope.userInfo': true, 'scope.userLocation': true }\n }),\n openSetting: (_args, { api }) => ok(api, { authSetting: {} }),\n getUserInfo: (_args, { api }) => ok(api, { userInfo: mockUser(), rawData: JSON.stringify(mockUser()), signature: '', encryptedData: '', iv: '' }),\n getUserProfile: (_args, { api }) => ok(api, { userInfo: mockUser(), rawData: JSON.stringify(mockUser()), signature: '', encryptedData: '', iv: '' }),\n getAccountInfoSync: (_args, { api }) => ok(api, { miniProgram: { appId: appid, envVersion: 'develop', version: '' } }),\n requestPayment: (_args, { api }) => fail(api, '浏览器运行时不支持支付,请在测试中通过 __wxa_test_api__.mock(\"requestPayment\", ...) 模拟'),\n getLocation: (_args, { api }) => ok(api, { latitude: 39.908823, longitude: 116.39747, speed: 0, accuracy: 65, altitude: 0, verticalAccuracy: 65, horizontalAccuracy: 65 }),\n scanCode: (_args, { api }) => fail(api, 'cancel'),\n\n setClipboardData: async (args) => {\n clipboard = String(args.data ?? '');\n await navigator.clipboard?.writeText(clipboard).catch(() => undefined);\n },\n getClipboardData: (_args, { api }) => ok(api, { data: clipboard }),\n makePhoneCall: (args) => console.info(`[wxa-runner] makePhoneCall ${args.phoneNumber}`),\n showShareMenu: () => undefined,\n hideShareMenu: () => undefined,\n updateShareMenu: () => undefined\n };\n}\n\nlet clipboard = '';\n\n/** @throws 开发服务器返回的失败原因(由注册表转成 xxx:fail),返回的不是 JSON 时带上状态码 */\nasync function postDevServer(url: string): Promise<Record<string, any>> {\n const response = await fetch(url, { method: 'POST' });\n const body = await response.json().catch(() => null);\n if (!response.ok || !body) throw new Error(body?.error || `开发服务器返回 HTTP ${response.status}`);\n return body;\n}\n\nfunction mockUser() {\n return { nickName: 'wxa-runner', avatarUrl: '', gender: 0, country: '', province: '', city: '', language: 'zh_CN' };\n}\n\n/**\n * 隐私授权信息:不用弹窗、没有未授权的接口,等于用户已经同意了隐私协议。基础库调用剪贴板、定位、选图等涉及隐私的接口前\n * 先拉取它,从结果的 data 里解析;2.32.3 拿不到时在回调里抛错,这些接口一直不回调。wording 是弹窗的文案,不弹窗也要有\n */\nconst PRIVACY_AUTH_INFO = { action_code: 0, need_popup_scope_list: [], unauth_scope_list: [], wording: {} };\n\n/**\n * 不校验业务域名,等同开发者工具的「不校验合法域名、web-view(业务域名)」:拿到空的业务域名列表时,\n * 基础库会把 web-view 事件里的网页地址清空,只有拉取失败才不校验。不同版本从不同的原生接口拉取\n * (如 3.13.2 用 getAppContact,3.17.3 用 operateWXData),两个都要失败\n */\nfunction bizDomainUnavailable(api: string): ApiResult {\n return fail(api, 'not available in wxa-runner');\n}\n","/**\n * 网络 API:wx.request / downloadFile / uploadFile / connectSocket\n *\n * 基础库 3.x 的协议是「创建任务同步返回 taskId,结果通过 on<Type>TaskStateChange 事件推送」。\n * HTTP 请求经开发服务器的 /__wxa__/proxy 转发:既绕开 CORS,也能携带浏览器禁止设置的\n * cookie / referer 等请求头。\n *\n * 基础库自己的请求(数据上报、配置拉取等)不发出,只放行 InnerAudioContext 下载音频,见 byCaller。\n */\n\nimport type { MockRequest } from '../../../setup';\nimport { ApiHandler, fail, ok } from './registry';\nimport type { RequestRoutes } from './routes';\nimport { saveTempFile, tempFileType } from './tempFiles';\n\nexport interface NetworkApiOptions {\n /** 向逻辑层派发事件 */\n emit: (event: string, data: Record<string, unknown>) => void;\n defaultTimeout: () => number;\n /** 请求拦截,只作用于 wx.request */\n routes?: RequestRoutes;\n /** wx.request 发出时调用,早于拦截和转发 */\n onRequest?: (request: RecordedRequest) => void;\n}\n\n/** 小程序发出的一个 wx.request */\nexport interface RecordedRequest extends MockRequest {\n /** 拦截它的规则(setup 的 network.routes 或测试 API 的 route),经代理发往网络时为 null */\n routedBy: string | null;\n}\n\n/** 最近发出的 wx.request。平时调试不跑测试时也在记录,只保留最近的 limit 个,内存不会一直增长 */\nexport class RequestLog {\n private items: RecordedRequest[] = [];\n\n constructor(private readonly limit = 1000) {}\n\n add(request: RecordedRequest) {\n this.items.push(request);\n if (this.items.length > this.limit) this.items.splice(0, this.items.length - this.limit);\n }\n\n /** 按发出顺序;返回副本,修改它不影响记录 */\n list(): RecordedRequest[] {\n return this.items.map(request => ({ ...request, header: { ...request.header } }));\n }\n\n clear() {\n this.items = [];\n }\n}\n\ninterface ProxyResponse {\n statusCode: number;\n header: Record<string, string>;\n cookies: string[];\n response: Response;\n}\n\nlet taskSeq = 0;\n\nexport function createNetworkApis(options: NetworkApiOptions): Record<string, ApiHandler> {\n const controllers = new Map<string, AbortController>();\n const sockets = new Map<string, WebSocket>();\n const { emit } = options;\n\n const startTask = (args: any, run: (signal: AbortSignal, id: string) => Promise<void>): string => {\n const id = String(++taskSeq);\n const controller = new AbortController();\n const timeout = args.timeout || options.defaultTimeout();\n const timer = timeout > 0 ? setTimeout(() => controller.abort(new Error('timeout')), timeout) : null;\n controllers.set(id, controller);\n // 任务 id 先同步返回给基础库,结果事件之后再推送\n setTimeout(() => {\n run(controller.signal, id).finally(() => {\n if (timer) clearTimeout(timer);\n controllers.delete(id);\n });\n }, 0);\n return id;\n };\n\n const abortTask = (args: any, key: string) => {\n if (args.operationType === 'abort') controllers.get(String(args[key]))?.abort(new Error('abort'));\n };\n\n const createRequestTask: ApiHandler = (args, { api }) => {\n const request: MockRequest = { url: args.url, method: (args.method || 'GET').toUpperCase(), header: { ...args.header }, data: args.data };\n // 发出时就确定是否拦截:记录里能看到命中的规则,之后增删规则不影响已发出的请求\n const route = options.routes?.match(request);\n options.onRequest?.({ ...request, header: { ...request.header }, routedBy: route ? route.pattern : null });\n\n const requestTaskId = startTask(args, async (signal, id) => {\n try {\n const mocked = route && await route.respond(signal);\n const res: ProxyResponse = mocked\n ? { statusCode: mocked.statusCode, header: mocked.header, cookies: [], response: new Response(mocked.body) }\n : await proxyFetch(request.url, { method: request.method, header: args.header, body: args.data, signal });\n emit('onRequestTaskStateChange', {\n requestTaskId: id, state: 'headersReceived', header: res.header, statusCode: res.statusCode, cookies: res.cookies\n });\n // 和真机一样由 responseType 决定拿到文本还是 ArrayBuffer,与响应内容无关,拦截规则给的响应也是\n const data = args.responseType === 'arraybuffer' ? await res.response.arrayBuffer() : await res.response.text();\n emit('onRequestTaskStateChange', {\n requestTaskId: id, state: 'success', data, statusCode: res.statusCode, header: res.header, cookies: res.cookies, profile: {}\n });\n } catch (error) {\n emit('onRequestTaskStateChange', { requestTaskId: id, state: 'fail', errMsg: `request:fail ${reason(error)}` });\n }\n });\n return ok(api, { requestTaskId });\n };\n\n const createDownloadTask: ApiHandler = (args, { api }) => {\n const downloadTaskId = startTask(args, async (signal, id) => {\n try {\n const res = await proxyFetch(args.url, { method: 'GET', header: args.header, signal });\n emit('onDownloadTaskStateChange', { downloadTaskId: id, state: 'headersReceived', header: res.header, cookies: res.cookies });\n const blob = await res.response.blob();\n emit('onDownloadTaskStateChange', {\n downloadTaskId: id, state: 'progressUpdate', progress: 100, totalBytesWritten: blob.size, totalBytesExpectedToWrite: blob.size\n });\n // 不用 blob: 地址:image 组件会把它当成页面相对路径\n const fileName = new URL(args.url).pathname.split('/').pop() || '';\n const tempFilePath = await saveTempFile(blob, tempFileType(fileName, blob.type, 'tmp'));\n emit('onDownloadTaskStateChange', {\n downloadTaskId: id,\n state: 'success',\n tempFilePath,\n statusCode: res.statusCode,\n header: res.header,\n profile: {}\n });\n } catch (error) {\n emit('onDownloadTaskStateChange', { downloadTaskId: id, state: 'fail', errMsg: `downloadFile:fail ${reason(error)}` });\n }\n });\n return ok(api, { downloadTaskId });\n };\n\n const createUploadTask: ApiHandler = (args, { api }) => {\n const uploadTaskId = startTask(args, async (signal, id) => {\n try {\n const file = await (await fetch(args.filePath)).blob();\n const form = new FormData();\n for (const [key, value] of Object.entries(args.formData || {})) form.append(key, String(value));\n form.append(args.name || 'file', file, String(args.filePath).split('/').pop() || 'file');\n\n const res = await proxyFetch(args.url, { method: 'POST', header: args.header, body: form, signal });\n const data = await res.response.text();\n emit('onUploadTaskStateChange', {\n uploadTaskId: id, state: 'progressUpdate', progress: 100, totalBytesSent: file.size, totalBytesExpectedToSend: file.size\n });\n emit('onUploadTaskStateChange', { uploadTaskId: id, state: 'success', data, statusCode: res.statusCode, header: res.header });\n } catch (error) {\n emit('onUploadTaskStateChange', { uploadTaskId: id, state: 'fail', errMsg: `uploadFile:fail ${reason(error)}` });\n }\n });\n return ok(api, { uploadTaskId });\n };\n\n const createSocketTask: ApiHandler = (args, { api }) => {\n const socketTaskId = String(++taskSeq);\n let socket: WebSocket;\n try {\n socket = new WebSocket(args.url, args.protocols && args.protocols.length ? args.protocols : undefined);\n } catch (error) {\n return fail(api, reason(error));\n }\n socket.binaryType = 'arraybuffer';\n sockets.set(socketTaskId, socket);\n socket.onopen = () => emit('onSocketTaskStateChange', { socketTaskId, state: 'open', header: {}, profile: {} });\n socket.onmessage = event => emit('onSocketTaskStateChange', { socketTaskId, state: 'message', data: event.data });\n socket.onerror = () => emit('onSocketTaskStateChange', { socketTaskId, state: 'error', errMsg: 'connectSocket:fail' });\n socket.onclose = event => {\n sockets.delete(socketTaskId);\n emit('onSocketTaskStateChange', { socketTaskId, state: 'close', code: event.code, reason: event.reason });\n };\n return ok(api, { socketTaskId });\n };\n\n const operateSocketTask: ApiHandler = (args, { api }) => {\n const socket = sockets.get(String(args.socketTaskId));\n if (!socket) return fail(api, 'socket task not found');\n if (args.operationType === 'send') {\n if (socket.readyState !== WebSocket.OPEN) return fail(api, 'socket is not open');\n socket.send(args.data);\n } else if (args.operationType === 'close') {\n socket.close(args.code || 1000, args.reason);\n }\n return ok(api);\n };\n\n /** 不是小程序的 wx.request:不记录,也不经拦截规则 */\n const downloadAudio: ApiHandler = (args, { api }) => {\n const requestTaskId = startTask(args, async (signal, id) => {\n try {\n const res = await proxyFetch(args.url, { method: 'GET', header: args.header, signal });\n const meta = { requestTaskId: id, statusCode: res.statusCode, header: res.header, cookies: res.cookies };\n emit('onRequestTaskStateChange', { ...meta, state: 'headersReceived' });\n emit('onRequestTaskStateChange', { ...meta, state: 'success', data: await res.response.arrayBuffer(), profile: {} });\n } catch (error) {\n emit('onRequestTaskStateChange', { requestTaskId: id, state: 'fail', errMsg: `request:fail ${reason(error)}` });\n }\n });\n return ok(api, { requestTaskId });\n };\n\n // 基础库自己的请求只放行下载音频\n const requestTask = byCaller(createRequestTask, (args, context) => (isAudioDownload(args)\n ? downloadAudio(args, context)\n : rejectBaseLib(args, context)));\n const downloadTask = byCaller(createDownloadTask);\n const uploadTask = byCaller(createUploadTask);\n\n return {\n createRequestTask: requestTask,\n createRequestTaskAsync: requestTask,\n createDownloadTask: downloadTask,\n createDownloadTaskAsync: downloadTask,\n createUploadTask: uploadTask,\n createUploadTaskAsync: uploadTask,\n createSocketTask: byCaller(createSocketTask),\n operateRequestTask: args => abortTask(args, 'requestTaskId'),\n operateDownloadTask: args => abortTask(args, 'downloadTaskId'),\n operateUploadTask: args => abortTask(args, 'uploadTaskId'),\n operateSocketTask\n };\n}\n\nconst rejectBaseLib: ApiHandler = (_args, { api }) => fail(api, '基础库内部的网络请求,wxa-runner 不发出');\n\n/**\n * 小程序的请求交给 forApp;基础库自己的网络请求(数据上报、配置拉取等)默认直接按失败返回:不发往网络,也不记入请求记录\n *\n * 它们连的是微信后台,与被测的小程序无关,测试和 CI 里不该因此产生对外请求。基础库通过\n * _requestSkipCheckDomain 一类内部接口发出,带 __skipDomainCheck__ 标记;小程序的 wx.request 不带\n */\nfunction byCaller(forApp: ApiHandler, forBaseLib = rejectBaseLib): ApiHandler {\n return (args, context) => (args?.__skipDomainCheck__ === true ? forBaseLib(args, context) : forApp(args, context));\n}\n\n/**\n * 基础库为 InnerAudioContext 下载音频的请求:用 Web Audio 播放时先把音频地址下载成 ArrayBuffer\n * (3.5.8 起平台是 devtools 时默认用 Web Audio,更早的版本要业务指定 useWebAudioImplement,否则调原生接口,见 audio.ts)。\n * 2.32.3 到 3.17.4 都是这个形状,基础库自己的其他请求不会同时带这两个参数\n */\nfunction isAudioDownload(args: any): boolean {\n return args.responseType === 'arraybuffer' && args.enableCache === true;\n}\n\nexport async function proxyFetch(\n url: string,\n init: { method: string; header?: Record<string, string>; body?: unknown; signal?: AbortSignal }\n): Promise<ProxyResponse> {\n if (!/^https?:\\/\\//i.test(url)) throw new Error(`invalid url \"${url}\"`);\n\n const hasBody = init.body !== undefined && init.body !== '' && !['GET', 'HEAD'].includes(init.method);\n const response = await fetch(`/__wxa__/proxy?url=${encodeURIComponent(url)}`, {\n method: init.method,\n headers: { 'x-wxa-headers': JSON.stringify(init.header || {}) },\n body: hasBody ? init.body as BodyInit : undefined,\n signal: init.signal\n });\n\n if (response.headers.get('x-wxa-proxy-error')) {\n throw new Error(await response.text());\n }\n\n return {\n statusCode: response.status,\n header: JSON.parse(decodeURIComponent(response.headers.get('x-wxa-headers') || '%7B%7D')),\n cookies: JSON.parse(decodeURIComponent(response.headers.get('x-wxa-set-cookie') || '%5B%5D')),\n response\n };\n}\n\nfunction reason(error: unknown): string {\n if (error instanceof DOMException && error.name === 'AbortError') return 'abort';\n return error instanceof Error ? error.message : String(error);\n}\n","/**\n * picker 组件背后的原生选择器\n *\n * 基础库把每列的选项文字交给宿主,宿主弹出选择器,再按基础库约定的格式返回用户的选择:\n * selector showPickerView → { index }\n * multiSelector showMultiPickerView → { current },选择期间用户换列时派发 onMultiPickerViewChange,\n * 页面改了 range 后基础库调 updateMultiPickerView 换掉那一列\n * date / time showDatePickerView → { value: 'YYYY-MM-DD' / 'HH:mm' }\n * region getRegionData 拿省市区数据后自己解析,再走 showMultiPickerView;\n * 指定了 level 时走 showAddressPickerView → { value: { value, code, postcode } }\n *\n * 日期、地区这类列之间有联动的,联动规则在这里实现,选择器界面只负责显示列。\n */\n\nimport type { PickerOptions, PickerSession } from '../ui/Picker';\nimport { ApiHandler, fail, ok } from './registry';\n\nexport type RegionDataKind = 'districts' | 'streets';\n\nexport interface PickerApiOptions {\n showPicker(options: PickerOptions): PickerSession;\n /** 派发给渲染层的原生事件(渲染层里 WeixinJSBridge.on 收到) */\n emitToWebview(webviewId: number, event: string, data: unknown): void;\n /** 开发者工具自带的行政区划数据,districts 到区县,streets 到街道 */\n loadRegionData(kind: RegionDataKind): Promise<string>;\n}\n\nexport async function fetchRegionData(kind: RegionDataKind): Promise<string> {\n const res = await fetch(`/__wxa__/region/${kind}`);\n if (!res.ok) throw new Error('没有找到行政区划数据,地区选择器需要本机微信开发者工具自带的数据');\n return res.text();\n}\n\nexport function createPickerApis({ showPicker, emitToWebview, loadRegionData }: PickerApiOptions): Record<string, ApiHandler> {\n let multiPicker: PickerSession | null = null;\n let regionTree: Promise<RegionNode[]> | null = null;\n\n const loadRegionTree = () => {\n regionTree ??= loadRegionData('streets').then(parseRegionTree);\n // 失败了下次重新加载\n regionTree.catch(() => {\n regionTree = null;\n });\n return regionTree;\n };\n\n /** 弹出列之间有联动的选择器:用户改了某列后,后面各列按 model 重新生成 */\n const showCascade = (model: CascadeModel, headerText?: string) => {\n const session: PickerSession = showPicker({\n columns: model.columns(),\n current: model.current(),\n headerText,\n onColumnChange(column, index) {\n model.select(column, index);\n const columns = model.columns();\n const current = model.current();\n for (let next = column + 1; next < columns.length; next++) session.setColumn(next, columns[next], current[next]);\n }\n });\n return session.result;\n };\n\n return {\n showPickerView: async (args, { api }) => {\n const result = await showPicker({\n columns: [labels(args.array)],\n current: [Number(args.current) || 0],\n headerText: args.headerText\n }).result;\n return result ? ok(api, { index: result[0] }) : fail(api, 'cancel');\n },\n\n showMultiPickerView: async (args, { api, webviewId }) => {\n const session = showPicker({\n columns: (args.array || []).map(labels),\n current: (args.current || []).map((index: unknown) => Number(index) || 0),\n headerText: args.headerText,\n onColumnChange: (column, current) => emitToWebview(webviewId, 'onMultiPickerViewChange', { column, current })\n });\n multiPicker = session;\n const result = await session.result;\n if (multiPicker === session) multiPicker = null;\n return result ? ok(api, { current: result }) : fail(api, 'cancel');\n },\n\n updateMultiPickerView: (args, { api }) => {\n if (!multiPicker) return fail(api, 'no picker is showing');\n multiPicker.setColumn(Number(args.column), labels(args.array), Number(args.current) || 0);\n return ok(api);\n },\n\n showDatePickerView: async (args, { api }) => {\n const model = new DateCascade(args.mode === 'time' ? 'time' : 'date', args.fields, args.range || {}, String(args.current || ''));\n const result = await showCascade(model, args.headerText);\n return result ? ok(api, { value: model.value() }) : fail(api, 'cancel');\n },\n\n showAddressPickerView: async (args, { api }) => {\n let tree: RegionNode[];\n try {\n tree = await loadRegionTree();\n } catch (error) {\n return fail(api, (error as Error).message);\n }\n const model = new RegionCascade(tree, REGION_LEVELS[args.mode] || 3, args.current || []);\n const result = await showCascade(model);\n return result ? ok(api, { value: model.value() }) : fail(api, 'cancel');\n },\n\n getRegionData: async (_args, { api }) => {\n try {\n return ok(api, { data: await loadRegionData('districts') });\n } catch (error) {\n return fail(api, (error as Error).message);\n }\n }\n };\n}\n\nfunction labels(items: unknown): string[] {\n return Array.isArray(items) ? items.map(item => String(item)) : [];\n}\n\ninterface CascadeModel {\n columns(): string[][];\n current(): number[];\n select(column: number, index: number): void;\n}\n\n// -----------------------------------------------------------------------------\n// 日期与时间\n// -----------------------------------------------------------------------------\n\nconst DEFAULT_DATE_RANGE = { start: [1900, 1, 1], end: [2100, 12, 31] };\nconst DATE_DEPTH: Record<string, number> = { year: 1, month: 2, day: 3 };\n\n/**\n * 每列是一段连续的数字(年、月、日或时、分)。某列的取值范围取决于前面各列:\n * 前面各列都落在 start 上时,这一列不能早于 start;end 同理;日的上限还取决于年月。\n * 改了某列后,后面各列保持原值,超出新范围时落到最近的边界(1 月 31 日切到 2 月变成 29 日)。\n */\nclass DateCascade implements CascadeModel {\n private readonly depth: number;\n private readonly min: number[];\n private readonly max: number[];\n private readonly parts: number[] = [];\n\n constructor(private readonly mode: 'date' | 'time', fields: unknown, range: { start?: string; end?: string }, current: string) {\n this.depth = mode === 'time' ? 2 : DATE_DEPTH[String(fields)] || 3;\n const lowest = mode === 'time' ? [0, 0] : DEFAULT_DATE_RANGE.start;\n const highest = mode === 'time' ? [23, 59] : DEFAULT_DATE_RANGE.end;\n this.min = fillParts(parseParts(range.start), lowest);\n this.max = fillParts(parseParts(range.end), highest);\n // 早于 start 或晚于 end 时整体落到那个边界,而不是逐列裁剪(2019-06-01 → 2020-03-15,而非 2020-06-01)\n let initial = fillParts(parseParts(current), lowest);\n if (compareParts(initial, this.min, this.depth) < 0) initial = this.min;\n else if (compareParts(initial, this.max, this.depth) > 0) initial = this.max;\n for (let column = 0; column < this.depth; column++) {\n const [low, high] = this.bounds(column);\n this.parts[column] = clamp(initial[column], low, high);\n }\n }\n\n columns(): string[][] {\n return this.parts.map((_, column) => {\n const [low, high] = this.bounds(column);\n return Array.from({ length: high - low + 1 }, (__, offset) => this.label(column, low + offset));\n });\n }\n\n current(): number[] {\n return this.parts.map((value, column) => value - this.bounds(column)[0]);\n }\n\n select(column: number, index: number) {\n this.parts[column] = this.bounds(column)[0] + index;\n for (let next = column + 1; next < this.depth; next++) {\n const [low, high] = this.bounds(next);\n this.parts[next] = clamp(this.parts[next], low, high);\n }\n }\n\n value(): string {\n if (this.mode === 'time') return this.parts.map(pad).join(':');\n return this.parts.map((value, column) => (column === 0 ? String(value) : pad(value))).join('-');\n }\n\n private bounds(column: number): [number, number] {\n const before = this.parts.slice(0, column);\n let [low, high] = this.naturalBounds(column);\n if (before.every((value, i) => value === this.min[i])) low = Math.max(low, this.min[column]);\n if (before.every((value, i) => value === this.max[i])) high = Math.min(high, this.max[column]);\n return [low, Math.max(low, high)];\n }\n\n private naturalBounds(column: number): [number, number] {\n if (this.mode === 'time') return column === 0 ? [0, 23] : [0, 59];\n if (column === 0) return [this.min[0], this.max[0]];\n if (column === 1) return [1, 12];\n return [1, new Date(this.parts[0], this.parts[1], 0).getDate()];\n }\n\n private label(column: number, value: number): string {\n if (this.mode === 'time') return pad(value);\n return value + ['年', '月', '日'][column];\n }\n}\n\nfunction parseParts(text: string | undefined): number[] {\n return String(text || '').split(/[-:]/).filter(Boolean).map(Number).filter(part => Number.isInteger(part));\n}\n\nfunction fillParts(parts: number[], defaults: number[]): number[] {\n return parts.length ? defaults.map((value, i) => parts[i] ?? value) : defaults;\n}\n\nfunction compareParts(a: number[], b: number[], depth: number): number {\n for (let i = 0; i < depth; i++) {\n if (a[i] !== b[i]) return a[i] - b[i];\n }\n return 0;\n}\n\nfunction clamp(value: number, low: number, high: number): number {\n return Math.min(high, Math.max(low, value));\n}\n\nfunction pad(value: number): string {\n return String(value).padStart(2, '0');\n}\n\n// -----------------------------------------------------------------------------\n// 地区\n// -----------------------------------------------------------------------------\n\nconst REGION_LEVELS: Record<string, number> = { province: 1, city: 2, region: 3, 'sub-district': 4 };\n\ninterface RegionNode {\n name: string;\n code: string;\n postcode: string;\n children: RegionNode[];\n}\n\n/** 数据每行是「编码、名称、邮编」,以 tab 分隔,名称前的 tab 个数就是层级 */\nfunction parseRegionTree(text: string): RegionNode[] {\n const roots: RegionNode[] = [];\n const lastAtDepth: RegionNode[] = [];\n for (const line of text.split('\\n')) {\n const match = /^(\\d+)(\\t+)([^\\t]+)\\t(\\d+)/.exec(line.trimEnd());\n if (!match) continue;\n const depth = match[2].length;\n const node: RegionNode = { code: match[1], name: match[3].trim(), postcode: match[4], children: [] };\n if (depth === 1) roots.push(node);\n else lastAtDepth[depth - 2]?.children.push(node);\n lastAtDepth[depth - 1] = node;\n lastAtDepth.length = depth;\n }\n return roots;\n}\n\n/** 省、市、区、街道逐级联动:改了上级后,下级回到新上级的第一项 */\nclass RegionCascade implements CascadeModel {\n private readonly path: number[];\n\n constructor(private readonly tree: RegionNode[], private readonly levels: number, names: unknown[]) {\n this.path = [];\n for (let level = 0; level < levels; level++) {\n const index = this.options(level).findIndex(node => node.name === names[level]);\n this.path[level] = Math.max(0, index);\n }\n }\n\n columns(): string[][] {\n return this.path.map((_, level) => this.options(level).map(node => node.name));\n }\n\n current(): number[] {\n return [...this.path];\n }\n\n select(column: number, index: number) {\n this.path[column] = index;\n for (let level = column + 1; level < this.levels; level++) this.path[level] = 0;\n }\n\n value(): { value: string[]; code: string[]; postcode: string } {\n const nodes = this.selectedNodes();\n return {\n value: nodes.map(node => node.name),\n code: nodes.map(node => node.code),\n postcode: nodes.at(-1)?.postcode ?? ''\n };\n }\n\n /** 某一级可选的节点:上一级选中节点的下级 */\n private options(level: number): RegionNode[] {\n if (level === 0) return this.tree;\n return this.selectedNodes(level).at(-1)?.children ?? [];\n }\n\n private selectedNodes(levels = this.levels): RegionNode[] {\n const nodes: RegionNode[] = [];\n let options = this.tree;\n for (let level = 0; level < levels; level++) {\n const node = options[this.path[level]];\n if (!node) break;\n nodes.push(node);\n options = node.children;\n }\n return nodes;\n }\n}\n","/**\n * 请求拦截:setup 的 network.routes、测试 API 的 route 声明的接口不发往网络,直接返回给定的响应\n *\n * 规则写法:'[METHOD ]URL',如 'POST https://api.example.com/login'。URL 里 * 匹配一段路径,\n * ** 匹配任意内容(可以不写域名,按路径匹配);查询参数和 hash 不参与匹配。\n */\n\nimport type { MockRequest, MockResponse, RouteHandler } from '../../../setup';\n\nconst METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT'];\n\ninterface Route {\n pattern: string;\n matches: RequestMatcher;\n handler: RouteHandler;\n}\n\ntype RequestMatcher = (request: Pick<MockRequest, 'url' | 'method'>) => boolean;\n\nexport interface MatchedRoute {\n /** 命中的规则,即添加时的写法 */\n pattern: string;\n /**\n * 响应体原样是文本或二进制,小程序拿到哪种由请求的 responseType 决定\n * @throws 延迟期间 signal 被 abort 时,抛出 signal.reason\n */\n respond(signal?: AbortSignal): Promise<{ statusCode: number; header: Record<string, string>; body: string | BufferSource }>;\n}\n\nexport class RequestRoutes {\n private routes: Route[] = [];\n\n /**\n * 后添加的规则优先\n * @throws 规则写法不对时\n */\n add(pattern: string, handler: RouteHandler) {\n const matches = compilePattern(pattern);\n if (typeof handler !== 'function' && (handler === null || typeof handler !== 'object')) {\n throw new Error('拦截规则的值需要是响应对象 { status?, header?, body?, delay? },或按请求返回响应的函数');\n }\n if (typeof handler === 'object') checkDelay(handler.delay);\n this.routes.unshift({ pattern, matches, handler });\n }\n\n /** 删除按这个写法添加的规则,不传时删除全部 */\n remove(pattern?: string) {\n this.routes = pattern === undefined ? [] : this.routes.filter(route => route.pattern !== pattern);\n }\n\n /** 找到匹配的规则,没有时返回 undefined。响应在调用 respond 时才生成 */\n match(request: MockRequest): MatchedRoute | undefined {\n const route = this.routes.find(r => r.matches(request));\n if (!route) return undefined;\n\n return {\n pattern: route.pattern,\n async respond(signal) {\n console.info(`[wxa-runner] 拦截请求 ${request.method} ${request.url}(${route.pattern})`);\n const response: MockResponse = typeof route.handler === 'function' ? (await route.handler(request)) || {} : route.handler;\n checkDelay(response.delay);\n if (response.delay) await sleep(response.delay, signal);\n const { body } = response;\n const isJson = body !== undefined && typeof body !== 'string' && !isBinary(body);\n return {\n statusCode: response.status ?? 200,\n header: { ...(isJson ? { 'Content-Type': 'application/json' } : {}), ...response.header },\n body: body === undefined ? '' : isJson ? JSON.stringify(body) : (body as string | BufferSource)\n };\n }\n };\n }\n}\n\n/**\n * 把 '[METHOD ]URL' 规则编译成匹配函数,查询参数和 hash 不参与匹配\n * @throws 规则写法不对时\n */\nexport function compilePattern(pattern: string): RequestMatcher {\n const parts = pattern.trim().split(/\\s+/);\n if (parts.length > 2 || (parts.length === 2 && !METHODS.includes(parts[0].toUpperCase()))) {\n throw new Error(`拦截规则应写成 \"[请求方法 ]地址\",如 \"POST https://api.example.com/login\"、\"**/auth/login\"`);\n }\n const [method, url] = parts.length === 2 ? [parts[0].toUpperCase(), parts[1]] : [null, parts[0]];\n const regexp = globToRegExp(url);\n return request => (!method || method === request.method) && regexp.test(String(request.url).replace(/[?#].*$/, ''));\n}\n\n/** ArrayBuffer 和 Uint8Array 等视图(Node 的 Buffer 经 Playwright 传进来也是 Uint8Array),不论属于哪个 iframe */\nfunction isBinary(value: unknown): value is BufferSource {\n return ArrayBuffer.isView(value) || Object.prototype.toString.call(value) === '[object ArrayBuffer]';\n}\n\nfunction checkDelay(delay: unknown) {\n if (delay !== undefined && !(typeof delay === 'number' && delay >= 0 && Number.isFinite(delay))) {\n throw new Error(`delay 需要是不小于 0 的毫秒数,实际是 ${String(delay)}`);\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason);\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener('abort', () => {\n clearTimeout(timer);\n reject(signal.reason);\n }, { once: true });\n });\n}\n\nfunction globToRegExp(glob: string): RegExp {\n const source = glob\n .split('**')\n .map(part => part.split('*').map(escapeRegExp).join('[^/]*'))\n .join('.*');\n return new RegExp(`^${source}$`);\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","/**\n * 保存的文件(wx.saveFile 等):文件和临时文件一样存在开发服务器上,保存记录写在 Storage 里\n *\n * 保存记录和 Storage 一样按 appid 隔离、整页刷新后还在。开发服务器重启后文件就没了,对应的记录随之失效,\n * 相当于真机上缓存的文件被清理:Painter 等库查不到缓存时会重新下载。\n */\n\nimport { ApiHandler } from './registry';\nimport type { MiniProgramStorage } from './storage';\nimport { isTempFile, removeTempFile, saveTempFile, tempFileSize, tempFileType } from './tempFiles';\n\nconst NAMESPACE = 'savedFiles';\n\ninterface SavedFile {\n size: number;\n /** 秒 */\n createTime: number;\n}\n\nexport function createSavedFileApis(storage: MiniProgramStorage): Record<string, ApiHandler> {\n const record = (filePath: string) => storage.get(NAMESPACE, filePath)?.data as SavedFile | undefined;\n\n /** 有保存记录、文件也还在时返回记录;文件已经没了就删掉记录 */\n const liveRecord = async (filePath: string) => {\n const saved = record(filePath);\n if (!saved) return undefined;\n if (await tempFileSize(filePath) !== null) return saved;\n storage.remove(NAMESPACE, filePath);\n return undefined;\n };\n\n return {\n // 和真机一样:存成新文件,原来的临时文件随之删除\n saveFile: async args => {\n // FileSystemManager.saveFile 可以指定保存位置,那是内存文件系统,存不了图片等二进制内容\n if (args.filePath) throw new Error('wxa-runner 暂不支持指定 filePath,不传时保存成功后返回 savedFilePath');\n const res = isTempFile(args.tempFilePath) ? await fetch(args.tempFilePath) : null;\n if (!res?.ok) throw new Error(`tempFilePath file not exist ${args.tempFilePath}`);\n const data = await res.blob();\n const savedFilePath = await saveTempFile(data, tempFileType(args.tempFilePath, data.type, 'tmp'));\n await removeTempFile(args.tempFilePath);\n storage.set(NAMESPACE, savedFilePath, { size: data.size, createTime: Math.floor(Date.now() / 1000) });\n return { savedFilePath };\n },\n getSavedFileList: async () => {\n const fileList = [];\n for (const filePath of storage.keys(NAMESPACE)) {\n const saved = await liveRecord(filePath);\n if (saved) fileList.push({ filePath, ...saved });\n }\n return { fileList };\n },\n getSavedFileInfo: async args => {\n const saved = await liveRecord(args.filePath);\n if (!saved) throw new Error(`file not exist ${args.filePath}`);\n return { ...saved };\n },\n removeSavedFile: async args => {\n if (!record(args.filePath)) throw new Error(`file not exist ${args.filePath}`);\n storage.remove(NAMESPACE, args.filePath);\n await removeTempFile(args.filePath);\n }\n };\n}\n","/**\n * Storage:落到浏览器 localStorage,按 appid 和 storageId 隔离\n *\n * 基础库传来的 data 已经序列化成字符串,并附带 dataType(\"Number\"、\"Object\" 等),\n * 读取时原样交回,由基础库反序列化。storageId 0 是业务数据,其他值是基础库内部缓存。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\n\n/** 只用到 localStorage 的这几个方法,便于测试时替换 */\nexport interface KeyValueStore {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n key(index: number): string | null;\n readonly length: number;\n}\n\nconst LIMIT_SIZE_KB = 10 * 1024;\n\nexport class MiniProgramStorage {\n constructor(private readonly store: KeyValueStore, private readonly appid: string) {}\n\n set(namespace: string, key: string, data: unknown, dataType?: string) {\n this.store.setItem(this.prefix(namespace) + key, JSON.stringify([data, dataType]));\n }\n\n get(namespace: string, key: string): { data: unknown; dataType?: string } | null {\n const raw = this.store.getItem(this.prefix(namespace) + key);\n if (raw === null) return null;\n const [data, dataType] = JSON.parse(raw);\n return { data, dataType };\n }\n\n remove(namespace: string, key: string) {\n this.store.removeItem(this.prefix(namespace) + key);\n }\n\n keys(namespace: string): string[] {\n const prefix = this.prefix(namespace);\n const keys: string[] = [];\n for (let i = 0; i < this.store.length; i++) {\n const key = this.store.key(i);\n if (key && key.startsWith(prefix)) keys.push(key.slice(prefix.length));\n }\n return keys;\n }\n\n clear(namespace: string) {\n for (const key of this.keys(namespace)) this.remove(namespace, key);\n }\n\n info(namespace: string) {\n const prefix = this.prefix(namespace);\n const keys = this.keys(namespace);\n let bytes = 0;\n for (const key of keys) {\n bytes += (key.length + (this.store.getItem(prefix + key) || '').length) * 2;\n }\n return { keys, currentSize: Math.ceil(bytes / 1024), limitSize: LIMIT_SIZE_KB };\n }\n\n private prefix(namespace: string) {\n return `wxa:${this.appid}:${namespace}:`;\n }\n}\n\nexport interface StoredValue {\n data: string;\n dataType: string;\n}\n\n/**\n * 按基础库 anyTypeToString 的规则序列化:宿主直接写入的值,wx.getStorageSync 读回来与原值一致\n *\n * @throws 值的类型无法存储(函数、Map 等)时\n */\nexport function encodeStorageValue(value: unknown): StoredValue {\n const dataType = typeOf(value);\n switch (dataType) {\n case 'Array':\n case 'Object':\n return { data: JSON.stringify(value), dataType };\n case 'String':\n case 'Number':\n case 'Boolean':\n return { data: String(value), dataType };\n case 'Date':\n return { data: String((value as Date).getTime()), dataType };\n case 'Undefined':\n case 'Null':\n return { data: dataType.toLowerCase(), dataType };\n default:\n throw new Error(`不支持存储 ${dataType} 类型的值`);\n }\n}\n\n/** encodeStorageValue 的逆过程,与基础库 stringToAnyType 一致;没有 dataType 时原样返回 */\nexport function decodeStorageValue(item: { data: unknown; dataType?: string }): unknown {\n const { data, dataType } = item;\n if (typeof data !== 'string' || !dataType) return data;\n switch (dataType) {\n case 'String':\n return data;\n case 'Array':\n case 'Object':\n return JSON.parse(data);\n case 'Number':\n return parseFloat(data);\n case 'Boolean':\n return data === 'true';\n case 'Date':\n return new Date(parseInt(data, 10));\n case 'Undefined':\n return undefined;\n case 'Null':\n return null;\n default:\n return '';\n }\n}\n\nfunction typeOf(value: unknown): string {\n return Object.prototype.toString.call(value).slice(8, -1);\n}\n\nexport function createStorageApis(storage: MiniProgramStorage): Record<string, ApiHandler> {\n const ns = (args: any) => `s${args.storageId || 0}`;\n\n const get: ApiHandler = (args, { api }) => {\n const item = storage.get(ns(args), args.key);\n return item ? ok(api, item) : fail(api, 'data not found');\n };\n const set: ApiHandler = args => storage.set(ns(args), args.key, args.data, args.dataType);\n const remove: ApiHandler = args => storage.remove(ns(args), args.key);\n const clear: ApiHandler = args => storage.clear(ns(args));\n const info: ApiHandler = args => storage.info(ns(args));\n\n // 渲染层用 global storage 存 cookie 等信息\n const globalGet: ApiHandler = (args, { api }) => {\n const item = storage.get('global', args.key);\n return item ? ok(api, { data: item.data }) : fail(api, 'data not found');\n };\n\n return {\n getStorage: get,\n getStorageSync: get,\n setStorage: set,\n setStorageSync: set,\n removeStorage: remove,\n removeStorageSync: remove,\n clearStorage: clear,\n clearStorageSync: clear,\n getStorageInfo: info,\n getStorageInfoSync: info,\n getGlobalStorage: globalGet,\n getGlobalStorageSync: globalGet,\n setGlobalStorage: args => storage.set('global', args.key, args.data),\n setGlobalStorageSync: args => storage.set('global', args.key, args.data),\n removeGlobalStorage: args => storage.remove('global', args.key),\n clearGlobalStorage: () => storage.clear('global'),\n getGlobalStorageInfo: () => storage.info('global')\n };\n}\n","/**\n * 分包加载的本地就绪协议:分包预下载(preloadRule)和分包异步化(跨分包组件、require.async)都走这里。\n *\n * AppBuilder 已预注册所有分包模块,静态资源也由开发服务器直接提供,因此这里不下载文件,\n * 只按基础库协议交回任务 ID,再异步通知进度与完成。未知包明确失败,不假装加载成功。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\n\nexport interface SubpackageApiOptions {\n subPackages: ReadonlyArray<{ root: string; name?: string }>;\n emit: (event: string, data: Record<string, unknown>) => void;\n}\n\nexport function createSubpackageApis(options: SubpackageApiOptions): Record<string, ApiHandler> {\n const names = new Set(['__APP__']);\n for (const pkg of options.subPackages) {\n names.add(normalizeName(pkg.root));\n if (pkg.name) names.add(normalizeName(pkg.name));\n }\n let taskSeq = 0;\n\n const createLoadSubPackageTask: ApiHandler = (args, { api }) => {\n const moduleName = args.moduleName;\n if (typeof moduleName !== 'string' || !moduleName || !names.has(normalizeName(moduleName))) {\n return fail(api, 'module not found');\n }\n\n const loadTaskId = String(++taskSeq);\n // 先让基础库登记任务、业务方绑定进度监听,之后再派发事件,与网络任务的时序一致。\n setTimeout(() => {\n const event = { taskId: loadTaskId, moduleName };\n options.emit('onLoadSubPackageTaskStateChange', {\n ...event, state: 'progressUpdate', progress: 100,\n // 没有网络下载,不伪造传输字节数。\n totalBytesWritten: 0, totalBytesExpectedToWrite: 0\n });\n options.emit('onLoadSubPackageTaskStateChange', { ...event, state: 'success' });\n }, 0);\n return ok(api, { loadTaskId });\n };\n\n return {\n createLoadSubPackageTask,\n // 事件已由桥接广播,具体监听与回调由基础库管理,无需另建一套订阅状态。\n listenLoadSubPackageTaskStateChange: (_args, { api }) => ok(api),\n // 分包加载完成后渲染层请求注入分包的模板和样式,它们已经打进 page-frame.js,回调后基础库替换占位组件。\n injectSubPackages: (_args, { api }) => ok(api)\n };\n}\n\n/** 基础库通常传 /root/;同时接受配置中的 root 与 name,不放宽到任意子路径。 */\nfunction normalizeName(name: string): string {\n return name.replace(/^\\.?\\//, '').replace(/\\/$/, '');\n}\n","/**\n * 设备与系统信息:以模拟设备为准,而不是宿主浏览器窗口\n */\n\nimport type { DeviceProfile } from '../../types';\nimport { ApiHandler, ok } from './registry';\n\nexport interface SystemApiOptions {\n device: DeviceProfile;\n baseLibVersion: string;\n /** 当前页面可用高度(扣除导航栏、tabBar) */\n windowHeight: () => number;\n /** 当前页面窗口顶部到屏幕顶部的距离,自定义导航栏时为 0 */\n screenTop: () => number;\n}\n\nexport const NAVIGATION_BAR_HEIGHT = 44;\nexport const TAB_BAR_HEIGHT = 50;\n\n/** 胶囊按钮位置,外壳绘制和 getMenuButtonBoundingClientRect 共用 */\nexport function menuButtonRect(device: DeviceProfile) {\n const width = 87;\n const height = 32;\n const top = device.statusBarHeight + 6;\n const right = device.screenWidth - 7;\n return { width, height, top, right, bottom: top + height, left: right - width };\n}\n\nexport function createSystemApis(options: SystemApiOptions): Record<string, ApiHandler> {\n const { device } = options;\n\n const windowInfo = () => {\n const safeBottom = device.screenHeight - device.safeAreaBottom;\n return {\n pixelRatio: device.pixelRatio,\n screenWidth: device.screenWidth,\n screenHeight: device.screenHeight,\n windowWidth: device.screenWidth,\n windowHeight: options.windowHeight(),\n windowTop: 0,\n windowBottom: 0,\n statusBarHeight: device.statusBarHeight,\n safeArea: {\n left: 0,\n right: device.screenWidth,\n top: device.statusBarHeight,\n bottom: safeBottom,\n width: device.screenWidth,\n height: safeBottom - device.statusBarHeight\n },\n safeAreaInsets: { top: device.statusBarHeight, left: 0, right: 0, bottom: device.safeAreaBottom },\n screenTop: options.screenTop()\n };\n };\n\n const deviceInfo = () => ({\n brand: 'devtools',\n model: device.model,\n system: device.system,\n platform: device.platform,\n benchmarkLevel: 1,\n abi: 'arm64',\n deviceAbi: 'arm64',\n cpuType: 'unknown',\n memorySize: 4096\n });\n\n const appBaseInfo = () => ({\n SDKVersion: options.baseLibVersion,\n enableDebug: false,\n host: { env: 'WeChat', appId: '' },\n language: 'zh_CN',\n version: '8.0.50',\n theme: 'light',\n fontSizeSetting: 16\n });\n\n const authorizeSetting = () => ({\n albumAuthorized: 'authorized',\n bluetoothAuthorized: 'authorized',\n cameraAuthorized: 'authorized',\n locationAuthorized: 'authorized',\n locationReducedAccuracy: false,\n microphoneAuthorized: 'authorized',\n notificationAuthorized: 'authorized',\n phoneCalendarAuthorized: 'authorized'\n });\n\n const systemSetting = () => ({\n bluetoothEnabled: true,\n locationEnabled: true,\n wifiEnabled: true,\n deviceOrientation: 'portrait'\n });\n\n const systemInfo: ApiHandler = (args, { api }) => {\n switch (args.type) {\n case 'windowInfo': return ok(api, windowInfo());\n case 'deviceInfo': return ok(api, deviceInfo());\n case 'appBaseInfo': return ok(api, appBaseInfo());\n case 'appAuthorizeSetting': return ok(api, authorizeSetting());\n case 'systemSetting': return ok(api, systemSetting());\n }\n return ok(api, {\n ...deviceInfo(),\n ...windowInfo(),\n ...appBaseInfo(),\n ...systemSetting(),\n albumAuthorized: true,\n cameraAuthorized: true,\n locationAuthorized: true,\n microphoneAuthorized: true,\n notificationAuthorized: true\n });\n };\n\n return {\n getSystemInfo: systemInfo,\n getSystemInfoSync: systemInfo,\n getSystemInfoAsync: systemInfo,\n getWindowInfo: (_args, { api }) => ok(api, windowInfo()),\n getDeviceInfo: (_args, { api }) => ok(api, deviceInfo()),\n getAppBaseInfo: (_args, { api }) => ok(api, appBaseInfo()),\n getAppAuthorizeSetting: (_args, { api }) => ok(api, authorizeSetting()),\n getSystemSetting: (_args, { api }) => ok(api, systemSetting()),\n getNetworkType: (_args, { api }) => ok(api, { networkType: 'wifi', signalStrength: 100, hasSystemProxy: false }),\n getBatteryInfo: (_args, { api }) => ok(api, { level: 100, isCharging: true }),\n getBatteryInfoSync: (_args, { api }) => ok(api, { level: 100, isCharging: true }),\n getMenuButtonBoundingClientRect: (_args, { api }) => ok(api, menuButtonRect(device)),\n getScreenBrightness: (_args, { api }) => ok(api, { value: 0.8 }),\n setScreenBrightness: () => undefined,\n setKeepScreenOn: () => undefined,\n vibrateShort: () => undefined,\n vibrateLong: () => undefined\n };\n}\n","/**\n * 界面 API:toast / loading / modal / actionSheet / 导航栏\n */\n\nimport type { NavigationState, PhoneShell } from '../ui/PhoneShell';\nimport { ApiHandler, fail, ok } from './registry';\n\nexport interface UiApiOptions {\n shell: PhoneShell;\n /** 修改当前页面的导航栏状态(随页面保存,返回时恢复) */\n updateNavigation: (state: Partial<NavigationState>) => void;\n}\n\nexport function createUiApis({ shell, updateNavigation }: UiApiOptions): Record<string, ApiHandler> {\n return {\n showToast: args => shell.showToast(args),\n hideToast: () => shell.hideToast(),\n showLoading: args => shell.showToast({ ...args, icon: 'loading', duration: 0 }),\n hideLoading: () => shell.hideToast(),\n showModal: async (args, { api }) => ok(api, await shell.showModal(args)),\n showActionSheet: async (args, { api }) => {\n const tapIndex = await shell.showActionSheet(args);\n return tapIndex === null ? fail(api, 'cancel') : ok(api, { tapIndex });\n },\n\n setNavigationBarTitle: args => updateNavigation({ title: String(args.title ?? '') }),\n setNavigationBarColor: args => updateNavigation({\n backgroundColor: args.backgroundColor,\n textStyle: String(args.frontColor).toLowerCase() === '#000000' ? 'black' : 'white'\n }),\n showNavigationBarLoading: () => shell.setNavigationLoading(true),\n hideNavigationBarLoading: () => shell.setNavigationLoading(false),\n hideHomeButton: () => undefined,\n setBackgroundColor: () => undefined,\n setBackgroundTextStyle: () => undefined,\n startPullDownRefresh: () => undefined,\n stopPullDownRefresh: () => undefined\n };\n}\n","/**\n * web-view 组件背后的原生网页视图\n *\n * 渲染层的 web-view 组件调 insertHTMLWebView 占位,updateHTMLWebView 设置地址和位置,\n * 销毁时 removeHTMLWebView;加载进度通过渲染层的 onWebviewStartLoad / onWebviewFinishLoad\n * 告诉组件,组件据此触发 bindload。\n *\n * 网页放在所在页面渲染层里的 iframe 中,跟着页面显示、隐藏和关闭。\n * 设置了 X-Frame-Options 或 CSP frame-ancestors 的网站不允许被嵌入,这类网页显示不出来。\n */\n\nimport { ApiHandler, fail, ok } from './registry';\n\nexport interface WebViewApiOptions {\n /** 页面渲染层的 document,页面已关闭时为 undefined */\n documentOf(webviewId: number): Document | undefined;\n /** 派发给渲染层的原生事件(渲染层里 WeixinJSBridge.on 收到) */\n emitToWebview(webviewId: number, event: string, data: unknown): void;\n}\n\ninterface Position {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\nexport function createWebViewApis({ documentOf, emitToWebview }: WebViewApiOptions): Record<string, ApiHandler> {\n // 三个接口都由网页所在的渲染层调用,到那个文档里按 htmlId 找;不另存引用,页面关闭时随文档一起释放\n const find = (webviewId: number, htmlId: unknown) =>\n documentOf(webviewId)?.querySelector<HTMLIFrameElement>(`iframe[data-wxa-html-id=\"${Number(htmlId)}\"]`) ?? null;\n\n const reportStart = (webviewId: number, htmlId: number, src: string) =>\n emitToWebview(webviewId, 'onWebviewStartLoad', { htmlId, src, isMainFrame: true });\n const reportFinish = (webviewId: number, htmlId: number, src: string) =>\n emitToWebview(webviewId, 'onWebviewFinishLoad', { htmlId, src });\n\n const place = (frame: HTMLIFrameElement, position?: Partial<Position>) => {\n if (!position) return;\n for (const side of ['left', 'top', 'width', 'height'] as const) {\n if (typeof position[side] === 'number') frame.style[side] = `${position[side]}px`;\n }\n };\n\n return {\n insertHTMLWebView: (args, { api, webviewId }) => {\n const doc = documentOf(webviewId);\n if (!doc) return fail(api, 'page not found');\n\n const htmlId = Number(args.htmlId);\n const frame = doc.createElement('iframe');\n frame.dataset.wxaHtmlId = String(htmlId);\n frame.style.cssText = 'position:fixed;z-index:2147483647;border:0;background:#fff';\n place(frame, args.position);\n frame.addEventListener('load', () => {\n const requested = frame.dataset.wxaLoading;\n if (requested) {\n delete frame.dataset.wxaLoading;\n reportFinish(webviewId, htmlId, requested);\n return;\n }\n // 网页里自己跳转的:同源时报告新地址;跨域读不到地址就不报,免得拿旧地址冒充\n const src = readableUrl(frame);\n if (!src || src === 'about:blank') return;\n reportStart(webviewId, htmlId, src);\n reportFinish(webviewId, htmlId, src);\n });\n doc.body.appendChild(frame);\n return ok(api);\n },\n\n updateHTMLWebView: (args, { api, webviewId }) => {\n const frame = find(webviewId, args.htmlId);\n if (!frame) return fail(api, 'web-view not found');\n place(frame, args.position);\n if (args.src) {\n const src = String(args.src);\n frame.dataset.wxaLoading = src;\n reportStart(webviewId, Number(args.htmlId), src);\n frame.src = src;\n }\n return ok(api);\n },\n\n removeHTMLWebView: (args, { api, webviewId }) => {\n find(webviewId, args.htmlId)?.remove();\n return ok(api);\n }\n };\n}\n\nfunction readableUrl(frame: HTMLIFrameElement): string | null {\n try {\n return frame.contentWindow?.location.href ?? null;\n } catch {\n return null;\n }\n}\n","/**\n * 页面栈:只管顺序和上限,页面的创建与销毁由调用方处理\n */\n\nexport const MAX_PAGE_STACK = 10;\n\nexport class PageStack<T> {\n private items: T[] = [];\n\n constructor(private readonly max = MAX_PAGE_STACK) {}\n\n get size(): number {\n return this.items.length;\n }\n\n current(): T | undefined {\n return this.items[this.items.length - 1];\n }\n\n entries(): T[] {\n return [...this.items];\n }\n\n canPush(): boolean {\n return this.items.length < this.max;\n }\n\n push(item: T) {\n if (!this.canPush()) throw new Error('webview count limit exceed');\n this.items.push(item);\n }\n\n /** 至少保留栈底页面;返回被弹出的页面(栈顶在前) */\n pop(delta = 1): T[] {\n const count = Math.max(0, Math.min(Math.floor(delta) || 1, this.items.length - 1));\n return this.items.splice(this.items.length - count, count).reverse();\n }\n\n /** 替换栈顶,返回原栈顶 */\n replaceTop(item: T): T | undefined {\n const previous = this.items.pop();\n this.items.push(item);\n return previous;\n }\n\n /** 清空并放入新页面,返回原有页面 */\n reset(item: T): T[] {\n const previous = this.items;\n this.items = [item];\n return previous.filter(existing => existing !== item);\n }\n}\n","/**\n * 一个页面对应一个渲染层 iframe\n */\n\nimport type { FrameBridge } from '../types';\nimport type { NavigationState, SafeAreaInsets } from './ui/PhoneShell';\n\ntype PendingDispatch = (bridge: FrameBridge, win: Window) => void;\n\nexport class PageView {\n readonly frame: HTMLIFrameElement;\n readonly ready: Promise<void>;\n win: Window | null = null;\n bridge: FrameBridge | null = null;\n navigation: NavigationState;\n private markReady!: () => void;\n private pending: PendingDispatch[] = [];\n\n constructor(\n readonly id: number,\n readonly path: string,\n readonly query: Record<string, string>,\n container: HTMLElement,\n version: number,\n navigation: NavigationState\n ) {\n this.navigation = navigation;\n this.ready = new Promise(resolve => {\n this.markReady = resolve;\n });\n\n this.frame = document.createElement('iframe');\n this.frame.name = `wxa-webview-${id}`;\n this.frame.dataset.webviewId = String(id);\n this.frame.dataset.path = path;\n this.frame.style.visibility = 'hidden';\n this.frame.src = `/__wxa__/webview/${path}.html?id=${id}&v=${version}`;\n container.appendChild(this.frame);\n }\n\n get url(): string {\n const query = new URLSearchParams(this.query).toString();\n return query ? `${this.path}?${query}` : this.path;\n }\n\n attach(win: Window, bridge: FrameBridge) {\n this.win = win;\n this.bridge = bridge;\n const pending = this.pending;\n this.pending = [];\n pending.forEach(dispatch => dispatch(bridge, win));\n }\n\n /** 渲染层脚本全部执行完(含 generateFuncReady)后调用 */\n loaded() {\n this.markReady();\n }\n\n /** 渲染层还没注册桥时先缓存,注册后按顺序补发 */\n dispatch(fn: PendingDispatch) {\n if (this.bridge && this.win) fn(this.bridge, this.win);\n else this.pending.push(fn);\n }\n\n /** 页面样式里的 env(safe-area-inset-*) 构建时已改写成这些变量,见 rewriteSafeAreaInsets */\n setSafeAreaInsets(insets: SafeAreaInsets) {\n this.dispatch((_bridge, win) => {\n const style = win.document.documentElement.style;\n for (const [side, value] of Object.entries(insets)) {\n style.setProperty(`--wxa-safe-area-inset-${side}`, `${value}px`);\n }\n });\n }\n\n /** data-current 是给测试用的公开契约:iframe[data-current] 始终指向当前页 */\n show() {\n this.frame.style.visibility = 'visible';\n this.frame.style.zIndex = '1';\n this.frame.dataset.current = '';\n }\n\n hide() {\n this.frame.style.visibility = 'hidden';\n this.frame.style.zIndex = '0';\n delete this.frame.dataset.current;\n }\n\n destroy() {\n this.frame.remove();\n this.win = null;\n this.bridge = null;\n }\n}\n","/**\n * 宿主交给 iframe 的值,在目标 iframe 的全局环境(realm)里重建\n *\n * 宿主、逻辑层、渲染层是不同的 iframe,各有一套 Object / Array / ArrayBuffer。属于别的 iframe 的值,\n * 在目标 iframe 里 instanceof 不成立,基础库的 setData 也会把这样的数组当成普通对象。\n */\n\n/** 在目标 iframe 的 realm 中重建数据,避免跨 realm 的 instanceof 判断失效 */\nexport function cloneInto<T>(win: Window, value: T): T {\n if (value === undefined) return value;\n return (win as any).JSON.parse(JSON.stringify(value));\n}\n\nconst BUFFER_KEY = '__wxa_array_buffer__';\n\n/**\n * 原生接口的结果和事件交给 iframe:同 cloneInto,另外把 ArrayBuffer(readFile 读到的文件、按 arraybuffer 请求到的数据、\n * WebSocket 的二进制消息)复制成目标 realm 的。\n * 只有原生接口会给出 ArrayBuffer;setData 等消息数据量大,仍走 cloneInto,省掉逐个字段的检查\n */\nexport function cloneNativeInto<T>(win: Window, value: T): T {\n if (value === undefined) return value;\n const buffers: ArrayBuffer[] = [];\n const json = JSON.stringify(value, (_key, item) => {\n if (Object.prototype.toString.call(item) !== '[object ArrayBuffer]') return item;\n buffers.push(item);\n return { [BUFFER_KEY]: buffers.length - 1 };\n });\n const targetJson: JSON = (win as any).JSON;\n if (!buffers.length) return targetJson.parse(json);\n return targetJson.parse(json, (_key, item) => (item?.[BUFFER_KEY] === undefined ? item : copyBuffer(win, buffers[item[BUFFER_KEY]])));\n}\n\nfunction copyBuffer(win: Window, source: ArrayBuffer): ArrayBuffer {\n const copy: ArrayBuffer = new (win as any).ArrayBuffer(source.byteLength);\n new Uint8Array(copy).set(new Uint8Array(source));\n return copy;\n}\n","/**\n * 浏览器的文件选择框\n */\n\nexport interface FileChooserOptions {\n /** 如 image/* */\n accept: string;\n multiple: boolean;\n /** 手机浏览器上直接打开相机;桌面浏览器忽略,照常打开文件选择框 */\n capture: boolean;\n}\n\n/**\n * 只能在用户点击后的短时间内调用(见 hasUserActivation),否则浏览器不打开选择框,返回的 Promise 也不会结束\n * @returns 用户关掉选择框时为 null\n */\nexport function chooseFiles(options: FileChooserOptions): Promise<File[] | null> {\n return new Promise(resolve => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = options.accept;\n input.multiple = options.multiple;\n if (options.capture) input.setAttribute('capture', 'environment');\n input.style.display = 'none';\n\n const finish = (files: File[] | null) => {\n input.remove();\n resolve(files);\n };\n input.addEventListener('change', () => finish(input.files?.length ? Array.from(input.files) : null));\n input.addEventListener('cancel', () => finish(null));\n document.body.appendChild(input);\n input.click();\n });\n}\n\n/**\n * 用户刚点击过、可以打开文件选择框。用户在页面里点击也算:点击会传到宿主页。\n * 不支持查询的浏览器当作可以\n */\nexport function hasUserActivation(): boolean {\n return navigator.userActivation?.isActive ?? true;\n}\n","export function element(tag: string, className: string, text?: string): HTMLElement {\n const el = document.createElement(tag);\n el.className = className;\n if (text !== undefined) el.textContent = text;\n return el;\n}\n","/**\n * 图片预览层:黑底全屏显示一张图片,左右切换;和真机一样点一下关闭\n */\n\nimport { element } from './dom';\n\n/** @param current 先显示的图片下标 */\nexport function openImagePreview(container: HTMLElement, urls: string[], current: number) {\n const layer = element('div', 'wxa-preview');\n layer.setAttribute('role', 'dialog');\n layer.setAttribute('aria-label', '图片预览');\n const image = document.createElement('img');\n image.className = 'wxa-preview-image';\n const position = element('div', 'wxa-preview-position');\n const prev = element('button', 'wxa-preview-prev', '‹');\n prev.setAttribute('aria-label', '上一张');\n const next = element('button', 'wxa-preview-next', '›');\n next.setAttribute('aria-label', '下一张');\n\n let shown = 0;\n const show = (index: number) => {\n shown = Math.min(Math.max(index, 0), urls.length - 1);\n image.src = urls[shown];\n position.textContent = `${shown + 1}/${urls.length}`;\n prev.style.visibility = shown > 0 ? '' : 'hidden';\n next.style.visibility = shown < urls.length - 1 ? '' : 'hidden';\n };\n prev.addEventListener('click', () => show(shown - 1));\n next.addEventListener('click', () => show(shown + 1));\n layer.addEventListener('click', event => {\n if (event.target !== prev && event.target !== next) layer.remove();\n });\n\n layer.append(image, position, prev, next);\n container.appendChild(layer);\n show(current);\n}\n","/** 外壳边框(box-shadow 最外圈)宽度,缩放时计入手机外框尺寸 */\nexport const DEVICE_BEZEL = 13;\nexport const STAGE_PADDING = 24;\nexport const STAGE_GAP = 16;\n/** 选择器每一行的高度,一列显示 5 行,选中项在中间 */\nexport const PICKER_ITEM_HEIGHT = 34;\n\nexport const SHELL_CSS = `\nhtml, body { margin: 0; height: 100%; background: radial-gradient(120% 80% at 50% 0%, #f6f7f9 0%, #e6e9ee 100%); font-family: -apple-system, BlinkMacSystemFont, \"SF Pro Text\", \"PingFang SC\", \"Helvetica Neue\", sans-serif; -webkit-font-smoothing: antialiased; }\n.wxa-stage { min-height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: ${STAGE_GAP}px; padding: ${STAGE_PADDING}px; box-sizing: border-box; }\n.wxa-device-slot { position: relative; flex: none; }\n.wxa-device { position: absolute; transform-origin: 0 0; overflow: hidden; background: #fff; border-radius: 6px; display: flex; flex-direction: column; box-shadow: 0 0 0 ${DEVICE_BEZEL - 2}px #111214, 0 0 0 ${DEVICE_BEZEL - 1}px #3a3b3f, 0 0 0 ${DEVICE_BEZEL}px #1b1c1f, 0 32px 64px -12px rgba(15,23,42,.35), 0 14px 28px -8px rgba(15,23,42,.18); }\n.wxa-device.has-notch { border-radius: 40px; }\n.wxa-notch { position: absolute; top: 0; left: 50%; z-index: 30; width: 209px; height: 30px; transform: translateX(-50%); background: #000; border-radius: 0 0 20px 20px; pointer-events: none; }\n.wxa-notch::before, .wxa-notch::after { content: ''; position: absolute; top: 0; width: 6px; height: 6px; }\n.wxa-notch::before { left: -6px; background: radial-gradient(circle at 0 100%, transparent 5.5px, #000 6px); }\n.wxa-notch::after { right: -6px; background: radial-gradient(circle at 100% 100%, transparent 5.5px, #000 6px); }\n.wxa-home-indicator { position: absolute; bottom: 8px; left: 50%; z-index: 30; width: 134px; height: 5px; transform: translateX(-50%); border-radius: 3px; background: rgba(0,0,0,.85); pointer-events: none; }\n.wxa-statusbar { flex: none; display: flex; align-items: center; justify-content: space-between; padding: 0 8px; font-size: 12px; font-weight: 600; box-sizing: border-box; user-select: none; }\n.wxa-statusbar-icons { display: flex; align-items: center; gap: 5px; }\n.wxa-statusbar svg { display: block; }\n.has-notch .wxa-statusbar { display: grid; grid-template-columns: 1fr 209px 1fr; align-items: start; padding: 15px 0 0; font-size: 15px; letter-spacing: -.2px; }\n.has-notch .wxa-statusbar-time { grid-column: 1; justify-self: center; line-height: 20px; }\n.has-notch .wxa-statusbar-icons { grid-column: 3; justify-self: center; height: 20px; }\n.wxa-navbar { flex: none; height: 44px; position: relative; display: flex; align-items: center; justify-content: center; box-sizing: border-box; }\n.wxa-navbar.is-hidden, .wxa-statusbar.is-hidden { display: none; }\n.wxa-navbar-title { font-size: 17px; font-weight: 600; max-width: calc(100% - 204px); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }\n.wxa-navbar-back { position: absolute; left: 4px; top: 0; height: 44px; width: 44px; padding: 0; border: 0; background: none; color: inherit; cursor: pointer; display: flex; align-items: center; justify-content: center; }\n.wxa-navbar-loading { width: 14px; height: 14px; margin-right: 6px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: wxa-spin .8s linear infinite; display: none; }\n.wxa-navbar.is-loading .wxa-navbar-loading { display: inline-block; }\n.wxa-capsule { position: absolute; z-index: 6; display: flex; align-items: center; box-sizing: border-box; border-radius: 16px; border: .5px solid rgba(0,0,0,.12); background: rgba(255,255,255,.62); color: #000; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); user-select: none; }\n.wxa-capsule.is-light { border-color: rgba(255,255,255,.28); background: rgba(0,0,0,.18); color: #fff; }\n.wxa-capsule > span { flex: 1; height: 100%; display: flex; align-items: center; justify-content: center; }\n.wxa-capsule > span + span { position: relative; }\n.wxa-capsule > span + span::before { content: ''; position: absolute; left: 0; top: 8px; bottom: 8px; width: 1px; background: currentColor; opacity: .25; transform: scaleX(.5); }\n.wxa-capsule svg { display: block; }\n.wxa-pages { flex: 1; position: relative; overflow: hidden; }\n.wxa-pages iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: #fff; }\n.wxa-tabbar { flex: none; height: calc(50px + var(--wxa-safe-bottom, 0px)); padding-bottom: var(--wxa-safe-bottom, 0px); display: flex; border-top: .5px solid rgba(0,0,0,.1); box-sizing: border-box; }\n.wxa-tabbar.is-hidden { display: none; }\n.wxa-tabbar-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: 10px; cursor: pointer; user-select: none; gap: 2px; }\n.wxa-tabbar-item img { width: 24px; height: 24px; }\n.wxa-overlay { position: absolute; inset: 0; pointer-events: none; z-index: 10; }\n.wxa-mask { position: absolute; inset: 0; pointer-events: auto; }\n.wxa-mask.is-dim { background: rgba(0,0,0,.5); }\n.wxa-toast { position: absolute; left: 50%; top: 45%; transform: translate(-50%, -50%); min-width: 120px; max-width: 70%; padding: 14px 16px; border-radius: 8px; background: rgba(17,17,17,.75); color: #fff; font-size: 14px; text-align: center; box-sizing: border-box; pointer-events: none; }\n.wxa-toast.has-icon { width: 136px; min-height: 120px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; }\n.wxa-toast-icon { font-size: 36px; line-height: 1; }\n.wxa-toast-spinner { width: 34px; height: 34px; border: 3px solid #fff; border-right-color: transparent; border-radius: 50%; animation: wxa-spin .8s linear infinite; }\n.wxa-modal { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 80%; background: #fff; border-radius: 12px; overflow: hidden; pointer-events: auto; text-align: center; }\n.wxa-modal-title { padding: 24px 20px 8px; font-size: 17px; font-weight: 600; }\n.wxa-modal-content { padding: 8px 20px 24px; font-size: 15px; color: #666; white-space: pre-wrap; word-break: break-word; }\n.wxa-modal-input { width: calc(100% - 40px); margin: 0 20px 20px; padding: 8px; font-size: 15px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 4px; }\n.wxa-modal-actions { display: flex; border-top: 1px solid rgba(0,0,0,.1); }\n.wxa-modal-actions button { flex: 1; height: 50px; border: 0; background: none; font-size: 17px; font-weight: 600; cursor: pointer; }\n.wxa-modal-actions button + button { border-left: 1px solid rgba(0,0,0,.1); }\n.wxa-actionsheet { position: absolute; left: 0; right: 0; bottom: 0; background: #f7f7f7; border-radius: 12px 12px 0 0; overflow: hidden; pointer-events: auto; }\n.wxa-actionsheet-alert { padding: 16px; font-size: 13px; color: #888; text-align: center; background: #fff; }\n.wxa-actionsheet button { display: block; width: 100%; height: 56px; border: 0; border-top: 1px solid rgba(0,0,0,.06); background: #fff; font-size: 17px; cursor: pointer; }\n.wxa-actionsheet .wxa-actionsheet-cancel { margin-top: 8px; border-top: 0; }\n.wxa-picker { position: absolute; left: 0; right: 0; bottom: 0; padding-bottom: var(--wxa-safe-bottom, 0px); background: #fff; border-radius: 12px 12px 0 0; pointer-events: auto; user-select: none; }\n.wxa-picker-header { display: flex; align-items: center; height: 56px; padding: 0 8px; }\n.wxa-picker-header button { flex: none; border: 0; background: none; padding: 8px 12px; font-size: 17px; cursor: pointer; }\n.wxa-picker-cancel { color: rgba(0,0,0,.9); }\n.wxa-picker-confirm { color: #07c160; font-weight: 600; }\n.wxa-picker-title { flex: 1; overflow: hidden; font-size: 17px; font-weight: 600; text-align: center; white-space: nowrap; text-overflow: ellipsis; }\n.wxa-picker-body { position: relative; display: flex; height: ${PICKER_ITEM_HEIGHT * 5}px; margin: 0 16px 24px; }\n.wxa-picker-column { flex: 1; min-width: 0; overflow-y: auto; padding: ${PICKER_ITEM_HEIGHT * 2}px 0; box-sizing: border-box; scroll-snap-type: y mandatory; overscroll-behavior: contain; scrollbar-width: none; }\n.wxa-picker-column::-webkit-scrollbar { display: none; }\n.wxa-picker-item { height: ${PICKER_ITEM_HEIGHT}px; line-height: ${PICKER_ITEM_HEIGHT}px; padding: 0 4px; overflow: hidden; font-size: 17px; color: rgba(0,0,0,.4); text-align: center; white-space: nowrap; text-overflow: ellipsis; scroll-snap-align: center; cursor: pointer; }\n.wxa-picker-item.is-selected { color: rgba(0,0,0,.9); }\n.wxa-picker-indicator { position: absolute; left: 0; right: 0; top: ${PICKER_ITEM_HEIGHT * 2}px; height: ${PICKER_ITEM_HEIGHT}px; border-radius: 8px; background: rgba(0,0,0,.05); pointer-events: none; }\n.wxa-preview { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: #000; pointer-events: auto; }\n.wxa-preview-image { max-width: 100%; max-height: 100%; object-fit: contain; }\n.wxa-preview-position { position: absolute; top: 60px; left: 0; right: 0; color: #fff; font-size: 15px; text-align: center; pointer-events: none; }\n.wxa-preview button { position: absolute; top: 50%; width: 40px; height: 56px; margin-top: -28px; border: 0; border-radius: 8px; background: rgba(255,255,255,.15); color: #fff; font-size: 28px; cursor: pointer; }\n.wxa-preview .wxa-preview-prev { left: 8px; }\n.wxa-preview .wxa-preview-next { right: 8px; }\n.wxa-error { position: absolute; inset: 0; z-index: 20; overflow: auto; padding: 20px; background: #fff5f5; color: #c00; font: 12px/1.6 Menlo, monospace; white-space: pre-wrap; }\n.wxa-toolbar { display: flex; align-items: center; gap: 10px; padding: 4px 4px 4px 12px; border-radius: 999px; background: rgba(255,255,255,.7); box-shadow: 0 1px 2px rgba(15,23,42,.08); font-size: 12px; color: #555; }\n.wxa-toolbar button { border: 0; background: #111214; color: #fff; border-radius: 999px; padding: 4px 12px; font-size: 12px; cursor: pointer; }\n.wxa-toolbar .wxa-scale { min-width: 52px; background: #fff; color: #333; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); font-variant-numeric: tabular-nums; }\n.wxa-route { font-family: Menlo, monospace; }\n.wxa-notice { position: fixed; top: 16px; right: 16px; z-index: 100; display: flex; align-items: flex-start; gap: 10px; width: max-content; max-width: min(320px, calc(100vw - 32px)); padding: 12px 10px 12px 14px; box-sizing: border-box; border-radius: 12px; background: #fff; box-shadow: 0 0 0 1px rgba(15,23,42,.06), 0 12px 32px -8px rgba(15,23,42,.28); font-size: 13px; line-height: 20px; color: #555; animation: wxa-notice-in .18s ease-out; }\n.wxa-notice-icon { flex: none; width: 18px; height: 18px; margin-top: 1px; border-radius: 50%; background: #fa5151; color: #fff; font-size: 12px; font-weight: 700; line-height: 18px; text-align: center; }\n.wxa-notice-text { flex: 1; min-width: 0; word-break: break-word; text-wrap: pretty; }\n.wxa-notice-title { font-weight: 600; color: #111214; }\n.wxa-notice-close { flex: none; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%; background: none; color: #999; font-size: 16px; line-height: 20px; cursor: pointer; }\n.wxa-notice-close:hover { background: rgba(0,0,0,.06); color: #111214; }\n@keyframes wxa-spin { to { transform: rotate(360deg); } }\n@keyframes wxa-notice-in { from { opacity: 0; transform: translateY(-8px); } }\n`;\n","/**\n * 选择器弹层:从底部弹出,若干列可滚动的选项,中间一行是选中项\n *\n * 用户可以滚动到某一项,也可以直接点它。列之间的联动(日期的天数、省市区)不在这里,\n * 由调用方在 onColumnChange 里用 setColumn 换掉后面的列。\n */\n\nimport { element } from './dom';\nimport { PICKER_ITEM_HEIGHT } from './styles';\n\nexport interface PickerOptions {\n /** 每列的选项文字 */\n columns: string[][];\n /** 每列初始选中的下标 */\n current: number[];\n headerText?: string;\n /** 用户改变某列的选中项后调用;setColumn 引起的变化不会触发 */\n onColumnChange?: (column: number, index: number) => void;\n}\n\nexport interface PickerSession {\n /** 确定时为各列选中的下标,取消时为 null */\n result: Promise<number[] | null>;\n /** 替换某列的选项和选中项 */\n setColumn(column: number, items: string[], current: number): void;\n}\n\n/** 滚动停下多久后按位置确定选中项 */\nconst SCROLL_SETTLE_DELAY = 100;\n\nexport function openPicker(container: HTMLElement, options: PickerOptions): PickerSession {\n let resolve!: (value: number[] | null) => void;\n const result = new Promise<number[] | null>(done => {\n resolve = done;\n });\n\n const layer = element('div', 'wxa-picker-layer');\n const mask = element('div', 'wxa-mask is-dim');\n const sheet = element('div', 'wxa-picker');\n sheet.setAttribute('role', 'dialog');\n const header = element('div', 'wxa-picker-header');\n const cancel = element('button', 'wxa-picker-cancel', '取消');\n const confirm = element('button', 'wxa-picker-confirm', '确定');\n header.append(cancel, element('div', 'wxa-picker-title', options.headerText || ''), confirm);\n const body = element('div', 'wxa-picker-body');\n const columns = options.columns.map((_, index) => new PickerColumn(next => options.onColumnChange?.(index, next)));\n body.append(...columns.map(column => column.el), element('div', 'wxa-picker-indicator'));\n sheet.append(header, body);\n layer.append(mask, sheet);\n container.appendChild(layer);\n // 滚动位置要在元素进入文档后才能设置\n columns.forEach((column, index) => column.setItems(options.columns[index], options.current[index] ?? 0));\n\n const close = (value: number[] | null) => {\n layer.remove();\n resolve(value);\n };\n cancel.addEventListener('click', () => close(null));\n mask.addEventListener('click', () => close(null));\n confirm.addEventListener('click', () => {\n // 还在滚动中的列先按当前位置定下来,联动的列随之更新\n columns.forEach(column => column.settle());\n close(columns.map(column => column.index));\n });\n\n return {\n result,\n setColumn(column, items, current) {\n columns[column]?.setItems(items, current);\n }\n };\n}\n\nclass PickerColumn {\n readonly el = element('div', 'wxa-picker-column');\n index = 0;\n private items: HTMLElement[] = [];\n private settleTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(private readonly onUserChange: (index: number) => void) {\n this.el.addEventListener('scroll', () => {\n clearTimeout(this.settleTimer);\n this.settleTimer = setTimeout(() => this.settle(), SCROLL_SETTLE_DELAY);\n });\n this.el.addEventListener('click', event => {\n const item = (event.target as HTMLElement).closest<HTMLElement>('.wxa-picker-item');\n if (item) this.choose(Number(item.dataset.index));\n });\n }\n\n setItems(labels: string[], current: number) {\n this.items = labels.map((label, index) => {\n const item = element('div', 'wxa-picker-item', label);\n item.dataset.index = String(index);\n return item;\n });\n this.el.replaceChildren(...this.items);\n this.show(Math.min(Math.max(0, current), Math.max(0, labels.length - 1)));\n }\n\n /** 滚动停下后,选中停在中间那一行的项 */\n settle() {\n clearTimeout(this.settleTimer);\n if (!this.items.length) return;\n const index = Math.min(this.items.length - 1, Math.max(0, Math.round(this.el.scrollTop / PICKER_ITEM_HEIGHT)));\n this.choose(index);\n }\n\n private choose(index: number) {\n const changed = index !== this.index;\n this.show(index);\n if (changed) this.onUserChange(index);\n }\n\n private show(index: number) {\n this.items[this.index]?.classList.remove('is-selected');\n this.index = index;\n this.items[index]?.classList.add('is-selected');\n this.el.scrollTo({ top: index * PICKER_ITEM_HEIGHT, behavior: 'instant' });\n }\n}\n","/**\n * 模拟手机外壳:刘海、状态栏、导航栏、胶囊按钮、页面容器、tabBar 和系统弹层\n */\n\nimport type { DeviceProfile } from '../../types';\nimport { menuButtonRect, NAVIGATION_BAR_HEIGHT, TAB_BAR_HEIGHT } from '../api/system';\nimport { element } from './dom';\nimport { openImagePreview } from './ImagePreview';\nimport { openPicker, PickerOptions, PickerSession } from './Picker';\nimport { DEVICE_BEZEL, SHELL_CSS, STAGE_GAP, STAGE_PADDING } from './styles';\n\nexport interface NavigationState {\n title: string;\n backgroundColor: string;\n textStyle: string;\n showBack: boolean;\n custom: boolean;\n}\n\nexport interface TabBarConfig {\n color?: string;\n selectedColor?: string;\n backgroundColor?: string;\n borderStyle?: string;\n custom?: boolean;\n list: Array<{ pagePath: string; text?: string; iconPath?: string; selectedIconPath?: string }>;\n}\n\nexport interface SafeAreaInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport interface ToastOptions {\n title?: string;\n icon?: 'success' | 'error' | 'loading' | 'none';\n image?: string;\n duration?: number;\n mask?: boolean;\n}\n\nexport interface ModalOptions {\n title?: string;\n content?: string;\n showCancel?: boolean;\n cancelText?: string;\n cancelColor?: string;\n confirmText?: string;\n confirmColor?: string;\n editable?: boolean;\n placeholderText?: string;\n}\n\nexport interface ActionSheetOptions {\n alertText?: string;\n itemList: string[];\n itemColor?: string;\n}\n\ntype ScaleMode = 'fit' | '1';\n\nconst SCALE_STORAGE_KEY = 'wxa-runner:scale';\nconst MIN_SCALE = 0.5;\nconst NOTICE_DURATION = 6000;\n\n/** 手动打开时默认适应窗口;自动化环境默认 1:1,截图和视觉基线不随窗口大小变化 */\nfunction loadScaleMode(): ScaleMode {\n try {\n const saved = localStorage.getItem(SCALE_STORAGE_KEY);\n if (saved === 'fit' || saved === '1') return saved;\n } catch {\n // 存储不可用时用默认值\n }\n return navigator.webdriver ? '1' : 'fit';\n}\n\nexport class PhoneShell {\n readonly pages: HTMLElement;\n private readonly stage: HTMLElement;\n private readonly slot: HTMLElement;\n private readonly device: HTMLElement;\n private readonly toolbar: HTMLElement;\n private readonly scaleButton: HTMLButtonElement;\n private scaleMode = loadScaleMode();\n private readonly statusBar: HTMLElement;\n private readonly navBar: HTMLElement;\n private readonly capsule: HTMLElement;\n private readonly navTitle: HTMLElement;\n private readonly backButton: HTMLButtonElement;\n private readonly tabBar: HTMLElement;\n private readonly overlay: HTMLElement;\n private readonly routeLabel: HTMLElement;\n private toastEl: HTMLElement | null = null;\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n private noticeEl: HTMLElement | null = null;\n private noticeTimer: ReturnType<typeof setTimeout> | null = null;\n private tabBarConfig: TabBarConfig | null = null;\n private onTabTap: (pagePath: string, index: number) => void = () => undefined;\n private navigation: NavigationState = { title: '', backgroundColor: '#000', textStyle: 'white', showBack: false, custom: false };\n private tabBarVisible = false;\n\n constructor(root: HTMLElement, private readonly profile: DeviceProfile) {\n const style = document.createElement('style');\n style.textContent = SHELL_CSS;\n document.head.appendChild(style);\n\n // 刘海屏的状态栏比传统机型(20px)高,以此区分是否绘制刘海\n const hasNotch = profile.statusBarHeight > 20;\n const capsule = menuButtonRect(profile);\n root.innerHTML = `\n <div class=\"wxa-stage\">\n <div class=\"wxa-device-slot\">\n <div class=\"wxa-device${hasNotch ? ' has-notch' : ''}\" style=\"width:${profile.screenWidth}px;height:${profile.screenHeight}px;--wxa-safe-bottom:${profile.safeAreaBottom}px\">\n <div class=\"wxa-statusbar\" style=\"height:${profile.statusBarHeight}px\">\n <span class=\"wxa-statusbar-time\">9:41</span>\n <span class=\"wxa-statusbar-icons\">${STATUS_ICONS}</span>\n </div>\n <div class=\"wxa-navbar\">\n <button class=\"wxa-navbar-back\" title=\"返回\" aria-label=\"返回\">${BACK_ICON}</button>\n <span class=\"wxa-navbar-loading\"></span><span class=\"wxa-navbar-title\"></span>\n </div>\n <div class=\"wxa-pages\"></div>\n <div class=\"wxa-tabbar is-hidden\"></div>\n <div class=\"wxa-capsule\" style=\"top:${capsule.top}px;left:${capsule.left}px;width:${capsule.width}px;height:${capsule.height}px\">\n <span class=\"wxa-capsule-more\">${MORE_ICON}</span><span class=\"wxa-capsule-close\">${CLOSE_ICON}</span>\n </div>\n <div class=\"wxa-overlay\"></div>\n ${hasNotch ? '<div class=\"wxa-notch\"></div>' : ''}\n ${profile.safeAreaBottom ? '<div class=\"wxa-home-indicator\"></div>' : ''}\n </div>\n </div>\n <div class=\"wxa-toolbar\">\n <span class=\"wxa-route\"></span><button class=\"wxa-scale\"></button><button class=\"wxa-reload\">刷新</button>\n </div>\n </div>`;\n\n this.stage = root.querySelector('.wxa-stage')!;\n this.slot = root.querySelector('.wxa-device-slot')!;\n this.device = root.querySelector('.wxa-device')!;\n this.toolbar = root.querySelector('.wxa-toolbar')!;\n this.scaleButton = root.querySelector('.wxa-scale')!;\n this.statusBar = root.querySelector('.wxa-statusbar')!;\n this.navBar = root.querySelector('.wxa-navbar')!;\n this.capsule = root.querySelector('.wxa-capsule')!;\n this.navTitle = root.querySelector('.wxa-navbar-title')!;\n this.backButton = root.querySelector('.wxa-navbar-back')!;\n this.pages = root.querySelector('.wxa-pages')!;\n this.tabBar = root.querySelector('.wxa-tabbar')!;\n this.overlay = root.querySelector('.wxa-overlay')!;\n this.routeLabel = root.querySelector('.wxa-route')!;\n root.querySelector('.wxa-reload')!.addEventListener('click', () => location.reload());\n\n this.scaleButton.addEventListener('click', () => {\n this.scaleMode = this.scaleMode === 'fit' ? '1' : 'fit';\n try {\n localStorage.setItem(SCALE_STORAGE_KEY, this.scaleMode);\n } catch {\n // 只影响记住选择\n }\n this.applyScale();\n });\n window.addEventListener('resize', () => this.applyScale());\n this.applyScale();\n }\n\n /**\n * 窗口放不下时整体缩小手机。只用 transform:iframe 内的布局、字号、坐标都不变,\n * Playwright 也能正确换算点击位置;CSS zoom 会让 Playwright 点击错位。\n * transform 不改变占位,所以由外层 slot 按缩放后的尺寸占位。\n */\n private applyScale() {\n const width = this.profile.screenWidth + DEVICE_BEZEL * 2;\n const height = this.profile.screenHeight + DEVICE_BEZEL * 2;\n let scale = 1;\n if (this.scaleMode === 'fit') {\n const availableWidth = window.innerWidth - STAGE_PADDING * 2;\n const availableHeight = window.innerHeight - STAGE_PADDING * 2 - STAGE_GAP - this.toolbar.offsetHeight;\n const fit = Math.floor(Math.min(availableWidth / width, availableHeight / height) * 100) / 100;\n scale = Math.min(1, Math.max(MIN_SCALE, fit));\n }\n this.slot.style.width = `${width * scale}px`;\n this.slot.style.height = `${height * scale}px`;\n this.device.style.left = this.device.style.top = `${DEVICE_BEZEL * scale}px`;\n this.device.style.transform = scale === 1 ? '' : `scale(${scale})`;\n this.scaleButton.textContent = `${Math.round(scale * 100)}%`;\n this.scaleButton.title = this.scaleMode === 'fit' ? '适应窗口,点击切换为实际大小' : '实际大小,点击切换为适应窗口';\n }\n\n onBack(handler: () => void) {\n this.backButton.addEventListener('click', handler);\n }\n\n setTabBar(config: TabBarConfig | undefined, onTap: (pagePath: string, index: number) => void) {\n this.tabBarConfig = config && config.list?.length && !config.custom ? config : null;\n this.onTabTap = onTap;\n }\n\n setRoute(route: string) {\n this.routeLabel.textContent = route;\n }\n\n setNavigation(state: Partial<NavigationState>) {\n this.navigation = { ...this.navigation, ...state };\n const { title, backgroundColor, textStyle, showBack, custom } = this.navigation;\n const color = textStyle === 'black' ? '#000' : '#fff';\n\n this.navTitle.textContent = title;\n this.backButton.style.visibility = showBack ? 'visible' : 'hidden';\n this.navBar.classList.toggle('is-hidden', custom);\n this.navBar.style.background = backgroundColor;\n this.navBar.style.color = color;\n // 自定义导航栏时页面从屏幕顶部开始绘制,状态栏浮在页面上;\n // 与微信一致,状态栏文字和胶囊配色仍跟随 navigationBarTextStyle\n this.statusBar.style.background = custom ? 'transparent' : backgroundColor;\n this.statusBar.style.color = color;\n this.capsule.classList.toggle('is-light', textStyle !== 'black');\n this.statusBar.style.position = custom ? 'absolute' : '';\n this.statusBar.style.left = this.statusBar.style.right = custom ? '0' : '';\n this.statusBar.style.zIndex = custom ? '5' : '';\n }\n\n getNavigation(): NavigationState {\n return { ...this.navigation };\n }\n\n setNavigationLoading(loading: boolean) {\n this.navBar.classList.toggle('is-loading', loading);\n }\n\n /** 该页面是否显示原生 tabBar(自定义 tabBar 不算) */\n hasTabBar(pagePath: string): boolean {\n return !!this.tabBarConfig?.list.some(item => item.pagePath === pagePath);\n }\n\n /**\n * 页面窗口里 env(safe-area-inset-*) 的取值:窗口贴着屏幕边缘的一侧才有安全区。\n * 默认导航栏下窗口在导航栏下方,tabBar 页面的窗口止于 tabBar 上方。\n */\n safeAreaInsetsFor(pagePath: string, navigation: Pick<NavigationState, 'custom'>): SafeAreaInsets {\n return {\n top: navigation.custom ? this.profile.statusBarHeight : 0,\n right: 0,\n bottom: this.hasTabBar(pagePath) ? 0 : this.profile.safeAreaBottom,\n left: 0\n };\n }\n\n /** 当前页面是 tabBar 页面时传入它的路径,否则传 null */\n renderTabBar(selectedPath: string | null) {\n const config = this.tabBarConfig;\n this.tabBarVisible = selectedPath !== null && this.hasTabBar(selectedPath);\n this.tabBar.classList.toggle('is-hidden', !this.tabBarVisible);\n if (!config || !this.tabBarVisible) return;\n\n this.tabBar.style.background = config.backgroundColor || '#f7f7f7';\n this.tabBar.style.borderTopColor = config.borderStyle === 'white' ? 'rgba(255,255,255,.3)' : 'rgba(0,0,0,.1)';\n this.tabBar.innerHTML = '';\n config.list.forEach((item, index) => {\n const selected = item.pagePath === selectedPath;\n const el = document.createElement('div');\n el.className = 'wxa-tabbar-item' + (selected ? ' is-selected' : '');\n el.dataset.pagePath = item.pagePath;\n el.style.color = selected ? (config.selectedColor || '#07c160') : (config.color || '#7a7e83');\n const icon = selected ? item.selectedIconPath || item.iconPath : item.iconPath;\n if (icon) {\n const img = document.createElement('img');\n img.src = '/' + icon.replace(/^\\//, '');\n el.appendChild(img);\n }\n const text = document.createElement('span');\n text.textContent = item.text || '';\n el.appendChild(text);\n el.addEventListener('click', () => this.onTabTap(item.pagePath, index));\n this.tabBar.appendChild(el);\n });\n }\n\n /** 页面可用高度,与 getSystemInfo().windowHeight 对应;tabBar 会连同底部安全区一起占掉 */\n windowHeight(): number {\n return this.profile.screenHeight\n - this.screenTop()\n - (this.tabBarVisible ? TAB_BAR_HEIGHT + this.profile.safeAreaBottom : 0);\n }\n\n /** 页面窗口顶部到屏幕顶部的距离,与 getWindowInfo().screenTop 对应 */\n screenTop(): number {\n return this.navigation.custom ? 0 : this.profile.statusBarHeight + NAVIGATION_BAR_HEIGHT;\n }\n\n showToast(options: ToastOptions) {\n this.hideToast();\n const icon = options.image ? 'image' : options.icon || 'success';\n const wrapper = document.createElement('div');\n if (options.mask) wrapper.appendChild(maskElement(false));\n\n const toast = document.createElement('div');\n toast.className = 'wxa-toast' + (icon === 'none' ? '' : ' has-icon');\n toast.setAttribute('role', 'alert');\n if (icon === 'loading') {\n toast.appendChild(element('div', 'wxa-toast-spinner'));\n } else if (icon === 'image') {\n const img = document.createElement('img');\n img.src = options.image!;\n img.width = img.height = 40;\n toast.appendChild(img);\n } else if (icon !== 'none') {\n toast.appendChild(element('div', 'wxa-toast-icon', icon === 'error' ? '✕' : '✓'));\n }\n toast.appendChild(element('div', 'wxa-toast-title', options.title || ''));\n wrapper.appendChild(toast);\n\n this.overlay.appendChild(wrapper);\n this.toastEl = wrapper;\n if (icon !== 'loading' || options.duration) {\n this.toastTimer = setTimeout(() => this.hideToast(), options.duration ?? 1500);\n }\n }\n\n hideToast() {\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toastTimer = null;\n this.toastEl?.remove();\n this.toastEl = null;\n }\n\n showModal(options: ModalOptions): Promise<{ confirm: boolean; cancel: boolean; content?: string }> {\n return new Promise(resolve => {\n const wrapper = document.createElement('div');\n wrapper.appendChild(maskElement(true));\n const modal = element('div', 'wxa-modal');\n modal.setAttribute('role', 'dialog');\n if (options.title) modal.appendChild(element('div', 'wxa-modal-title', options.title));\n if (options.content && !options.editable) modal.appendChild(element('div', 'wxa-modal-content', options.content));\n\n let input: HTMLInputElement | null = null;\n if (options.editable) {\n input = document.createElement('input');\n input.className = 'wxa-modal-input';\n input.value = options.content || '';\n input.placeholder = options.placeholderText || '';\n modal.appendChild(input);\n }\n\n const actions = element('div', 'wxa-modal-actions');\n const close = (confirm: boolean) => {\n wrapper.remove();\n resolve({ confirm, cancel: !confirm, ...(options.editable ? { content: input!.value } : {}) });\n };\n if (options.showCancel !== false) {\n const cancel = element('button', 'wxa-modal-cancel', options.cancelText || '取消');\n cancel.style.color = options.cancelColor || '#000';\n cancel.addEventListener('click', () => close(false));\n actions.appendChild(cancel);\n }\n const confirm = element('button', 'wxa-modal-confirm', options.confirmText || '确定');\n confirm.style.color = options.confirmColor || '#576b95';\n confirm.addEventListener('click', () => close(true));\n actions.appendChild(confirm);\n modal.appendChild(actions);\n\n wrapper.appendChild(modal);\n this.overlay.appendChild(wrapper);\n });\n }\n\n showActionSheet(options: ActionSheetOptions): Promise<number | null> {\n return new Promise(resolve => {\n const wrapper = document.createElement('div');\n const mask = maskElement(true);\n const sheet = element('div', 'wxa-actionsheet');\n const close = (index: number | null) => {\n wrapper.remove();\n resolve(index);\n };\n\n if (options.alertText) sheet.appendChild(element('div', 'wxa-actionsheet-alert', options.alertText));\n options.itemList.forEach((text, index) => {\n const button = element('button', 'wxa-actionsheet-item', text);\n button.style.color = options.itemColor || '#000';\n button.addEventListener('click', () => close(index));\n sheet.appendChild(button);\n });\n const cancel = element('button', 'wxa-actionsheet-cancel', '取消');\n cancel.addEventListener('click', () => close(null));\n sheet.appendChild(cancel);\n mask.addEventListener('click', () => close(null));\n\n wrapper.append(mask, sheet);\n this.overlay.appendChild(wrapper);\n });\n }\n\n showPicker(options: PickerOptions): PickerSession {\n return openPicker(this.overlay, options);\n }\n\n showImagePreview(urls: string[], current: number) {\n openImagePreview(this.overlay, urls, current);\n }\n\n /**\n * 在手机外面提示 wxa-runner 自身的问题(如真实登录失败),不混进小程序的界面。\n * 同一时间只显示一条,新的替换旧的:业务代码反复重试时不会堆满屏幕\n */\n showNotice(title: string, message: string) {\n this.hideNotice();\n const notice = element('div', 'wxa-notice');\n notice.setAttribute('role', 'alert');\n const text = element('div', 'wxa-notice-text');\n text.append(element('div', 'wxa-notice-title', title), element('div', 'wxa-notice-message', message));\n const close = element('button', 'wxa-notice-close', '×');\n close.setAttribute('aria-label', '关闭');\n close.addEventListener('click', () => this.hideNotice());\n notice.append(element('span', 'wxa-notice-icon', '!'), text, close);\n\n this.stage.appendChild(notice);\n this.noticeEl = notice;\n this.noticeTimer = setTimeout(() => this.hideNotice(), NOTICE_DURATION);\n }\n\n hideNotice() {\n if (this.noticeTimer) clearTimeout(this.noticeTimer);\n this.noticeTimer = null;\n this.noticeEl?.remove();\n this.noticeEl = null;\n }\n\n showError(message: string) {\n this.clearError();\n const el = element('div', 'wxa-error', message);\n this.device.appendChild(el);\n }\n\n clearError() {\n this.device.querySelector('.wxa-error')?.remove();\n }\n}\n\nfunction maskElement(dim: boolean): HTMLElement {\n return element('div', 'wxa-mask' + (dim ? ' is-dim' : ''));\n}\n\nconst BACK_ICON = '<svg width=\"12\" height=\"20\" viewBox=\"0 0 12 20\"><path d=\"M10 2 2 10l8 8\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>';\n\nconst MORE_ICON = '<svg width=\"22\" height=\"8\" viewBox=\"0 0 22 8\" fill=\"currentColor\"><circle cx=\"3.5\" cy=\"4\" r=\"2.3\"/><circle cx=\"11\" cy=\"4\" r=\"3.3\"/><circle cx=\"18.5\" cy=\"4\" r=\"2.3\"/></svg>';\n\nconst CLOSE_ICON = '<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\"><circle cx=\"10\" cy=\"10\" r=\"8.2\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"/><circle cx=\"10\" cy=\"10\" r=\"3.4\" fill=\"currentColor\"/></svg>';\n\nconst STATUS_ICONS = [\n // 信号\n '<svg width=\"17\" height=\"11\" viewBox=\"0 0 17 11\" fill=\"currentColor\"><rect x=\"0\" y=\"7\" width=\"3\" height=\"4\" rx=\".8\"/><rect x=\"4.6\" y=\"5\" width=\"3\" height=\"6\" rx=\".8\"/><rect x=\"9.2\" y=\"2.6\" width=\"3\" height=\"8.4\" rx=\".8\"/><rect x=\"13.8\" y=\"0\" width=\"3\" height=\"11\" rx=\".8\"/></svg>',\n // Wi-Fi\n '<svg width=\"16\" height=\"12\" viewBox=\"0 0 16 12\" fill=\"currentColor\"><path d=\"M8 11.2L5.45 8.65A3.6 3.6 0 0 1 10.55 8.65ZM2.77 5.97A7.4 7.4 0 0 1 13.23 5.97L11.68 7.52A5.2 5.2 0 0 0 4.32 7.52ZM0.08 3.28A11.2 11.2 0 0 1 15.92 3.28L14.36 4.84A9 9 0 0 0 1.64 4.84Z\"/></svg>',\n // 电池\n '<svg width=\"25\" height=\"12\" viewBox=\"0 0 25 12\"><rect x=\".5\" y=\".5\" width=\"21.5\" height=\"11\" rx=\"3.2\" fill=\"none\" stroke=\"currentColor\" stroke-opacity=\".4\"/><rect x=\"2\" y=\"2\" width=\"18.5\" height=\"8\" rx=\"1.8\" fill=\"currentColor\"/><path d=\"M23.4 4v4a2.2 2.2 0 0 0 0-4z\" fill=\"currentColor\" fill-opacity=\".45\"/></svg>'\n].join('');\n","/**\n * 宿主:管理逻辑层 iframe 和各页面的渲染层 iframe\n *\n * 宿主不实现页面生命周期——它只维护页面栈并在路由变化时派发 onAppRoute,\n * App/Page 的生命周期全部由官方基础库根据这个事件驱动。\n */\n\nimport type { AppInfo, FrameBridge, FrameKind, HostApi, InvokeCallback } from '../types';\nimport { ApiContext, ApiRegistry, ApiResult, fail, ok } from './api/registry';\nimport { createAudioApis } from './api/audio';\nimport { createFileSystemApis } from './api/fs';\nimport { createLibFileApis } from './api/libFiles';\nimport { createMapApis, MapOperations } from './api/map';\nimport { createMediaApis } from './api/media';\nimport { createMiscApis } from './api/misc';\nimport { createNetworkApis, RequestLog } from './api/network';\nimport { createPickerApis, fetchRegionData } from './api/picker';\nimport { RequestRoutes } from './api/routes';\nimport { createSavedFileApis } from './api/savedFiles';\nimport { createStorageApis, MiniProgramStorage } from './api/storage';\nimport { createSubpackageApis } from './api/subpackages';\nimport { createSystemApis } from './api/system';\nimport { tempFileRootPath } from './api/tempFiles';\nimport { createUiApis } from './api/ui';\nimport { createWebViewApis } from './api/webView';\nimport { PageStack } from './PageStack';\nimport { PageView } from './PageView';\nimport { cloneInto, cloneNativeInto } from './realm';\nimport { chooseFiles, hasUserActivation } from './ui/fileChooser';\nimport { NavigationState, PhoneShell } from './ui/PhoneShell';\n\nexport type OpenType = 'appLaunch' | 'navigateTo' | 'navigateBack' | 'redirectTo' | 'reLaunch' | 'switchTab';\n\nexport interface LaunchTarget {\n path: string;\n query: Record<string, string>;\n}\n\nexport interface FrameError {\n kind: FrameKind;\n webviewId: number;\n message: string;\n stack?: string;\n /** 调用了未实现的原生 API 时为 API 名称 */\n api?: string;\n}\n\nconst ROUTE_DONE_DELAY = 300;\nconst PAGE_LOAD_TIMEOUT = 15000;\n\nexport class Host implements HostApi {\n readonly device;\n readonly errors: FrameError[] = [];\n /** 小程序发出的 wx.request */\n readonly requests = new RequestLog();\n readonly api = new ApiRegistry(context => this.reportUnimplemented(context));\n readonly shell: PhoneShell;\n readonly storage: MiniProgramStorage;\n /** setup 和测试 API 声明的请求拦截 */\n readonly routes = new RequestRoutes();\n private readonly mapOperations = new MapOperations((webviewId, event, data) => this.publishToPages(event, data, [webviewId]));\n private service: { win: Window; bridge: FrameBridge } | null = null;\n /** 新版基础库的业务子上下文;旧版基础库业务代码直接在逻辑层 iframe 里 */\n private appContext: Window | null = null;\n private serviceLoaded!: () => void;\n private readonly serviceReady = new Promise<void>(resolve => {\n this.serviceLoaded = resolve;\n });\n private readonly pages = new Map<number, PageView>();\n private readonly tabPages = new Map<string, PageView>();\n private readonly stack = new PageStack<PageView>();\n private readonly tabPaths: Set<string>;\n private nextWebviewId = 1;\n private routeChain: Promise<unknown> = Promise.resolve();\n private routeListeners: Array<(page: PageView, openType: OpenType) => void> = [];\n\n constructor(readonly info: AppInfo, root: HTMLElement) {\n this.device = info.device;\n this.shell = new PhoneShell(root, info.device);\n this.tabPaths = new Set((info.wxConfig.tabBar?.list || []).map((item: any) => stripHtml(item.pagePath)));\n this.storage = new MiniProgramStorage(window.localStorage, info.appid);\n\n const tabBar = info.wxConfig.tabBar\n ? { ...info.wxConfig.tabBar, list: info.wxConfig.tabBar.list.map((item: any) => ({ ...item, pagePath: stripHtml(item.pagePath) })) }\n : undefined;\n this.shell.setTabBar(tabBar, pagePath => this.enqueueRoute(() => this.switchTab(pagePath)));\n this.shell.onBack(() => this.enqueueRoute(() => this.navigateBack(1)));\n\n this.registerApis();\n }\n\n async start(target: LaunchTarget) {\n const frame = document.createElement('iframe');\n frame.name = 'wxa-appservice';\n frame.style.display = 'none';\n const params = new URLSearchParams({ v: String(this.info.version), path: target.path, query: new URLSearchParams(target.query).toString() });\n frame.src = `/__wxa__/appservice.html?${params}`;\n document.body.appendChild(frame);\n\n document.addEventListener('visibilitychange', () => {\n const page = this.currentPage();\n if (!page) return;\n const event = document.hidden ? 'onAppEnterBackground' : 'onAppEnterForeground';\n this.emitToService(event, { path: page.path, query: page.query, scene: 1001, referrerInfo: {} });\n });\n\n await this.serviceReady;\n await this.enqueueRoute(() => this.launch(target));\n }\n\n // ---------------------------------------------------------------------------\n // HostApi:供 iframe 内的桥调用\n // ---------------------------------------------------------------------------\n\n registerFrame(kind: FrameKind, win: Window, bridge: FrameBridge, webviewId: number) {\n if (kind === 'service') {\n this.service = { win, bridge };\n } else {\n this.pages.get(webviewId)?.attach(win, bridge);\n }\n }\n\n registerAppContext(win: Window | null) {\n this.appContext = win;\n }\n\n frameLoaded(kind: FrameKind, webviewId: number) {\n if (kind === 'service') this.serviceLoaded();\n else this.pages.get(webviewId)?.loaded();\n }\n\n invoke(kind: FrameKind, win: Window, api: string, args: unknown, callback?: InvokeCallback) {\n const webviewId = kind === 'webview' ? this.webviewIdOf(win) : this.currentPage()?.id ?? 0;\n const result = this.api.invoke(api, args, { api, from: kind, webviewId });\n const deliver = (res: ApiResult | string) => {\n if (callback) callback(cloneNativeInto(kind === 'service' ? this.serviceWindow()! : win, res));\n };\n\n if (result && typeof (result as Promise<ApiResult>).then === 'function') {\n (result as Promise<ApiResult | string>).then(deliver);\n } else {\n deliver(result as ApiResult | string);\n }\n }\n\n publish(kind: FrameKind, win: Window, event: string, data: unknown, webviewIds?: number[]) {\n if (kind === 'service') {\n this.publishToPages(event, data, webviewIds);\n return;\n }\n if (event === 'operateMapCallback' && this.mapOperations.receive(data)) return;\n\n const fromId = this.webviewIdOf(win);\n const service = this.service;\n if (!service) return;\n const payload = this.cloneForService(data);\n queueMicrotask(() => service.bridge.__dispatchSub(event, payload, fromId));\n }\n\n /** 不指定目标时发给所有页面:旧版 canvas 的绘制指令就是这样发的,由 canvasNumber 找到对应画布 */\n private publishToPages(event: string, data: unknown, webviewIds?: number[]) {\n const targets = webviewIds?.length ? webviewIds.map(id => this.pages.get(Number(id))) : this.livePages();\n const message = event === 'canvasActionsChanged' ? withDrawableImages(data) : data;\n for (const page of targets) {\n page?.dispatch((bridge, target) => {\n const payload = cloneInto(target, message);\n queueMicrotask(() => bridge.__dispatchSub(event, payload, 0));\n });\n }\n }\n\n reportError(kind: FrameKind, webviewId: number, error: unknown) {\n // 错误对象来自 iframe,跨 realm 的 instanceof Error 不成立;DOMException 等也不是 Error 的实例\n const err = typeof (error as Error | null)?.message === 'string' ? error as Error : null;\n this.errors.push({\n kind,\n webviewId,\n message: err ? err.message : String(error),\n stack: typeof err?.stack === 'string' ? err.stack : undefined\n });\n }\n\n /**\n * 业务代码只运行在逻辑层,所以只记逻辑层调用、名字在 wx 上的 API,每个 API 一次。\n * 其余是基础库内部调用的原生接口(如 getPermissionBytes),业务既没调用也 mock 不了\n */\n private reportUnimplemented({ api, from }: ApiContext) {\n const wx = (this.serviceWindow() as any)?.wx;\n if (from !== 'service' || typeof wx?.[api] !== 'function') return;\n if (this.errors.some(error => error.api === api)) return;\n this.errors.push({\n kind: 'service',\n webviewId: 0,\n api,\n message: `wx.${api} 尚未实现,返回了默认成功。可以用 mock 覆盖,启动阶段就调用的要在 setup 里 mock`\n });\n }\n\n // ---------------------------------------------------------------------------\n // 路由\n // ---------------------------------------------------------------------------\n\n currentPage(): PageView | undefined {\n return this.stack.current();\n }\n\n pageStack(): PageView[] {\n return this.stack.entries();\n }\n\n /** 所有活着的页面:页面栈加上隐藏中的 tabBar 页面 */\n livePages(): PageView[] {\n return [...this.pages.values()];\n }\n\n /** 业务代码所在的 window:getCurrentPages / wx 等在它上面 */\n serviceWindow(): Window | null {\n return this.appContext ?? this.service?.win ?? null;\n }\n\n /**\n * 交给逻辑层的值属于业务代码所在的全局环境,而不是逻辑层 iframe:新版基础库不一定在业务子上下文里\n * 重建这些值,属于别的 iframe 的对象在业务代码里 instanceof 不成立,setData 也会把这样的数组当成普通对象\n */\n private cloneForService<T>(value: T): T {\n return cloneInto(this.serviceWindow()!, value);\n }\n\n onRoute(listener: (page: PageView, openType: OpenType) => void) {\n this.routeListeners.push(listener);\n }\n\n /** 路由操作串行执行,避免连续跳转时页面栈错乱 */\n enqueueRoute<T>(operation: () => Promise<T>): Promise<T> {\n const run = this.routeChain.then(operation, operation);\n this.routeChain = run.catch(() => undefined);\n return run;\n }\n\n private async launch(target: LaunchTarget) {\n const page = await this.openPage(target.path, target.query);\n this.stack.reset(page);\n this.activate(page, 'appLaunch');\n }\n\n async navigateTo(url: string): Promise<ApiResult> {\n if (!this.stack.canPush()) return fail('navigateTo', 'webview count limit exceed');\n const { path, query } = this.resolveUrl(url);\n if (this.tabPaths.has(path)) return fail('navigateTo', 'can not navigateTo a tabbar page');\n if (!this.hasPage(path)) return fail('navigateTo', `page \"${path}\" is not found`);\n\n const page = await this.openPage(path, query);\n this.stack.push(page);\n this.activate(page, 'navigateTo');\n return ok('navigateTo', { webviewId: page.id });\n }\n\n async navigateBack(delta: number): Promise<ApiResult> {\n if (this.stack.size <= 1) return fail('navigateBack', 'cannot navigate back at first page.');\n this.stack.pop(delta).forEach(page => this.closePage(page));\n this.activate(this.currentPage()!, 'navigateBack');\n return ok('navigateBack');\n }\n\n async redirectTo(url: string): Promise<ApiResult> {\n const { path, query } = this.resolveUrl(url);\n if (this.tabPaths.has(path)) return fail('redirectTo', 'can not redirectTo a tabbar page');\n if (!this.hasPage(path)) return fail('redirectTo', `page \"${path}\" is not found`);\n\n const page = await this.openPage(path, query);\n const previous = this.stack.replaceTop(page);\n if (previous) this.closePage(previous);\n this.activate(page, 'redirectTo');\n return ok('redirectTo');\n }\n\n async reLaunch(url: string): Promise<ApiResult> {\n const { path, query } = this.resolveUrl(url);\n if (!this.hasPage(path)) return fail('reLaunch', `page \"${path}\" is not found`);\n\n const page = await this.openPage(path, query, { reuseTab: false });\n this.stack.reset(page).forEach(previous => this.closePage(previous, { keepTab: false }));\n for (const [tabPath, tabPage] of this.tabPages) {\n if (tabPage !== page) {\n this.closePage(tabPage, { keepTab: false });\n this.tabPages.delete(tabPath);\n }\n }\n this.activate(page, 'reLaunch');\n return ok('reLaunch');\n }\n\n async switchTab(url: string): Promise<ApiResult> {\n const { path } = this.resolveUrl(url);\n if (!this.tabPaths.has(path)) return fail('switchTab', 'can not switch to no-tabBar page');\n if (this.currentPage()?.path === path && this.stack.size === 1) return ok('switchTab');\n\n const page = await this.openPage(path, {});\n this.stack.reset(page).forEach(previous => this.closePage(previous));\n this.activate(page, 'switchTab');\n return ok('switchTab');\n }\n\n private async openPage(path: string, query: Record<string, string>, options = { reuseTab: true }): Promise<PageView> {\n const isTab = this.tabPaths.has(path);\n if (isTab && options.reuseTab && this.tabPages.has(path)) {\n return this.tabPages.get(path)!;\n }\n\n const page = new PageView(\n this.nextWebviewId++,\n path,\n query,\n this.shell.pages,\n this.info.version,\n this.navigationFor(path)\n );\n // 渲染层注册桥时(基础库加载前)写入,首屏就按正确的安全区排版\n page.setSafeAreaInsets(this.shell.safeAreaInsetsFor(path, page.navigation));\n this.pages.set(page.id, page);\n if (isTab) this.tabPages.set(path, page);\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<void>(resolve => {\n timer = setTimeout(() => {\n console.error(`[wxa-runner] 页面 ${path} 的渲染层 ${PAGE_LOAD_TIMEOUT}ms 内没有加载完成,请检查控制台报错`);\n resolve();\n }, PAGE_LOAD_TIMEOUT);\n });\n await Promise.race([page.ready, timedOut]);\n clearTimeout(timer);\n return page;\n }\n\n private closePage(page: PageView, options = { keepTab: true }) {\n if (options.keepTab && this.tabPaths.has(page.path) && this.tabPages.get(page.path) === page) {\n page.hide();\n return;\n }\n if (this.tabPages.get(page.path) === page) this.tabPages.delete(page.path);\n this.pages.delete(page.id);\n page.destroy();\n }\n\n private activate(page: PageView, openType: OpenType) {\n for (const other of this.pages.values()) {\n if (other !== page) other.hide();\n }\n page.show();\n\n page.navigation = { ...page.navigation, showBack: this.stack.size > 1 };\n this.shell.setNavigation(page.navigation);\n this.shell.renderTabBar(this.tabPaths.has(page.path) ? page.path : null);\n this.shell.setRoute(page.url);\n this.updateLocation(page);\n\n const data = { path: page.path, query: page.query, openType, webviewId: page.id };\n this.emitToService('onAppRoute', data, page.id);\n setTimeout(() => {\n // 期间又发生了路由时,基础库会把迟到的 routeDone 当作错误\n if (this.currentPage() === page) this.emitToService('onAppRouteDone', data, page.id);\n }, ROUTE_DONE_DELAY);\n this.routeListeners.forEach(listener => listener(page, openType));\n }\n\n /** 宿主地址栏同步为当前页面,刷新后可回到同一页面 */\n private updateLocation(page: PageView) {\n const params = new URLSearchParams(location.search);\n params.set('path', page.path);\n for (const key of [...params.keys()]) {\n if (key !== 'path') params.delete(key);\n }\n for (const [key, value] of Object.entries(page.query)) params.set(key, value);\n history.replaceState(null, '', `${location.pathname}?${params}`);\n }\n\n private navigationFor(path: string): NavigationState {\n const window = {\n ...this.info.wxConfig.global?.window,\n ...this.info.wxConfig.page?.[path + '.html']?.window\n };\n return {\n title: window.navigationBarTitleText || '',\n backgroundColor: window.navigationBarBackgroundColor || '#000000',\n textStyle: window.navigationBarTextStyle === 'black' ? 'black' : 'white',\n showBack: false,\n custom: window.navigationStyle === 'custom'\n };\n }\n\n private hasPage(path: string): boolean {\n return this.info.pages.includes(path);\n }\n\n /**\n * 基础库调用路由 API 前已经把相对路径解析成根路径并加上 .html(如 \"pages/a/a.html?id=1\"),\n * 这里只做格式归一。\n */\n resolveUrl(url: string): { path: string; query: Record<string, string> } {\n const [rawPath, rawQuery = ''] = String(url || '').split('?');\n const path = stripHtml(rawPath.replace(/^\\/+/, ''));\n return { path, query: Object.fromEntries(new URLSearchParams(rawQuery)) };\n }\n\n // ---------------------------------------------------------------------------\n // 事件\n // ---------------------------------------------------------------------------\n\n emitToService(event: string, data: unknown, webviewId?: number) {\n const service = this.service;\n if (!service) return;\n const payload = cloneNativeInto(this.serviceWindow()!, data);\n queueMicrotask(() => service.bridge.__dispatchOn(event, payload, webviewId));\n }\n\n /** 派发给渲染层的原生事件(渲染层里 WeixinJSBridge.on 收到) */\n emitToWebview(webviewId: number, event: string, data: unknown) {\n this.pages.get(webviewId)?.dispatch((bridge, target) => {\n const payload = cloneNativeInto(target, data);\n queueMicrotask(() => bridge.__dispatchOn(event, payload, webviewId));\n });\n }\n\n private webviewIdOf(win: Window): number {\n for (const page of this.pages.values()) {\n if (page.win === win) return page.id;\n }\n return 0;\n }\n\n private updateNavigation(state: Partial<NavigationState>) {\n const page = this.currentPage();\n if (!page) return;\n page.navigation = { ...page.navigation, ...Object.fromEntries(Object.entries(state).filter(([, v]) => v !== undefined)) };\n this.shell.setNavigation(page.navigation);\n }\n\n private registerApis() {\n const routeApi = (handler: (args: any) => Promise<ApiResult>) =>\n (args: any) => this.enqueueRoute(() => handler(args));\n\n this.api.register({\n navigateTo: routeApi(args => this.navigateTo(args.url)),\n navigateBack: routeApi(args => this.navigateBack(args.delta || 1)),\n redirectTo: routeApi(args => this.redirectTo(args.url)),\n reLaunch: routeApi(args => this.reLaunch(args.url)),\n switchTab: routeApi(args => this.switchTab(args.url)),\n ...createStorageApis(this.storage),\n ...createSubpackageApis({\n subPackages: this.info.wxConfig.subPackages || [],\n emit: (event, data) => this.emitToService(event, data)\n }),\n ...createSavedFileApis(this.storage),\n ...createFileSystemApis(),\n ...createSystemApis({\n device: this.device,\n baseLibVersion: this.info.baseLibVersion,\n windowHeight: () => this.shell.windowHeight(),\n screenTop: () => this.shell.screenTop()\n }),\n ...createNetworkApis({\n emit: (event, data) => this.emitToService(event, data),\n defaultTimeout: () => this.info.wxConfig.networkTimeout?.request || 60000,\n routes: this.routes,\n onRequest: request => this.requests.add(request)\n }),\n ...createAudioApis({ emit: (event, data) => this.emitToService(event, data) }),\n ...createMapApis({ registry: this.api, operations: this.mapOperations }),\n ...createLibFileApis({ windowOf: webviewId => this.pages.get(webviewId)?.win }),\n ...createUiApis({ shell: this.shell, updateNavigation: state => this.updateNavigation(state) }),\n ...createMediaApis({\n showActionSheet: options => this.shell.showActionSheet(options),\n chooseFiles,\n hasUserActivation,\n showImagePreview: (urls, current) => this.shell.showImagePreview(urls, current)\n }),\n ...createPickerApis({\n showPicker: options => this.shell.showPicker(options),\n emitToWebview: (webviewId, event, data) => this.emitToWebview(webviewId, event, data),\n loadRegionData: fetchRegionData\n }),\n ...createWebViewApis({\n documentOf: webviewId => this.pages.get(webviewId)?.win?.document,\n emitToWebview: (webviewId, event, data) => this.emitToWebview(webviewId, event, data)\n }),\n ...createMiscApis(this.info.appid, {\n realLogin: this.info.realLogin,\n onRealLoginFail: (api, reason) => this.shell.showNotice(`wx.${api} 真实登录失败`, reason)\n })\n });\n }\n}\n\n/**\n * 旧版 canvas 的绘制指令里,drawImage 用到的临时文件换成根路径。基础库的网页实现把 http(s) 地址\n * 都当成网络图片直接跳过(只放行开发者工具的 http://tmp/ 等),不报错,画布上什么也没有\n */\nfunction withDrawableImages(message: any): unknown {\n const actions = message?.data?.actions;\n if (!Array.isArray(actions)) return message;\n return {\n ...message,\n data: {\n ...message.data,\n actions: actions.map(action => {\n const [src, ...rest] = action.data ?? [];\n return action.method === 'drawImage' && typeof src === 'string'\n ? { ...action, data: [tempFileRootPath(src), ...rest] }\n : action;\n })\n }\n };\n}\n\nfunction stripHtml(path: string): string {\n return path.replace(/\\.html$/, '');\n}\n","/**\n * 热更新:不刷新宿主,应用样式、模板和页面逻辑的改动,保留页面状态(哪些改动能热更新见 server/hmr.ts)\n *\n * 样式在每个渲染层里原地替换(见 updateStyles);模板和逻辑借助基础库为开发者工具准备的接口\n * __virtualDOM__.updateWxAppCode(开关见 server/html.ts):\n * - 模板:按模板路径更新,基础库用实例当前的 data 重新渲染\n * - Page() 构造的页面:不走基础库按 .js 路径的更新——那会重新挂载页面(onUnload → onLoad),data 回到初始值。\n * 这里把新方法换到活着的页面实例上,再重新注册 Page,之后新打开的页面用新代码\n * - Component() 构造的页面和组件(uni-app 的页面也是):状态常在框架自己的实例里(如 Vue 的 setup),\n * 换方法保不住,交给基础库按 .js 路径重新挂载这些实例;页面栈、globalData、其他页面不受影响\n */\n\nimport type { Host } from './Host';\n\nexport interface HotUpdate {\n version: number;\n templates: string[];\n scripts: string[];\n styles: string[];\n}\n\n/**\n * @throws 拿不到新代码、新代码执行出错、模块没有调用 Page() / Component() 等无法热更新的情况;调用方应整页刷新\n */\nexport async function applyHotUpdate(host: Host, update: HotUpdate): Promise<void> {\n const hasTemplates = update.templates.length > 0;\n const hasStyles = update.styles.length > 0;\n const v = `?v=${update.version}`;\n const [pageStyles, pageTemplates, serviceTemplates, moduleScripts] = await Promise.all([\n hasStyles ? fetchText(`/__wxa__/page-styles.js${v}`) : '',\n hasTemplates ? fetchText(`/__wxa__/page-templates.js${v}`) : '',\n hasTemplates ? fetchText(`/__wxa__/service-templates.js${v}`) : '',\n Promise.all(update.scripts.map(id => fetchText(`/__wxa__/module/${encodeURI(id)}.js${v}`)))\n ]);\n\n // 与路由串行:跳转进行到一半时页面列表和实例都不稳定\n await host.enqueueRoute(async () => {\n const service = host.serviceWindow() as any;\n if (!service?.__virtualDOM__?.updateWxAppCode) throw new Error('基础库的热更新开关没有打开');\n\n if (hasStyles) {\n for (const page of host.livePages()) {\n if (page.win) updateStyles(page.win as any, pageStyles);\n }\n }\n\n if (hasTemplates) {\n // 渲染层先换上新模板,逻辑层随后发出的重新渲染指令才能对上\n for (const page of host.livePages()) {\n if (page.win) updateTemplates(page.win as any, pageTemplates, update.templates);\n }\n updateTemplates(service, serviceTemplates, update.templates);\n }\n\n update.scripts.forEach((id, index) => updateScript(service, host, id, moduleScripts[index]));\n });\n}\n\n/**\n * 重新执行公共样式(app.wxss、被 @import 的文件),再重放这个渲染层用过的页面和组件样式。\n * 不区分改了哪个文件:没改的样式写回相同的内容\n *\n * 基础库按「路径:组件 class 前缀」登记样式表,同一个 key 再次写入时原地替换 <style> 的内容。\n * 每次写入会多登记一个 rpx 重算回调(窗口尺寸变化时重新生成样式),回调按登记顺序执行,最新的样式最后写入\n *\n * 不用基础库为 .wxss 登记的 updateWxAppCode 回调:它按组件的方式注入页面样式,页面里合法的 ID、标签选择器\n * 每次都会报「组件中不允许」的警告,page-isolated 的页面还会换成带组件前缀的另一份样式、旧样式留在原处\n */\nfunction updateStyles(win: any, code: string) {\n const sheets: Record<string, StyleSheetEntry> | undefined = win.__styleSheetManager2__?._pathMap;\n if (!sheets) throw new Error('基础库没有样式表管理器,无法热替换样式');\n const applied = Object.keys(sheets);\n runScript(win, code);\n\n for (const key of applied) {\n const [, file, classPrefix] = /^\\.\\/(.+\\.wxss):(.*)$/.exec(key) || [];\n // app.wxss 等公共样式没有注册到 __wxAppCode__,执行 code 时已经替换\n const inject = file && win.__wxAppCode__[file];\n if (typeof inject === 'function') inject(classPrefix);\n }\n restoreSheetOrder(Object.values(sheets));\n // 与基础库自己更新样式后一样通知组件重新布局,如 movable-area 重新计算尺寸\n win.wx.triggerPageReRender();\n}\n\ninterface StyleSheetEntry {\n inserted: boolean;\n style: HTMLStyleElement;\n}\n\n/**\n * 加载时为空的样式表只登记、不插入页面,第一次写入内容时追加在 head 末尾,排到了本该在它后面的样式之后。\n * 按登记顺序(即加载时的注入顺序)挪回原位,层叠结果才与刷新后一致\n */\nfunction restoreSheetOrder(sheets: StyleSheetEntry[]) {\n let next: HTMLStyleElement | null = null;\n for (const { inserted, style } of sheets.reverse()) {\n // 被基础库移出页面的不参与排序,如 page-isolated 页面里的 app.wxss\n if (!inserted || !style.isConnected) continue;\n if (next && style.compareDocumentPosition(next) & Node.DOCUMENT_POSITION_PRECEDING) next.before(style);\n next = style;\n }\n}\n\nfunction updateTemplates(win: any, code: string, units: string[]) {\n // wcc 生成的模板把编译结果缓存在 __WXML_GLOBAL__ 上,不清掉的话新代码会读到旧缓存。\n // 保留 wxs_nf_init:WXS 运行时只能初始化一次,重复执行会因改写内置对象原型而报错\n const cache = win.__WXML_GLOBAL__;\n if (cache) Object.assign(cache, { ops_cached: {}, ops_set: {}, ops_init: {}, debuginfo_set: {}, modules: {} });\n runScript(win, code);\n\n for (const id of units) {\n const generate = win.__wxAppCode__[id + '.wxml'];\n if (generate) win.__virtualDOM__.updateWxAppCode(id + '.wxml', generate);\n }\n}\n\n/** 每次热更新的模块 id 都不同:同一个构建版本也可能被应用两次 */\nlet hotModuleSeq = 0;\n\nfunction updateScript(service: any, host: Host, id: string, moduleScript: string) {\n // 基础库忽略对已有模块的重复 define,新代码换个同目录的模块 id 执行:相对路径的 require 解析结果不变,\n // 它依赖的模块直接取缓存,不会重新执行\n const registration = loadModule(service, moduleScript, `${id}.hot-${++hotModuleSeq}.js`);\n if (!registration) throw new Error(`${id}.js 没有调用 Page() 或 Component(),无法热更新`);\n\n if (registration.constructor === service.Page) {\n for (const page of host.livePages()) {\n if (page.path !== id) continue;\n const instance = service.__virtualDOM__.getRootNode(page.id)?.__methodCaller;\n if (!instance) throw new Error(`找不到页面 ${id}(webviewId ${page.id})的实例`);\n swapMethods(instance, registration.options);\n }\n register(service, id, registration);\n return;\n }\n\n // 回调由基础库在注册时登记;没被调用说明没登记上,这次更新不会生效\n let registered = false;\n service.__virtualDOM__.updateWxAppCode(`${id}.js`, () => {\n register(service, id, registration);\n registered = true;\n });\n if (!registered) throw new Error(`基础库没有登记 ${id}.js 的热更新回调`);\n}\n\ninterface Registration {\n constructor: (options: Record<string, any>) => unknown;\n options: Record<string, any>;\n}\n\n/** 按 bootstrap 里 require 页面和组件时的方式设置当前文件,再真正注册 */\nfunction register(service: any, id: string, { constructor, options }: Registration) {\n service.__wxRoute = id;\n service.__wxRouteBegin = true;\n service.__wxAppCurrentFile__ = id + '.js';\n constructor(options);\n}\n\n/**\n * 以新模块 id 执行模块,拦下 Page() / Component() 的参数而不注册\n *\n * 逻辑层的 define 不可改写,这里把模块脚本包进以 define 为参数的函数来取出模块函数。\n * Page / Component 要改全局:uni-app 等框架在自己的 vendor 模块里调用它们,包一层参数拦不到\n */\nfunction loadModule(service: any, script: string, hotId: string): Registration | undefined {\n let factory: unknown;\n service.__wxaHotDefine__ = (_id: string, fn: unknown) => {\n factory = fn;\n };\n try {\n runScript(service, `(function (define) {\\n${script}\\n})(__wxaHotDefine__);`);\n } finally {\n delete service.__wxaHotDefine__;\n }\n if (typeof factory !== 'function') throw new Error('模块脚本没有 define 模块');\n service.define(hotId, factory);\n\n const { Page, Component } = service;\n let registration: Registration | undefined;\n service.Page = (options: Record<string, any>) => {\n registration = { constructor: Page, options };\n };\n service.Component = (options: Record<string, any>) => {\n registration = { constructor: Component, options };\n };\n try {\n if (service.Page === Page || service.Component === Component) throw new Error('无法拦截 Page / Component');\n service.require(hotId);\n } finally {\n service.Page = Page;\n service.Component = Component;\n }\n return registration;\n}\n\n/**\n * 方法一律换新;data 和其他非函数字段(如 pageSize)可能已被运行时改过,属于状态:\n * 已有的保持不动,只补上新增的,改了初始值的对当前实例不生效\n */\nfunction swapMethods(instance: any, definition: Record<string, any>) {\n for (const [key, value] of Object.entries(definition)) {\n if (typeof value === 'function') instance[key] = value;\n else if (key !== 'data' && !(key in instance)) instance[key] = value;\n }\n const data = definition.data || {};\n const added = Object.keys(data).filter(key => !(key in instance.data));\n if (added.length) instance.setData(Object.fromEntries(added.map(key => [key, data[key]])));\n}\n\n/**\n * 在 win 的全局作用域执行代码,出错时抛出(不记入宿主的错误列表)\n *\n * 不用 win.eval:新版基础库会删掉所在上下文的 eval。内联脚本同步执行,\n * 出错时在 win 上派发 error 事件,捕获阶段先于 frame.ts 的错误上报拦下\n */\nfunction runScript(win: any, code: string) {\n let failed = false;\n let error: unknown;\n const onError = (event: ErrorEvent) => {\n failed = true;\n error = event.error ?? new Error(event.message);\n event.stopImmediatePropagation();\n event.preventDefault();\n };\n const script = win.document.createElement('script');\n script.text = code;\n win.addEventListener('error', onError, true);\n try {\n win.document.head.appendChild(script);\n } finally {\n win.removeEventListener('error', onError, true);\n script.remove();\n }\n if (failed) throw error;\n}\n\nasync function fetchText(url: string): Promise<string> {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`${url} ${response.status}`);\n return response.text();\n}\n","/**\n * wxa-runner 触发的整页刷新(改了无法热更新的文件、热更新失败)保留页面栈:\n * 刷新前记下每一页的路径和参数,启动后依次重新打开\n *\n * 开发者手动刷新不经过这里,只按地址栏恢复当前页——手动刷新通常就是想从头来过。\n * 为此记录在启动时就取出并删掉;恢复完成之前又被 wxa-runner 刷新时,再原样写回去。\n */\n\nimport type { Host, LaunchTarget } from './Host';\n\nexport class PageStackRestore {\n private readonly key: string;\n /** 本次启动要恢复的页面栈 */\n private saved: LaunchTarget[];\n /** 恢复完成前(包括编译、setup 出错没能启动)自动刷新,要把 saved 原样记回去 */\n private restoring: boolean;\n\n /** 按 appid 区分:同一个标签页换了项目时不会串用 */\n constructor(appid: string) {\n this.key = `wxa-runner:reload-page-stack:${appid}`;\n this.saved = read(this.key);\n this.restoring = this.saved.length > 0;\n }\n\n /** 启动页:记下的第一页;记下的页面已经不存在时,从它开始往后都不恢复 */\n launchTarget(pages: string[], fallback: LaunchTarget): LaunchTarget {\n const invalid = this.saved.findIndex(entry => !pages.includes(entry.path));\n if (invalid >= 0) this.saved = this.saved.slice(0, invalid);\n return this.saved[0] ?? fallback;\n }\n\n /**\n * 在已启动的第一页之上依次 navigateTo 其余页面;某一页打不开就停下\n *\n * 整段放进同一个路由任务:恢复期间开发者点返回、切 tab 会排在恢复完成之后\n */\n async reopen(host: Host) {\n try {\n await host.enqueueRoute(async () => {\n for (const { path, query } of this.saved.slice(1)) {\n const search = new URLSearchParams(query).toString();\n const result = await host.navigateTo(search ? `${path}?${search}` : path);\n if (!String(result.errMsg).endsWith(':ok')) {\n console.warn(`[wxa-runner] 恢复页面栈时打不开 ${path}:${result.errMsg}`);\n return;\n }\n }\n });\n } finally {\n this.restoring = false;\n }\n }\n\n /** 记下当前页面栈后整页刷新 */\n reload(host: Host | undefined) {\n const stack = this.restoring ? this.saved : host?.pageStack().map(page => ({ path: page.path, query: page.query })) ?? [];\n if (stack.length) {\n try {\n sessionStorage.setItem(this.key, JSON.stringify(stack));\n } catch {\n // 存不了就只恢复当前页\n }\n }\n location.reload();\n }\n}\n\nfunction read(key: string): LaunchTarget[] {\n try {\n const saved = JSON.parse(sessionStorage.getItem(key) || '[]');\n sessionStorage.removeItem(key);\n if (!Array.isArray(saved)) return [];\n return saved\n .filter(entry => entry && typeof entry.path === 'string')\n .map(entry => ({ path: entry.path, query: { ...entry.query } }));\n } catch {\n return [];\n }\n}\n","/**\n * 执行 setup:在逻辑层创建之前预置存储、覆盖原生 API\n *\n * 必须早于小程序启动:基础库会把读过的存储缓存在内存里,启动后再从宿主写入,\n * wx.getStorageSync 读不到新值。\n */\n\nimport type { MockValue, RouteHandler, SetupApi, SetupConfig, SetupEnv } from '../../setup';\nimport { proxyFetch } from './api/network';\nimport type { ApiRegistry } from './api/registry';\nimport type { RequestRoutes } from './api/routes';\nimport { decodeStorageValue, encodeStorageValue, MiniProgramStorage } from './api/storage';\n\nexport interface SetupTarget {\n storage: MiniProgramStorage;\n api: ApiRegistry;\n routes: RequestRoutes;\n}\n\nexport interface SetupSummary {\n storage: string[];\n mock: string[];\n network: string[];\n}\n\nconst CONFIG_KEYS = ['storage', 'mock', 'network', 'run'];\nconst NETWORK_KEYS = ['routes'];\nconst STORAGE_NAMESPACE = 's0';\n\n/** 基础库里这些 API 不经同名 invoke 实现,按 wx 的名字 mock 不会生效 */\nexport const TASK_APIS = new Set(['request', 'downloadFile', 'uploadFile', 'connectSocket']);\nconst STORAGE_API = /^(get|set|remove|clear)Storage(Info)?(Sync)?$/;\n\n/**\n * @param definition setup 文件的默认导出\n * @param env 暴露给 setup 的环境变量\n * @throws 配置写错或 setup 自身执行出错时;此时已应用的部分不会回滚,调用方不应继续启动小程序\n */\nexport async function applySetup(definition: unknown, target: SetupTarget, env: SetupEnv): Promise<SetupSummary> {\n const summary: SetupSummary = { storage: [], mock: [], network: [] };\n const record = (list: string[], name: string) => {\n if (!list.includes(name)) list.push(name);\n };\n\n const setStorage = (key: string, value: unknown, label = key) => {\n let encoded;\n try {\n encoded = encodeStorageValue(value);\n } catch (error) {\n throw new Error(`storage.${label}:${(error as Error).message}`);\n }\n target.storage.set(STORAGE_NAMESPACE, key, encoded.data, encoded.dataType);\n record(summary.storage, key);\n };\n\n const mock = (api: string, impl: MockValue) => {\n checkMock(api, impl);\n target.api.mock(api, impl);\n record(summary.mock, api);\n };\n\n const route = (pattern: string, handler: RouteHandler) => {\n try {\n target.routes.add(pattern, handler);\n } catch (error) {\n throw new Error(`network.routes[${JSON.stringify(pattern)}]:${(error as Error).message}`);\n }\n record(summary.network, pattern);\n };\n\n const config = await resolveConfig(definition, env);\n\n for (const [key, value] of Object.entries(config.storage || {})) setStorage(key, value);\n for (const [api, impl] of Object.entries(config.mock || {})) mock(api, impl);\n for (const [pattern, handler] of Object.entries(config.network?.routes || {})) route(pattern, handler);\n\n if (config.run) {\n const wxa: SetupApi = {\n env,\n storage: {\n get: key => {\n const item = target.storage.get(STORAGE_NAMESPACE, key);\n return item ? decodeStorageValue(item) : undefined;\n },\n set: (key, value) => setStorage(key, value),\n remove: key => target.storage.remove(STORAGE_NAMESPACE, key),\n clear: () => target.storage.clear(STORAGE_NAMESPACE)\n },\n mock: (api, impl) => mock(api, impl as MockValue),\n route,\n fetch: (url, init = {}) => proxyFetch(url, { method: (init.method || 'GET').toUpperCase(), header: init.header, body: init.body })\n .then(res => new Response(NULL_BODY_STATUS.has(res.statusCode) ? null : res.response.body, {\n status: res.statusCode,\n headers: res.header\n }))\n };\n await config.run(wxa);\n }\n\n return summary;\n}\n\nexport function formatSetupSummary(summary: SetupSummary): string {\n const lines = ['[wxa-runner] setup 已应用'];\n if (summary.storage.length) lines.push(` storage ${summary.storage.join(', ')}`);\n if (summary.mock.length) lines.push(` mock ${summary.mock.join(', ')}`);\n if (summary.network.length) lines.push(` network ${summary.network.join(', ')}`);\n return lines.join('\\n');\n}\n\nconst NULL_BODY_STATUS = new Set([101, 204, 205, 304]);\n\nasync function resolveConfig(definition: unknown, env: SetupEnv): Promise<SetupConfig> {\n const config = typeof definition === 'function' ? await definition({ env }) : definition;\n if (!isPlainObject(config)) {\n throw new Error('setup 文件需要 export default 一个配置对象,或返回配置对象的函数(可用 defineSetup 包一层获得类型提示)');\n }\n\n const unknown = Object.keys(config).filter(key => !CONFIG_KEYS.includes(key));\n if (unknown.length) {\n throw new Error(`未知的配置项 ${unknown.join(', ')},可用的配置项:${CONFIG_KEYS.join(', ')}`);\n }\n if (config.storage !== undefined && !isPlainObject(config.storage)) throw new Error('storage 需要是 { key: 值 } 形式的对象');\n if (config.mock !== undefined && !isPlainObject(config.mock)) throw new Error('mock 需要是 { API 名: 返回值或函数 } 形式的对象');\n if (config.network !== undefined) {\n if (!isPlainObject(config.network)) throw new Error('network 需要是 { routes: { 规则: 响应 } } 形式的对象');\n const unknownNetwork = Object.keys(config.network).filter(key => !NETWORK_KEYS.includes(key));\n if (unknownNetwork.length) throw new Error(`network 下未知的配置项 ${unknownNetwork.join(', ')},可用的配置项:${NETWORK_KEYS.join(', ')}`);\n if (config.network.routes !== undefined && !isPlainObject(config.network.routes)) {\n throw new Error('network.routes 需要是 { 规则: 响应 } 形式的对象');\n }\n }\n if (config.run !== undefined && typeof config.run !== 'function') throw new Error('run 需要是函数');\n return config as SetupConfig;\n}\n\nfunction checkMock(api: string, impl: unknown) {\n if (TASK_APIS.has(api)) {\n throw new Error(`mock.${api}:wx.${api} 由基础库内部的任务实现,mock 无法覆盖;拦截 wx.request 请用 network.routes(请求拦截)`);\n }\n if (STORAGE_API.test(api)) {\n throw new Error(`mock.${api}:存储数据请用 storage 预置,不要覆盖存储 API`);\n }\n if (typeof impl !== 'function' && !isPlainObject(impl)) {\n throw new Error(`mock.${api}:需要是作为调用结果的对象,或按调用参数返回结果的函数`);\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, any> {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n","/**\n * window.__wxa_test_api__:给 E2E 测试(Playwright 等)使用的钩子\n */\n\nimport type { RouteHandler } from '../../setup';\nimport type { RecordedRequest } from './api/network';\nimport type { ApiHandler, ApiResult } from './api/registry';\nimport { compilePattern } from './api/routes';\nimport { decodeStorageValue } from './api/storage';\nimport type { FrameError, Host } from './Host';\nimport { cloneInto } from './realm';\nimport { TASK_APIS } from './setup';\n\nexport type { RecordedRequest };\n\nexport interface PageSnapshot {\n webviewId: number;\n /** 页面路径,如 pages/index/index,不带开头的 / */\n path: string;\n query: Record<string, string>;\n /** 渲染层 iframe 的 name,可用于 page.frame({ name }) */\n frameName: string;\n}\n\nexport interface WxaTestApi {\n /** 小程序启动完成(首页加载完、整页刷新后页面栈恢复完)后 resolve。setup 或启动前的准备出错时不会 resolve,模拟器显示错误 */\n ready: Promise<void>;\n /** 当前页,即页面栈顶;小程序启动前为 null */\n currentPage(): PageSnapshot | null;\n /** 整个页面栈,栈底在前 */\n pageStack(): PageSnapshot[];\n /**\n * 等到指定页面成为当前页,已经是当前页时立即返回\n * @param path 页面路径,如 pages/index/index,开头的 / 可有可无\n * @param timeout 毫秒,默认 10000\n * @throws 超时\n */\n waitForPage(path: string, timeout?: number): Promise<PageSnapshot>;\n /**\n * 页面的 data,是一份拷贝,修改它不影响页面\n * @param path 不传时读当前页;传页面路径时读页面栈里离栈顶最近的这个页面\n * @returns 页面不在页面栈里,或逻辑层还没创建它(刚跳转时)时为 null\n */\n pageData(path?: string): Record<string, unknown> | null;\n /**\n * 调用当前页的方法,如 callPageMethod('onPullDownRefresh')。方法返回 Promise 时等它完成\n * @param args 要能 JSON 序列化\n * @returns 方法的返回值\n * @throws 当前页还没创建、没有这个方法,或者方法抛错时\n */\n callPageMethod(name: string, ...args: unknown[]): Promise<unknown>;\n /**\n * 覆盖原生 API,同名的 setup mock 也被覆盖。整页刷新后失效\n * @param api 与 wx 上的名字相同,如 login、getLocation\n * @param impl 对象作为调用结果;函数按调用参数返回结果,可以返回 Promise,抛错即调用失败\n * @throws api 是 request、downloadFile 等由基础库任务实现的 API 时:mock 不会生效,wx.request 要用 route 拦截\n */\n mock(api: string, impl: ApiHandler | ApiResult): void;\n /** 撤销 mock,恢复内置实现;不传 api 时撤销全部,包括 setup 声明的 */\n unmock(api?: string): void;\n /**\n * 拦截 wx.request:命中的请求不发往网络,直接返回给定的响应。写法与 setup 的 network.routes 相同,后添加的规则优先。整页刷新后失效\n * @param pattern '[请求方法 ]地址',如 'POST https://api.example.com/login';* 匹配一段路径,** 匹配任意内容(可以不写域名)\n * @param handler 响应 { status?, header?, body?, delay? },或按请求返回响应的函数\n * @throws 规则写法不对时\n */\n route(pattern: string, handler: RouteHandler): void;\n /** 删除按这个写法添加的拦截规则;不传时删除全部,包括 setup 声明的 */\n unroute(pattern?: string): void;\n /**\n * 小程序发出的 wx.request,按发出顺序,被拦截的和经代理转发的都有。只保留最近 1000 个,整页刷新后清空\n * @param pattern 只返回匹配的请求,写法同 route\n * @throws pattern 写法不对时\n */\n requests(pattern?: string): RecordedRequest[];\n /** 清空已记录的请求,常用于只关心某个操作之后发出的请求 */\n clearRequests(): void;\n /**\n * 打开新页面,同 wx.navigateTo\n * @param url 从小程序根目录写起,如 /pages/detail/detail?id=1\n * @returns 调用结果;失败时不抛错,errMsg 以 navigateTo:fail 开头说明原因\n */\n navigateTo(url: string): Promise<ApiResult>;\n /**\n * 返回上一页或多级页面,同 wx.navigateBack\n * @param delta 返回的层数,默认 1\n * @returns 调用结果;失败时不抛错,errMsg 说明原因\n */\n navigateBack(delta?: number): Promise<ApiResult>;\n /**\n * 关闭当前页,打开新页面,同 wx.redirectTo\n * @returns 调用结果;失败时不抛错,errMsg 说明原因\n */\n redirectTo(url: string): Promise<ApiResult>;\n /**\n * 关闭所有页面,打开新页面,同 wx.reLaunch\n * @returns 调用结果;失败时不抛错,errMsg 说明原因\n */\n reLaunch(url: string): Promise<ApiResult>;\n /**\n * 切换到 tabBar 页面,同 wx.switchTab\n * @returns 调用结果;失败时不抛错,errMsg 说明原因\n */\n switchTab(url: string): Promise<ApiResult>;\n /** 读取小程序的 Storage,值保持写入时的类型;没有这个 key 时为 undefined */\n getStorage(key: string): unknown;\n /** 清空小程序的 Storage。基础库会缓存读过的值,小程序启动后再清空,已读过的 key 可能仍读到旧值 */\n clearStorage(): void;\n /**\n * 逻辑层、渲染层的运行时错误,以及业务代码调用过的未实现 wx API(api 为 API 名称,每个 API 记一次)。\n * 这些都不会让测试失败,需要自己检查\n */\n errors(): FrameError[];\n}\n\nexport function installTestApi(host: Host, ready: Promise<void>): WxaTestApi {\n const snapshot = (page: ReturnType<Host['currentPage']>): PageSnapshot | null =>\n page ? { webviewId: page.id, path: page.path, query: { ...page.query }, frameName: page.frame.name } : null;\n\n /** 逻辑层里的页面实例;同一页面打开多次时取离栈顶最近的 */\n const pageInstance = (path: string | undefined): any => {\n if (!path) return undefined;\n const pages: any[] = (host.serviceWindow() as any)?.getCurrentPages?.() || [];\n return [...pages].reverse().find(page => page.route === path);\n };\n\n const api: WxaTestApi = {\n ready,\n currentPage: () => snapshot(host.currentPage()),\n pageStack: () => host.pageStack().map(page => snapshot(page)!),\n waitForPage(path, timeout = 10000) {\n const target = path.replace(/^\\//, '');\n return new Promise((resolve, reject) => {\n const current = host.currentPage();\n if (current?.path === target) return resolve(snapshot(current)!);\n const timer = setTimeout(() => reject(new Error(`等待页面 ${target} 超时`)), timeout);\n host.onRoute(page => {\n if (page.path === target) {\n clearTimeout(timer);\n resolve(snapshot(page)!);\n }\n });\n });\n },\n pageData(path) {\n const instance = pageInstance(path === undefined ? host.currentPage()?.path : host.resolveUrl(path).path);\n if (!instance) return null;\n // __webviewId__ 是基础库加进 data 的内部字段\n const { __webviewId__: _webviewId, ...data } = JSON.parse(JSON.stringify(instance.data));\n return data;\n },\n async callPageMethod(name, ...args) {\n const current = host.currentPage();\n if (!current) throw new Error('小程序还没有启动');\n const instance = pageInstance(current.path);\n if (!instance) throw new Error(`页面 ${current.path} 的逻辑层还没有创建`);\n if (typeof instance[name] !== 'function') throw new Error(`页面 ${current.path} 没有方法 ${name}`);\n return instance[name](...cloneInto(host.serviceWindow()!, args));\n },\n mock(name, impl) {\n if (TASK_APIS.has(name)) {\n throw new Error(`wx.${name} 由基础库内部的任务实现,mock 不会生效;wx.request 请用 route 拦截`);\n }\n host.api.mock(name, impl);\n },\n unmock: name => host.api.unmock(name),\n route: (pattern, handler) => host.routes.add(pattern, handler),\n unroute: pattern => host.routes.remove(pattern),\n requests(pattern) {\n const matches = pattern === undefined ? () => true : compilePattern(pattern);\n return host.requests.list().filter(matches);\n },\n clearRequests: () => host.requests.clear(),\n navigateTo: url => host.enqueueRoute(() => host.navigateTo(url)),\n navigateBack: (delta = 1) => host.enqueueRoute(() => host.navigateBack(delta)),\n redirectTo: url => host.enqueueRoute(() => host.redirectTo(url)),\n reLaunch: url => host.enqueueRoute(() => host.reLaunch(url)),\n switchTab: url => host.enqueueRoute(() => host.switchTab(url)),\n getStorage(key) {\n const item = host.storage.get('s0', key);\n return item ? decodeStorageValue(item) : undefined;\n },\n clearStorage: () => host.storage.clear('s0'),\n errors: () => [...host.errors]\n };\n\n (window as any).__wxa_test_api__ = api;\n return api;\n}\n","/**\n * 宿主页面入口(打包为 /__wxa__/runtime/host.js)\n */\n\nimport type { AppInfo } from '../types';\nimport { Host, LaunchTarget } from './Host';\nimport { applyHotUpdate, HotUpdate } from './hmr';\nimport { PageStackRestore } from './pageStackRestore';\nimport { applySetup, formatSetupSummary } from './setup';\nimport { installTestApi, WxaTestApi } from './testApi';\nimport { PhoneShell } from './ui/PhoneShell';\n\nasync function main() {\n const root = document.getElementById('wxa-root')!;\n const info: AppInfo = await (await fetch('/__wxa__/app-info.json')).json();\n const restore = new PageStackRestore(info.appid);\n\n connectDevServer(restore);\n\n if (info.buildError) {\n new PhoneShell(root, info.device).showError(`编译失败\\n\\n${info.buildError}`);\n return;\n }\n\n const host = new Host(info, root);\n (window as any).__wxaHost = host;\n\n let markReady!: () => void;\n const ready = new Promise<void>(resolve => {\n markReady = resolve;\n });\n const testApi = installTestApi(host, ready);\n\n if (info.setup && !(await runSetup(host, info.setup))) return;\n if (!(await runBeforeLaunch(host, testApi))) return;\n await host.start(restore.launchTarget(info.pages, launchTarget(info)));\n await restore.reopen(host);\n markReady();\n}\n\n/**\n * 在逻辑层创建前执行 setup;失败时显示错误并返回 false——带着一半的预置状态启动,\n * 小程序的表现会让人误以为是业务代码的问题\n */\nasync function runSetup(host: Host, setup: NonNullable<AppInfo['setup']>): Promise<boolean> {\n try {\n if (setup.error) throw new Error(setup.error);\n // 地址是变量:esbuild 不会尝试在打包时解析它\n const url = '/__wxa__/setup.js';\n const module = await import(url);\n console.info(formatSetupSummary(await applySetup(module.default, host, setup.env)));\n return true;\n } catch (error) {\n console.error('[wxa-runner] setup 执行失败', error);\n host.shell.showError(`setup 执行失败\\n\\n${(error as Error).message}`);\n return false;\n }\n}\n\n/**\n * 执行测试工具在页面脚本之前定义的 window.__wxa_before_launch__。排在 setup 之后,\n * 这里声明的 mock 覆盖 setup 的同名 mock;失败时同 setup,显示错误、不启动小程序\n */\nasync function runBeforeLaunch(host: Host, testApi: WxaTestApi): Promise<boolean> {\n const hook = window.__wxa_before_launch__;\n if (typeof hook !== 'function') return true;\n try {\n await hook(testApi);\n return true;\n } catch (error) {\n console.error('[wxa-runner] __wxa_before_launch__ 执行失败', error);\n host.shell.showError(`启动前的测试准备(__wxa_before_launch__)执行失败\\n\\n${(error as Error).message}`);\n return false;\n }\n}\n\n/** ?path=pages/detail/detail&id=1 可以直接打开指定页面 */\nfunction launchTarget(info: AppInfo): LaunchTarget {\n const params = new URLSearchParams(location.search);\n const path = (params.get('path') || '').replace(/^\\//, '').replace(/\\.html$/, '');\n params.delete('path');\n if (path && info.pages.includes(path)) {\n return { path, query: Object.fromEntries(params) };\n }\n const entry = String(info.wxConfig.entryPagePath || info.pages[0]).replace(/\\.html$/, '');\n return { path: entry, query: {} };\n}\n\n/** 文件变化后热更新或整页刷新;编译出错时显示错误 */\nfunction connectDevServer(restore: PageStackRestore) {\n const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';\n const socket = new WebSocket(`${protocol}//${location.host}/__wxa__/ws`);\n // 连续保存时按顺序应用\n let hotChain = Promise.resolve();\n socket.onmessage = event => {\n const message = JSON.parse(event.data);\n if (message.type === 'reload') restore.reload(currentHost());\n if (message.type === 'hot') hotChain = hotChain.then(() => hotUpdate(message, restore));\n if (message.type === 'error') {\n const host = currentHost();\n if (host) host.shell.showError(`编译失败\\n\\n${message.message}`);\n else restore.reload(host);\n }\n };\n}\n\nfunction currentHost(): Host | undefined {\n return (window as any).__wxaHost;\n}\n\nasync function hotUpdate(update: HotUpdate, restore: PageStackRestore) {\n const host = currentHost();\n const files = [\n ...update.styles.map(id => id + '.wxss'),\n ...update.templates.map(id => id + '.wxml'),\n ...update.scripts.map(id => id + '.js')\n ].join(', ');\n try {\n if (!host) throw new Error('宿主尚未启动');\n await applyHotUpdate(host, update);\n console.info(`[wxa-runner] 热更新完成:${files}`);\n } catch (error) {\n console.warn(`[wxa-runner] ${files} 无法热更新,整页刷新:`, error);\n restore.reload(host);\n }\n}\n\nmain().catch(error => {\n console.error('[wxa-runner] 启动失败', error);\n document.body.textContent = `wxa-runner 启动失败:${error.message}`;\n});\n"],"mappings":"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","names":["reason","location","chooseFiles","hasUserActivation","source","taskSeq","labels","confirm","window","reason","runScript"]}
|