@hd-front-end/jsbridge-sdk 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -225,9 +225,20 @@ class Bridge {
225
225
  const timeoutId = setTimeout(() => {
226
226
  reject(new Error(`${method} 调用超时`));
227
227
  }, 10000);
228
+ // 核心防御:防止 DataCloneError 和 Vue Proxy 序列化失败
229
+ // 剥离可能存在的不可序列化对象(如 success/fail 回调函数,或者 Vue 的 Proxy 对象)
230
+ let safeData = data;
231
+ if (data && typeof data === 'object') {
232
+ try {
233
+ safeData = JSON.parse(JSON.stringify(data));
234
+ }
235
+ catch (e) {
236
+ // 忽略异常,保留原数据
237
+ }
238
+ }
228
239
  // Android 调用
229
240
  if (this.platform === 'android' && this.bridge) {
230
- this.bridge.callHandler(method, data, (result) => {
241
+ this.bridge.callHandler(method, safeData, (result) => {
231
242
  clearTimeout(timeoutId);
232
243
  resolve(result);
233
244
  });
@@ -249,17 +260,6 @@ class Bridge {
249
260
  reject(err);
250
261
  }
251
262
  };
252
- // 核心防御:防止 DataCloneError
253
- // 剥离可能存在的不可序列化对象(如 success/fail 回调函数)
254
- let safeData = data;
255
- if (data && typeof data === 'object') {
256
- try {
257
- safeData = JSON.parse(JSON.stringify(data));
258
- }
259
- catch (e) {
260
- // 忽略异常,保留原数据
261
- }
262
- }
263
263
  handler.postMessage({
264
264
  handlerName: method,
265
265
  data: safeData,
@@ -1341,6 +1341,140 @@ async function logout() {
1341
1341
  }
1342
1342
  }
1343
1343
 
1344
+ // @ts-nocheck
1345
+ class JsBridge {
1346
+ static setup() {
1347
+ if (this.isInitialized) {
1348
+ return Promise.resolve();
1349
+ }
1350
+ return new Promise((resolve, reject) => {
1351
+ // Android 原生环境:按原有逻辑初始化 WKWebViewJavascriptBridge
1352
+ if (JsBridge.isSoaAndroid) {
1353
+ if (window.WKWebViewJavascriptBridge) {
1354
+ JsBridge.bridge = window.WKWebViewJavascriptBridge;
1355
+ JsBridge.isInitialized = true;
1356
+ resolve();
1357
+ return;
1358
+ }
1359
+ window.WKWVJBCallbacks = [
1360
+ (bridge) => {
1361
+ JsBridge.bridge = bridge;
1362
+ JsBridge.isInitialized = true;
1363
+ resolve();
1364
+ }
1365
+ ];
1366
+ if (!window.InjectJavascript) {
1367
+ reject(new Error('调用失败:InjectJavascript不存在,请检查Android端注入逻辑'));
1368
+ return;
1369
+ }
1370
+ window.InjectJavascript.init();
1371
+ return;
1372
+ }
1373
+ // iOS 原生环境:只要 JsBridge 通道存在即可认为初始化成功
1374
+ if (JsBridge.isIosApp()) {
1375
+ JsBridge.isInitialized = true;
1376
+ resolve();
1377
+ return;
1378
+ }
1379
+ // 其它环境:明确失败,方便 H5 判断
1380
+ reject(new Error('调用失败:当前不是 SoaAndroid 或 Soa iOS 环境'));
1381
+ });
1382
+ }
1383
+ static async registerHandler(method, handler) {
1384
+ if (!JsBridge.inAndroidApp() && !JsBridge.isIosApp())
1385
+ return;
1386
+ if (!JsBridge.isInitialized) {
1387
+ await JsBridge.setup();
1388
+ }
1389
+ if (JsBridge.inAndroidApp()) {
1390
+ JsBridge.bridge.registerHandler(method, handler);
1391
+ }
1392
+ else {
1393
+ // iOS 环境下,对接由 JSBridge.swift 注入的底层 bridge
1394
+ const w = window;
1395
+ if (w.WebViewJavascriptBridge) {
1396
+ w.WebViewJavascriptBridge.registerHandler(method, handler);
1397
+ }
1398
+ }
1399
+ }
1400
+ static _handleMessageFromNative(messageJSON) {
1401
+ const w = window;
1402
+ if (w.WebViewJavascriptBridge && w.WebViewJavascriptBridge._handleMessageFromNative) {
1403
+ w.WebViewJavascriptBridge._handleMessageFromNative(messageJSON);
1404
+ }
1405
+ }
1406
+ static async callHandler(method, data = null) {
1407
+ // Android
1408
+ if (JsBridge.inAndroidApp()) {
1409
+ if (!JsBridge.isInitialized) {
1410
+ await JsBridge.setup();
1411
+ }
1412
+ return new Promise((resolve) => {
1413
+ JsBridge.bridge.callHandler(method, data, (result) => {
1414
+ resolve(result);
1415
+ });
1416
+ });
1417
+ }
1418
+ // iOS
1419
+ if (JsBridge.isIosApp()) {
1420
+ return new Promise((resolve, reject) => {
1421
+ const w = window;
1422
+ const handler = w.webkit && w.webkit.messageHandlers && w.webkit.messageHandlers.JsBridge;
1423
+ if (!handler || typeof handler.postMessage !== 'function') {
1424
+ reject(new Error('调用失败:iOS JsBridge handler 不存在'));
1425
+ return;
1426
+ }
1427
+ const callbackId = 'cb_' + JsBridge.seq++;
1428
+ JsBridge.callbacks[callbackId] = { resolve, reject };
1429
+ handler.postMessage({
1430
+ handlerName: method,
1431
+ data,
1432
+ callbackId
1433
+ });
1434
+ });
1435
+ }
1436
+ return Promise.reject(new Error('调用失败:当前环境不支持 JsBridge.callHandler'));
1437
+ }
1438
+ static _invokeCallback(callbackId, result, error) {
1439
+ const entry = JsBridge.callbacks[callbackId];
1440
+ if (!entry)
1441
+ return;
1442
+ delete JsBridge.callbacks[callbackId];
1443
+ if (error) {
1444
+ entry.reject(error);
1445
+ }
1446
+ else {
1447
+ entry.resolve(result);
1448
+ }
1449
+ }
1450
+ static isReady() {
1451
+ return JsBridge.isInitialized;
1452
+ }
1453
+ static inAndroidApp() {
1454
+ return JsBridge.isSoaAndroid;
1455
+ }
1456
+ static isIosApp() {
1457
+ if (typeof window === 'undefined')
1458
+ return false;
1459
+ const w = window;
1460
+ return !!(w.webkit && w.webkit.messageHandlers && w.webkit.messageHandlers.JsBridge);
1461
+ }
1462
+ }
1463
+ JsBridge.bridge = null;
1464
+ JsBridge.isInitialized = false;
1465
+ // #ifndef H5
1466
+ JsBridge.isSoaAndroid = false;
1467
+ // #endif
1468
+ // #ifdef H5
1469
+ JsBridge.isSoaAndroid = Boolean(navigator.userAgent.match(/SoaAndroid/gi));
1470
+ // #endif
1471
+ JsBridge.callbacks = {};
1472
+ JsBridge.seq = 1;
1473
+ // 关键:把 JsBridge 挂到 window 上,给原生回调用
1474
+ if (typeof window !== 'undefined') {
1475
+ window.JsBridge = JsBridge;
1476
+ }
1477
+
1344
1478
  class PageLifeCycle {
1345
1479
  constructor(state, route) {
1346
1480
  this.state = state;
@@ -1371,54 +1505,54 @@ class JsBridgeHandlers {
1371
1505
  * @param from
1372
1506
  */
1373
1507
  static handleRouterAfterEach(to, from) {
1374
- return bridge.call('routerAfterEach', { to, from });
1508
+ return JsBridge.callHandler('routerAfterEach', { to, from });
1375
1509
  }
1376
1510
  /**
1377
1511
  * 获取app端信息
1378
1512
  */
1379
1513
  static handleGetAppInfo() {
1380
- return bridge.call('getAppInfo');
1514
+ return JsBridge.callHandler('getAppInfo');
1381
1515
  }
1382
1516
  /**
1383
1517
  * 页面生命周期通知原生
1384
1518
  * @param lifecycle
1385
1519
  */
1386
1520
  static handlePageLifeCycle(lifecycle) {
1387
- return bridge.call('uniPageLifeCycle', lifecycle);
1521
+ return JsBridge.callHandler('uniPageLifeCycle', lifecycle);
1388
1522
  }
1389
1523
  /**
1390
1524
  * 注册路由跳转调用
1391
1525
  * @param handler
1392
1526
  */
1393
1527
  static registerOnRoute(handler) {
1394
- return bridge.register('route', handler);
1528
+ return JsBridge.registerHandler('route', handler);
1395
1529
  }
1396
1530
  /**
1397
1531
  * 注册获取路由信息调用
1398
1532
  */
1399
1533
  static registerOnGetRouteInfo(handler) {
1400
- return bridge.register('getRouteInfo', handler);
1534
+ return JsBridge.registerHandler('getRouteInfo', handler);
1401
1535
  }
1402
1536
  /**
1403
1537
  * 注册刷新store数据
1404
1538
  * @param handler
1405
1539
  */
1406
1540
  static registerOnRefreshStore(handler) {
1407
- return bridge.register('refreshStore', handler);
1541
+ return JsBridge.registerHandler('refreshStore', handler);
1408
1542
  }
1409
1543
  /**
1410
1544
  * 注册PDA扫码回调
1411
1545
  * @param handler
1412
1546
  */
1413
1547
  static registerOnPdaScan(handler) {
1414
- return bridge.register('pdaScan', handler);
1548
+ return JsBridge.registerHandler('pdaScan', handler);
1415
1549
  }
1416
1550
  /**
1417
1551
  * 调用原生扫码
1418
1552
  * @param request
1419
1553
  */
1420
1554
  static handleScan(request = new UniScanRequest()) {
1421
- return bridge.call('scan', request).then((res) => {
1555
+ return JsBridge.callHandler('scan', request).then((res) => {
1422
1556
  const json = JSON.parse(res);
1423
1557
  const result = new UniScanResult();
1424
1558
  // eslint-disable-next-line @typescript-eslint/camelcase
@@ -1435,7 +1569,7 @@ class JsBridgeHandlers {
1435
1569
  * @param request
1436
1570
  */
1437
1571
  static handleChooseMedia(request) {
1438
- return bridge.call('chooseMedia', request).then((res) => {
1572
+ return JsBridge.callHandler('chooseMedia', request).then((res) => {
1439
1573
  if (res) {
1440
1574
  const result = JSON.parse(res);
1441
1575
  return result;
@@ -1449,7 +1583,7 @@ class JsBridgeHandlers {
1449
1583
  * @param request
1450
1584
  */
1451
1585
  static handleGetImageInfo(request) {
1452
- return bridge.call('getImageInfo', request).then((res) => {
1586
+ return JsBridge.callHandler('getImageInfo', request).then((res) => {
1453
1587
  const result = JSON.parse(res);
1454
1588
  return result;
1455
1589
  });
@@ -1459,7 +1593,7 @@ class JsBridgeHandlers {
1459
1593
  * @param request
1460
1594
  */
1461
1595
  static handleUploadFile(request) {
1462
- return bridge.call('uploadFile', request).then((res) => {
1596
+ return JsBridge.callHandler('uploadFile', request).then((res) => {
1463
1597
  const result = JSON.parse(res);
1464
1598
  return result;
1465
1599
  });
@@ -1469,28 +1603,28 @@ class JsBridgeHandlers {
1469
1603
  * @param request
1470
1604
  */
1471
1605
  static handleCloseWebView() {
1472
- return bridge.call('closeWebView');
1606
+ return JsBridge.callHandler('closeWebView');
1473
1607
  }
1474
1608
  /**
1475
1609
  * 打电话
1476
1610
  * @param request
1477
1611
  */
1478
1612
  static handleMakePhoneCall(request) {
1479
- return bridge.call('makePhoneCall', request);
1613
+ return JsBridge.callHandler('makePhoneCall', request);
1480
1614
  }
1481
1615
  /**
1482
1616
  * 动态设置标题
1483
1617
  * @param request
1484
1618
  */
1485
1619
  static handleSetNavigationBar(request) {
1486
- return bridge.call('setNavigationBar', request);
1620
+ return JsBridge.callHandler('setNavigationBar', request);
1487
1621
  }
1488
1622
  /**
1489
1623
  * 打日志
1490
1624
  * @param request
1491
1625
  */
1492
1626
  static handleLog(request) {
1493
- return bridge.call('log', request);
1627
+ return JsBridge.callHandler('log', request);
1494
1628
  }
1495
1629
  /**
1496
1630
  * 通知原生APP已加载完成
@@ -1504,28 +1638,28 @@ class JsBridgeHandlers {
1504
1638
  * @param data
1505
1639
  */
1506
1640
  static handleLogout() {
1507
- return bridge.call('logout');
1641
+ return JsBridge.callHandler('logout');
1508
1642
  }
1509
1643
  /**
1510
1644
  * 通知原生APP打开链接
1511
1645
  * @param data
1512
1646
  */
1513
1647
  static handleOpenSchemeUrl(request) {
1514
- return bridge.call('openSchemeUrl', request);
1648
+ return JsBridge.callHandler('openSchemeUrl', request);
1515
1649
  }
1516
1650
  /**
1517
1651
  * 图片路径转换成base64格式
1518
1652
  * @param path
1519
1653
  */
1520
1654
  static handlePathToBase64(request) {
1521
- return bridge.call('pathToBase64', request).then((res) => {
1655
+ return JsBridge.callHandler('pathToBase64', request).then((res) => {
1522
1656
  const result = JSON.parse(res);
1523
1657
  return result;
1524
1658
  });
1525
1659
  }
1526
1660
  static handleBluetoothPrintImage(request) {
1527
1661
  console.log(request);
1528
- return bridge.call('printImage', request).then((res) => {
1662
+ return JsBridge.callHandler('printImage', request).then((res) => {
1529
1663
  if (!res)
1530
1664
  return res;
1531
1665
  if (typeof res === 'string') {
@@ -1544,7 +1678,7 @@ class JsBridgeHandlers {
1544
1678
  * @param data
1545
1679
  */
1546
1680
  static handleBluetoothPrint(request) {
1547
- return bridge.call('bluetoothPrint', request).then((res) => {
1681
+ return JsBridge.callHandler('bluetoothPrint', request).then((res) => {
1548
1682
  if (!res)
1549
1683
  return res;
1550
1684
  if (typeof res === 'string') {
@@ -1563,7 +1697,7 @@ class JsBridgeHandlers {
1563
1697
  * @param request
1564
1698
  */
1565
1699
  static handleReloadModule(request) {
1566
- return bridge.call('reloadModule', request);
1700
+ return JsBridge.callHandler('reloadModule', request);
1567
1701
  }
1568
1702
  }
1569
1703