forked from x6eull/mobile-nx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextHelper.ts
84 lines (73 loc) · 2.66 KB
/
extHelper.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* 供小组件使用的运行时,APP本体不使用此文件。
*/
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { WidgetExtensionExposedAPIs } from '@/extension/WidgetExtensionRuntime'
import type { PackagedResponse } from '@/extension/ExtensionRuntime'
function decodeReturn(vToDecode: unknown, extNx: ExtNxType) {
if (typeof vToDecode !== 'object' || vToDecode === null) return vToDecode
if ('$borrowedId' in vToDecode) {
const borrowHandle = vToDecode['$borrowedId'] as number
const rawHandle = { __borrowedHandleId: borrowHandle, then: undefined }
const handle = new Proxy(rawHandle, {
get(target, prop) {
if (prop in target || typeof prop === 'symbol')
return target[prop as keyof typeof target]
return (...args: unknown[]) =>
extNx.applyOnHandle(borrowHandle, prop, args)
},
})
return handle
}
if ('$response' in vToDecode) {
const packaged = vToDecode['$response'] as PackagedResponse
const resp = new Response(packaged.body, {
headers: packaged.headers,
status: packaged.status,
})
Object.defineProperty(resp, 'url', { value: packaged.url })
return resp
}
return vToDecode
}
const helperVersion = '0.1.0'
const nxObj = { helperVersion, then: undefined } as const
export type ExtNxType = typeof nxObj & WidgetExtensionExposedAPIs
function postParent(data: any) {
return parent.postMessage(data, '*')
}
let traceId = 0
function newTraceId() {
return String(++traceId)
}
const traceMap = new Map<
string,
{ resolve(data: any): void; reject(reason: any): void }
>()
const proxyedNxObj = new Proxy(nxObj, {
get(target, prop) {
if (prop in target || typeof prop === 'symbol')
return target[prop as keyof typeof target]
//尝试调用API。如果没有这个API,parent会回传错误
return (...args: unknown[]) => {
return new Promise((resolve, reject) => {
const traceId = newTraceId()
traceMap.set(traceId, { resolve, reject })
postParent({ traceId, call: prop, args })
})
}
},
}) as ExtNxType
self.addEventListener('message', ({ data, source }) => {
if (!source || source !== parent) return
const { traceId, return: returnValue, error } = data
if (typeof traceId !== 'string') return
if (!traceMap.has(traceId)) throw new Error('traceId not found: ' + traceId)
const pair = traceMap.get(traceId)!
if (error !== undefined) pair.reject(error)
else pair.resolve(decodeReturn(returnValue, proxyedNxObj))
traceMap.delete(traceId)
})
Reflect.defineProperty(self, 'nx', { value: proxyedNxObj })
export default proxyedNxObj