@jolibox/implement 1.1.13-beta.1 → 1.1.13-beta.3

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.
Files changed (52) hide show
  1. package/.rush/temp/package-deps_build.json +16 -33
  2. package/.rush/temp/shrinkwrap-deps.json +1 -1
  3. package/dist/index.js +3 -3
  4. package/dist/index.native.js +6 -6
  5. package/dist/native/api/keyboard.d.ts +1 -1
  6. package/implement.build.log +2 -2
  7. package/package.json +4 -3
  8. package/src/common/ads/index.ts +51 -33
  9. package/src/native/api/ads.ts +1 -1
  10. package/src/native/api/get-system-info.ts +1 -1
  11. package/src/native/api/keyboard.ts +1 -1
  12. package/src/native/api/lifecycle.ts +1 -1
  13. package/src/native/api/login.ts +1 -1
  14. package/src/native/api/navigate.ts +1 -1
  15. package/src/native/api/storage.ts +1 -1
  16. package/src/native/bootstrap/index.ts +13 -6
  17. package/src/native/network/create-fetch.ts +1 -1
  18. package/src/native/report/errors/index.ts +1 -1
  19. package/src/native/report/index.ts +1 -1
  20. package/src/native/report/task-tracker.ts +1 -1
  21. package/src/native/ui/retention.ts +1 -1
  22. package/dist/native/bootstrap/bridge.d.ts +0 -4
  23. package/dist/native/js-bridge/const.d.ts +0 -6
  24. package/dist/native/js-bridge/index.d.ts +0 -2
  25. package/dist/native/js-bridge/invoke.d.ts +0 -21
  26. package/dist/native/js-bridge/js-bridge.d.ts +0 -6
  27. package/dist/native/js-bridge/publish.d.ts +0 -1
  28. package/dist/native/js-bridge/report.d.ts +0 -63
  29. package/dist/native/js-bridge/subscribe.d.ts +0 -10
  30. package/dist/native/js-bridge/types.d.ts +0 -18
  31. package/dist/native/js-bridge/utils.d.ts +0 -17
  32. package/dist/native/js-core/index.d.ts +0 -3
  33. package/dist/native/js-core/jolibox-js-core.d.ts +0 -50
  34. package/dist/native/js-core/message-port.d.ts +0 -12
  35. package/dist/native/js-core/utils.d.ts +0 -7
  36. package/src/native/bootstrap/bridge.ts +0 -68
  37. package/src/native/js-bridge/const.ts +0 -13
  38. package/src/native/js-bridge/index.ts +0 -2
  39. package/src/native/js-bridge/invoke.ts +0 -208
  40. package/src/native/js-bridge/js-bridge.ts +0 -28
  41. package/src/native/js-bridge/publish.ts +0 -44
  42. package/src/native/js-bridge/report.ts +0 -311
  43. package/src/native/js-bridge/subscribe.ts +0 -74
  44. package/src/native/js-bridge/types.ts +0 -36
  45. package/src/native/js-bridge/utils.ts +0 -116
  46. package/src/native/js-core/index.ts +0 -4
  47. package/src/native/js-core/jolibox-js-core.ts +0 -192
  48. package/src/native/js-core/message-port.ts +0 -52
  49. package/src/native/js-core/utils.ts +0 -9
  50. package/src/native/types/global.d.ts +0 -27
  51. package/src/native/types/native-method-map.d.ts +0 -329
  52. package/src/native/types/native-method.d.ts +0 -30
@@ -1,208 +0,0 @@
1
- import { pack, unpack } from './utils';
2
- import { Deferred, isObject, isPromiseLike, InternalApplyNativeError, logger } from '@jolibox/common';
3
- import { formatErrorCode } from '../../common/report/errors';
4
- import { BACKGROUND_FORBIDDEN_METHODS, BUFFER_METHODS, SYNC_METHODS } from './const';
5
- import { createReportInvokeMetrics } from './report';
6
- import { InvokeHandler, On } from './types';
7
-
8
- import { AnyFunction } from '@jolibox/types';
9
-
10
- interface Invokes {
11
- /** 暴露给宿主, 触发调用的方法 */
12
- invokeHandler: InvokeHandler;
13
- /** 基础库内部, 调用宿主的方法, 返回 native 返回对象 */
14
- invokeNative: (method: string, args?: Record<string, unknown>, webviewId?: number) => any;
15
- /** 基础库内部, 调用宿主的方法, 会根据 errMsg throwError */
16
- applyNative: (method: string, args?: Record<string, unknown>, webviewId?: number) => any;
17
- }
18
-
19
- type Response = {
20
- errMsg: string;
21
- errNo?: number;
22
- __timing?: {
23
- receiveJSInvoke: number;
24
- invokeCallback: number;
25
- };
26
- } & Record<string, unknown>;
27
-
28
- // 后台期间积压的请求
29
- const asyncInvokes: {
30
- method: string;
31
- args?: Record<string, unknown>;
32
- resolve: AnyFunction;
33
- }[] = [];
34
-
35
- //TODO: support arrayBuffer
36
- const NOT_SUPPORT_ARRAY_BUFFER = false;
37
-
38
- export function createInvoke(jsCore: jsb.JSCore, onNative: On): Invokes {
39
- let resolveId = 0;
40
- let IS_FOREGROUND = true;
41
-
42
- const resolveMap = new Map<number, AnyFunction>();
43
- const reportInvokeMetrics = createReportInvokeMetrics(jsCore, onNative);
44
-
45
- onNative('onJoliboxEnterBackground', () => {
46
- IS_FOREGROUND = false;
47
- });
48
-
49
- onNative('onJoliboxEnterForeground', () => {
50
- IS_FOREGROUND = true;
51
- // 从后台进入前台后, 处理之前在后台挤压的任务
52
- asyncInvokes.forEach(async ({ method, args, resolve }) => {
53
- const res = await invokeNative(method, args);
54
- resolve(res);
55
- });
56
- // 清空积压
57
- asyncInvokes.length = 0;
58
- });
59
-
60
- const invokeHandler: InvokeHandler = (resolveId, data): void => {
61
- /**
62
- * Android resolveId 是 `string`
63
- * iOS 上待确认, IDE 上是 `number`
64
- */
65
- const resolve = resolveMap.get(Number(resolveId));
66
- if (!resolve) return;
67
- const response = unpack(data);
68
- resolve(response);
69
- resolveMap.delete(Number(resolveId));
70
- };
71
-
72
- const invokeNative = (
73
- method: string,
74
- args?: Record<string, unknown>
75
- ): Record<string, unknown> | Promise<Record<string, unknown>> => {
76
- const startTime = Date.now();
77
- const isForeground = `${IS_FOREGROUND}`;
78
-
79
- resolveId += 1;
80
-
81
- const deferred = new Deferred<Response>();
82
- resolveMap.set(resolveId, deferred.resolve);
83
-
84
- if (!IS_FOREGROUND && BACKGROUND_FORBIDDEN_METHODS.includes(method)) {
85
- // `FOREGROUND_FORBIDDEN_EVENTS` all async API
86
- return new Promise<Record<string, unknown>>((resolve) => {
87
- asyncInvokes.push({ method, args, resolve });
88
- });
89
- }
90
-
91
- const basicReportParam = {
92
- method,
93
- startTime,
94
- args,
95
- isForeground
96
- };
97
-
98
- const invokeReportParam = {
99
- ...basicReportParam,
100
- invokeType: 'js-bridge'
101
- } as const;
102
-
103
- const useArrayBuffer = !NOT_SUPPORT_ARRAY_BUFFER && BUFFER_METHODS.includes(method);
104
-
105
- const payload = pack(args, useArrayBuffer);
106
- const params = useArrayBuffer ? payload : JSON.stringify(payload);
107
-
108
- /** 调用结果 */
109
- let response;
110
-
111
- if (method.endsWith('Sync') || SYNC_METHODS.includes(method)) {
112
- response = jsCore.call?.(method, payload, resolveId);
113
- } else {
114
- if (typeof params === 'string') {
115
- response = jsCore.invoke(method, params, resolveId);
116
- } else {
117
- response = jsCore.call?.(method, params, resolveId);
118
- }
119
- }
120
-
121
- /**
122
- * 如果 invoke 返回了结果,则为同步调用
123
- * - iOS 返回 `undefined`
124
- * - Android 返回空字符串 `""`
125
- */
126
- if (response) {
127
- try {
128
- if (typeof response === 'string') {
129
- response = JSON.parse(response);
130
- }
131
- response = unpack(response);
132
- } catch (error) {
133
- logger.error(error);
134
- }
135
- resolveMap.delete(resolveId);
136
- if (response.errorCode) {
137
- response.errorCode = formatErrorCode(method, response.errorCode);
138
- }
139
- reportInvokeMetrics({ ...invokeReportParam, ...response });
140
-
141
- return response;
142
- }
143
-
144
- if (method.endsWith('Sync')) {
145
- resolveMap.delete(resolveId);
146
- }
147
-
148
- return deferred.promise.then((response) => {
149
- if (response.errorCode) {
150
- response.errorCode = formatErrorCode(method, response.errorCode as number | undefined);
151
- }
152
- reportInvokeMetrics({ ...invokeReportParam, ...response });
153
- return response;
154
- });
155
- };
156
-
157
- const applyNative = (method: string, arg?: Record<string, unknown>) => {
158
- const res = invokeNative(method, arg);
159
- if (isPromiseLike(res)) {
160
- return res.then((r) =>
161
- ifThrowError(
162
- method,
163
- r as {
164
- errMsg?: string;
165
- errNo?: number;
166
- errorType?: string;
167
- errorCode?: number;
168
- }
169
- )
170
- );
171
- }
172
- return ifThrowError(method, res);
173
- };
174
-
175
- return {
176
- invokeNative,
177
- applyNative,
178
- invokeHandler
179
- };
180
- }
181
-
182
- export function ifThrowError(
183
- method: string,
184
- res: {
185
- errMsg?: string;
186
- errNo?: number;
187
- errorType?: string;
188
- errorCode?: number;
189
- }
190
- ) {
191
- if (!isObject(res)) {
192
- logger.warn(`[Jolibox SDK]${method} no response value`);
193
- return;
194
- }
195
- const { errMsg, errNo, errorType, errorCode, ...data } = res;
196
-
197
- if (errMsg && errMsg !== `${method}:ok`) {
198
- throw new InternalApplyNativeError(errMsg, errNo, errorType, errorCode);
199
- }
200
-
201
- return data;
202
- }
203
-
204
- export class ApplyNativeError extends Error {
205
- constructor(message: string, readonly errNo?: number) {
206
- super(message);
207
- }
208
- }
@@ -1,28 +0,0 @@
1
- import { createInvoke } from './invoke';
2
- import { createSubscribe } from './subscribe';
3
- import { JSBridge } from './types';
4
- import { createPublish } from './publish';
5
-
6
- /**
7
- * build js-bridge
8
- * @param jsCore jsCore function inject by native
9
- */
10
- export function createBridge(jsCore: jsb.JSCore): JSBridge {
11
- const { subscribeHandler, onNative, offNative, subscribe, unsubscribe } = createSubscribe(jsCore);
12
-
13
- const { invokeNative, invokeHandler, applyNative } = createInvoke(jsCore, onNative);
14
- const publish = createPublish(jsCore);
15
-
16
- return {
17
- // 宿主调用
18
- invokeHandler,
19
- subscribeHandler,
20
- applyNative,
21
- invokeNative,
22
- onNative,
23
- offNative,
24
- publish,
25
- subscribe,
26
- unsubscribe
27
- };
28
- }
@@ -1,44 +0,0 @@
1
- import { CUSTOM_EVENT_PREFIX, BATCH_EVENT } from './const';
2
-
3
- type BatchEvent = [event: string, data: unknown];
4
- type BatchEvents = BatchEvent[];
5
-
6
- export function createPublish(jsCore: jsb.JSCore) {
7
- const eventsMap = new Map<number | undefined, BatchEvents>();
8
- let batchTask: Promise<void> | undefined;
9
- const publish = (event: string, data: Record<string, unknown>, webviewId?: number, force?: boolean) => {
10
- if (force) {
11
- const ids = webviewId ? [webviewId] : '*';
12
- jsCore.publish(`${CUSTOM_EVENT_PREFIX}${event}`, data, ids);
13
- return;
14
- }
15
-
16
- if (!batchTask) {
17
- batchTask = Promise.resolve().then(() => {
18
- eventsMap.forEach((data, webviewId) => {
19
- try {
20
- const ids = webviewId ? [webviewId] : '*';
21
- jsCore.publish(BATCH_EVENT, data, ids);
22
- } catch {
23
- // 避免一组 webview publish 的报错影响其他 webview publish
24
- }
25
- });
26
-
27
- // reset
28
- batchTask = undefined;
29
- eventsMap.clear();
30
- });
31
- }
32
-
33
- let events = eventsMap.get(webviewId);
34
-
35
- if (!events) {
36
- events = [];
37
- eventsMap.set(webviewId, events);
38
- }
39
-
40
- events.push([`${CUSTOM_EVENT_PREFIX}${event}`, data]);
41
- };
42
-
43
- return publish;
44
- }
@@ -1,311 +0,0 @@
1
- import { On } from './types';
2
- import { isObject, isString, InternalMetricReportError } from '@jolibox/common';
3
-
4
- type MetricReporter = (points: unknown) => unknown;
5
- interface MetricCache {
6
- [props: string]: MetricCache | (number | string)[];
7
- }
8
-
9
- interface PVMetricCache {
10
- [props: string]: PVMetricCache | number;
11
- }
12
-
13
- type MetricCacheType = MetricCache | PVMetricCache;
14
- type MetricType = 'pv' | 'default';
15
- type Prettier<T> = T extends Record<string, unknown> ? { [K in keyof T]: T[K] } : T;
16
- type MetricPoint<Tag extends string, Name extends string> = Prettier<
17
- {
18
- [k in Tag]: string;
19
- } & {
20
- [K in Name]: number | string;
21
- }
22
- >;
23
-
24
- interface PVPoint {
25
- [props: string]: string | JSON;
26
- }
27
-
28
- const getType = (type: unknown): MetricType => {
29
- if (type === 'pv') return type;
30
- return 'default';
31
- };
32
-
33
- interface MetricConfig<Tag extends string, Name extends string, Type extends string> {
34
- reporter: MetricReporter;
35
- interval?: number;
36
- eventName: string;
37
- tagNameOrder: Tag[];
38
- metricName: Name;
39
- type?: Type;
40
- }
41
-
42
- export class MetricsMonitor<Tag extends string, Name extends string, Type extends string> {
43
- reporter: MetricReporter;
44
- interval = 30;
45
- lastReportTime = 0;
46
- cache: MetricCacheType = {};
47
- eventName: string;
48
- tagNameOrder: Tag[];
49
- metricName: Name;
50
- type: MetricType;
51
-
52
- constructor(config: MetricConfig<Tag, Name, Type>) {
53
- const { reporter, interval = 30, eventName, tagNameOrder, metricName, type } = config;
54
- this.reporter = reporter;
55
- this.interval = interval;
56
- this.eventName = eventName;
57
- this.tagNameOrder = tagNameOrder;
58
- this.metricName = metricName;
59
- this.type = getType(type);
60
- }
61
-
62
- report(point: Type extends 'pv' ? PVPoint : MetricPoint<Tag, Name>) {
63
- if (this.type === 'pv') {
64
- this.addPVPoint(point);
65
- } else {
66
- this.addPoint(point as MetricPoint<Tag, Name>);
67
- }
68
-
69
- this.tryReport(false);
70
- }
71
-
72
- flush() {
73
- this.tryReport(true);
74
- }
75
-
76
- private tryReport(force: boolean) {
77
- if (!Object.keys(this.cache).length) {
78
- return;
79
- }
80
-
81
- if (force) {
82
- this.reporter(this.processPoints(this.cache));
83
- this.clearPoints();
84
- return;
85
- }
86
-
87
- this.lastReportTime = this.lastReportTime || Date.now();
88
-
89
- if (Date.now() - this.lastReportTime >= this.interval * 1000) {
90
- this.reporter(this.processPoints(this.cache));
91
- this.clearPoints();
92
- this.lastReportTime = Date.now();
93
- }
94
- }
95
-
96
- private addPoint(point: MetricPoint<Tag, Name>) {
97
- const safeSetVal = (
98
- target: MetricCache,
99
- props: Tag[],
100
- metricName: Name,
101
- point: MetricPoint<Tag, Name>
102
- ) => {
103
- const currentProp = props.shift();
104
- if (currentProp) {
105
- const currentVal = point[currentProp];
106
- if (!target[currentVal]) target[currentVal] = {};
107
-
108
- safeSetVal(target[currentVal] as MetricCache, props, metricName, point);
109
- } else {
110
- if (!target[metricName]) target[metricName] = [];
111
- (target[metricName] as unknown[]).push(point[metricName]);
112
- }
113
- };
114
-
115
- safeSetVal(this.cache as MetricCache, [...this.tagNameOrder], this.metricName, point);
116
- }
117
-
118
- private addPVPoint(point: PVPoint) {
119
- const safeSetVal = (
120
- target: Record<string, unknown>,
121
- props: Tag[],
122
- metricName: Name,
123
- relation: unknown
124
- ) => {
125
- const currentProp = props.shift();
126
-
127
- if (!currentProp && isObject(relation)) {
128
- throw new InternalMetricReportError(
129
- `report value failed to match tagNameOrder, ${JSON.stringify(originParams)}`
130
- );
131
- }
132
-
133
- if (currentProp) {
134
- const keys: string[] = [];
135
- if (isObject(relation)) {
136
- keys.push(...Object.keys(relation));
137
- } else if (isString(relation)) {
138
- if (props.length > 0) {
139
- throw new InternalMetricReportError(
140
- `report value failed to match tagNameOrder, ${JSON.stringify(originParams)}`
141
- );
142
- }
143
-
144
- keys.push(relation);
145
- } else {
146
- throw new InternalMetricReportError(
147
- `expected metric value to be a string, but got a(n) ${typeof relation}, ${JSON.stringify(
148
- originParams
149
- )}`
150
- );
151
- }
152
-
153
- keys.forEach((key) => {
154
- if (!target[key]) target[key] = {};
155
- const value = isObject(relation) ? relation[key] : relation;
156
- safeSetVal(target[key] as MetricCache, [...props], metricName, value);
157
- });
158
- } else {
159
- if (!target[metricName]) {
160
- target[metricName] = 1;
161
- } else {
162
- (target[metricName] as number)++;
163
- }
164
- }
165
- };
166
-
167
- const originParams = {
168
- point,
169
- metricName: this.metricName,
170
- tagNameOrder: this.tagNameOrder
171
- };
172
- safeSetVal(this.cache, [...this.tagNameOrder], this.metricName, point);
173
- }
174
-
175
- private processPoints(points: MetricCacheType) {
176
- return {
177
- eventName: this.eventName,
178
- tagNameOrder: this.tagNameOrder,
179
- metricName: this.metricName,
180
- metricAggregateType: this.type === 'pv' ? 'itoa' : 'arr',
181
- data: points
182
- };
183
- }
184
-
185
- private clearPoints() {
186
- this.cache = {};
187
- }
188
- }
189
-
190
- interface InvokeMetrics {
191
- errMsg: string;
192
- errNo?: number;
193
- __timing?: {
194
- receiveJSInvoke: number;
195
- invokeCallback: number;
196
- };
197
- method: string;
198
- startTime: number;
199
- args?: Record<string, unknown>;
200
- isForeground: string;
201
-
202
- [prop: string]: unknown;
203
- }
204
-
205
- let monitorHasInitialized = false;
206
- let invokeMonitor: MetricsMonitor<
207
- 'status' | 'method' | 'errNo' | 'errMsg' | 'isForeground',
208
- 'duration',
209
- 'default'
210
- >;
211
- let invokeJSToNativeMonitor: MetricsMonitor<'status' | 'method' | 'isForeground', 'duration', 'default'>;
212
- let invokeNativeToJSMonitor: MetricsMonitor<'status' | 'method' | 'isForeground', 'duration', 'default'>;
213
-
214
- export type reportInvokeFn = (invokeMetrics: InvokeMetrics) => void;
215
-
216
- export function createReportInvokeMetrics(jsCore: jsb.JSCore, onNative: On): reportInvokeFn {
217
- if (!monitorHasInitialized) {
218
- /** invoke 埋点 */
219
- invokeMonitor = new MetricsMonitor({
220
- eventName: 'jolibox_invoke',
221
- tagNameOrder: ['status', 'method', 'errNo', 'errMsg', 'isForeground'],
222
- metricName: 'duration',
223
- reporter(data) {
224
- jsCore.invoke('track', JSON.stringify({ event: 'reportMetrics', data }), -1);
225
- }
226
- });
227
-
228
- /** invoke js -> native */
229
- invokeJSToNativeMonitor = new MetricsMonitor({
230
- eventName: 'jolibox_invoke_js2native',
231
- tagNameOrder: ['status', 'method', 'isForeground'],
232
- metricName: 'duration',
233
- reporter(data) {
234
- jsCore.invoke('track', JSON.stringify({ event: 'reportMetrics', data }), -1);
235
- }
236
- });
237
-
238
- /** invoke native -> js */
239
- invokeNativeToJSMonitor = new MetricsMonitor({
240
- eventName: 'jolibox_invoke_native2js',
241
- tagNameOrder: ['status', 'method', 'isForeground'],
242
- metricName: 'duration',
243
- reporter(data) {
244
- jsCore.invoke('track', JSON.stringify({ event: 'reportMetrics', data }), -1);
245
- }
246
- });
247
-
248
- onNative('onJoliboxEnterBackground', () => {
249
- invokeMonitor.flush();
250
- invokeJSToNativeMonitor.flush();
251
- invokeNativeToJSMonitor.flush();
252
- });
253
-
254
- monitorHasInitialized = true;
255
- }
256
-
257
- function report(invokeMetrics: InvokeMetrics) {
258
- const {
259
- method,
260
- args,
261
- startTime,
262
- isForeground,
263
- errMsg = `${method}:fail no errMsg`,
264
- errNo = 0,
265
- __timing = {
266
- receiveJSInvoke: 0,
267
- invokeCallback: 0
268
- }
269
- } = invokeMetrics;
270
- const { receiveJSInvoke, invokeCallback } = __timing;
271
- const status = errMsg.match(/\S:(\S+)\s?/)?.[1] ?? 'fail';
272
-
273
- // report sync
274
- invokeMonitor.report({
275
- status,
276
- method: normalizeMethod(method, args),
277
- errNo: `${errNo}`,
278
- errMsg,
279
- isForeground,
280
- duration: Date.now() - startTime
281
- });
282
-
283
- if (startTime && receiveJSInvoke && invokeCallback) {
284
- invokeJSToNativeMonitor.report({
285
- status,
286
- method,
287
- isForeground,
288
- duration: Number((receiveJSInvoke - startTime).toFixed(3))
289
- });
290
- invokeNativeToJSMonitor.report({
291
- status,
292
- method,
293
- isForeground,
294
- duration: Number((Date.now() - invokeCallback).toFixed(3))
295
- });
296
- }
297
- }
298
-
299
- function normalizeMethod(method: string, args?: Record<string, unknown>) {
300
- // Reserve an interface;
301
- // an API might be provided later to directly expose client-side methods to users.
302
- if (method === 'callHostMethod' || method === 'callHostMethodSync') {
303
- if (args?.method) {
304
- return `${method}-${args.method}`;
305
- }
306
- }
307
- return method;
308
- }
309
-
310
- return report;
311
- }
@@ -1,74 +0,0 @@
1
- import { EventEmitter, logger } from '@jolibox/common';
2
- import { DataObj, unpack } from './utils';
3
- import { Off, On } from './types';
4
- import { AnyFunction } from '@jolibox/types';
5
- import { MetricsMonitor } from './report';
6
- import { BATCH_EVENT, CUSTOM_EVENT_PREFIX } from './const';
7
-
8
- export interface Subscribes {
9
- onNative: On;
10
- offNative: Off;
11
- subscribeHandler: AnyFunction;
12
- subscribe: On;
13
- unsubscribe: Off;
14
- }
15
-
16
- export function createSubscribe(jsCore: jsb.JSCore): Subscribes {
17
- const nativeEmitter = new EventEmitter();
18
- const customEmitter = new EventEmitter();
19
- const publishMonitor = new MetricsMonitor({
20
- eventName: 'jolibox_publish',
21
- tagNameOrder: ['type', 'event'],
22
- metricName: 'duration',
23
- reporter(data) {
24
- jsCore.invoke('track', JSON.stringify({ event: 'reportMetrics', data }), -1);
25
- }
26
- });
27
-
28
- nativeEmitter.on('onJoliboxEnterBackground', () => {
29
- publishMonitor.flush();
30
- });
31
-
32
- return {
33
- onNative: nativeEmitter.on.bind(nativeEmitter),
34
- offNative: nativeEmitter.off.bind(nativeEmitter),
35
- subscribe: customEmitter.on.bind(customEmitter),
36
- unsubscribe: customEmitter.off.bind(customEmitter),
37
- subscribeHandler(event, data, webviewId) {
38
- // ios: jsc 端基于系统方法,前端接受到的 data 总是 string 类型, webview 基于 evaluateJavascript,前端接受到的 data 总是 object 类型
39
- // android: 传入为 string 则接收到 string,传入为可序列化成功的 object,则接收到 object
40
- const unpackedData = unpack(data);
41
- let originalParams: undefined | DataObj;
42
- if (unpackedData.__extra) {
43
- originalParams = unpackedData.params;
44
- const { type, startTime } = unpackedData.__extra;
45
- publishMonitor.report({
46
- type,
47
- event,
48
- duration: Date.now() - startTime // ms
49
- });
50
- } else {
51
- originalParams = unpackedData;
52
- }
53
-
54
- if (event === BATCH_EVENT) {
55
- const list = originalParams as [event: string, data: unknown][];
56
- list.forEach((item) => {
57
- const [_event, _data] = item;
58
- try {
59
- customEmitter.emit(_event.slice(CUSTOM_EVENT_PREFIX.length), _data, webviewId);
60
- } catch {
61
- // 忽略
62
- }
63
- });
64
- return;
65
- }
66
-
67
- if (event.startsWith(CUSTOM_EVENT_PREFIX)) {
68
- customEmitter.emit(event.slice(CUSTOM_EVENT_PREFIX.length), originalParams, webviewId);
69
- return;
70
- }
71
- nativeEmitter.emit(event, originalParams, webviewId);
72
- }
73
- };
74
- }
@@ -1,36 +0,0 @@
1
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
- export type Listener = (...args: any[]) => any;
3
-
4
- export type On = <T extends string>(event: T, handler: Listener) => void;
5
-
6
- export type Off = <T extends string>(event: T, handler: Listener) => void;
7
-
8
- export type InvokeHandler = (callbackId: string | number, data: string | Record<string, unknown>) => void;
9
-
10
- export type Publish = (
11
- event: string,
12
- data: Record<string, unknown>,
13
- webviewId?: number,
14
- force?: boolean
15
- ) => void;
16
-
17
- export type SubscribeHandler = (
18
- event: string,
19
- data: string | Record<string, unknown>,
20
- webviewId?: number
21
- ) => void;
22
-
23
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
- export type AnyFunction = (...args: any[]) => any;
25
-
26
- export interface JSBridge {
27
- invokeHandler: InvokeHandler;
28
- subscribeHandler: SubscribeHandler;
29
- invokeNative: jsb.service.InvokeNative;
30
- applyNative: jsb.service.ApplyNative;
31
- onNative: jsb.service.OnNative;
32
- offNative: jsb.service.OffNative;
33
- publish: Publish;
34
- subscribe: On;
35
- unsubscribe: Off;
36
- }