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