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