react-native-update 10.52.0 → 10.52.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.
- package/NATIVE_CHECKUPDATE_DESIGN.md +14 -5
- package/NATIVE_CHECK_FOLLOWUPS.md +105 -2
- package/README-CN.md +3 -3
- package/README.md +3 -3
- package/harmony/pushy/src/main/cpp/PushyTurboModule.cpp +14 -0
- package/harmony/pushy.har +0 -0
- package/package.json +1 -1
- package/src/client.ts +11 -2
- package/src/permissions.ts +5 -2
- package/src/provider.tsx +2 -1
|
@@ -516,11 +516,20 @@ afterDownload)`:本地 silent 策略 或 响应标记 forceBoot 即激活。
|
|
|
516
516
|
raise NSException → uncaught → 进入本 handler;NSURLSession/信号量模式
|
|
517
517
|
照旧可用。下载器从 NSURLSessionDownloadTask 改为 data task 流式追加写
|
|
518
518
|
(downloadTask 的临时文件失败即丢,存不下 partial,是续传的硬前提)。
|
|
519
|
-
- **Harmony
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
519
|
+
- **Harmony:不需要 crash hold——RNOH 的进程模型天然免疫(2026-08-13 模
|
|
520
|
+
拟器实证)。** 未捕获的 JS 错误在 RNOH release 下只记 #RNOH_JS 错误日志,
|
|
521
|
+
**不杀进程**:Hermes 跑在 RNOH 自管线程,异常不会重抛到 ArkTS 主线程触发
|
|
522
|
+
errorManager。ets 编排器跑在 ArkTS 主线程事件循环上,JS 死后照常完成整
|
|
523
|
+
轮(实测:+1s JS 崩溃,+5s 轮次检查→下载→forceBoot 激活,重启进修复
|
|
524
|
+
版)。因此 Android/iOS 的"救援窗口排在崩溃点之后"问题在鸿蒙不存在,
|
|
525
|
+
§10 原机制即完整覆盖 crash-on-launch 砖,且没有预算压力(600s 下载窗口
|
|
526
|
+
完整可用)。续传 + 零延迟标记仍有价值(设备重启/系统杀进程等场景)。
|
|
527
|
+
原 errorManager/appRecovery 的 spike 论述作废留档:当时的前提("JS 崩溃
|
|
528
|
+
杀进程")被实证推翻。
|
|
529
|
+
注意两个鸿蒙特有的工程事实:PushyTurboModule.cpp 的 C++ 方法表是 RNOH
|
|
530
|
+
给 JS 的唯一桥,**新增 spec 方法必须同步注册**(10.50~10.52.0 漏注册了
|
|
531
|
+
syncNativeConfig 等四个方法,原生检测因此从未生效,10.52.1 修复);鸿蒙
|
|
532
|
+
模拟器是 QEMU 虚机,app 内 127.0.0.1 不通宿主,人工验证需 `hdc rport`。
|
|
524
533
|
|
|
525
534
|
### 11.6 验证
|
|
526
535
|
|
|
@@ -407,5 +407,108 @@ strict、77 金标向量 + ASan/UBSan、`.so` 符号与 16KB 对齐、iOS clang
|
|
|
407
407
|
版无 crash hold(errorManager 同步回调驱动不了 ArkTS 异步 IO),只有续
|
|
408
408
|
传+零延迟。
|
|
409
409
|
|
|
410
|
-
- [
|
|
411
|
-
|
|
410
|
+
- [x] 10.52.0 发版后按本节上方同一实验复测 crash-on-launch 砖(见下)
|
|
411
|
+
|
|
412
|
+
### 2026-08-12 实测:crash-on-launch 砖被救回(Android 真机 emu + 生产服务端)
|
|
413
|
+
|
|
414
|
+
10.52.0 发布到 npm,testHotUpdate 升级并出 release APK(rnu 10.52.0)。
|
|
415
|
+
复刻 crash-on-launch 砖:砖包活过一次启动并 markSuccess(first_time 保护
|
|
416
|
+
解除),之后每次启动读到标记即在 JS 线程抛错。fix 版本绑定到同一原生版本
|
|
417
|
+
1.87.1,砖包磁盘上的 fix 预下载被删除,逼救援在崩溃窗口内完整走
|
|
418
|
+
检查+下载+commit。
|
|
419
|
+
|
|
420
|
+
冷启动时序(同一进程 PID 11498):
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
22:59:52.365 JS 线程抛 BRICK(mqt_v_native),进程存活 122ms
|
|
424
|
+
22:59:52.367 crash rescue: holding process for up to 10000ms (uptime 122ms)
|
|
425
|
+
22:59:56.645 native check: downloaded -IxhPnHy(fix) and set for next launch
|
|
426
|
+
22:59:56.651 前任 handler 接管,进程被 SIG9 终止
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
崩溃到 commit 全程 **4.28s**,落在 10s(后台线程)预算内。下次冷启动直接
|
|
430
|
+
进 fix 版本(hot-fix-1052),不再崩溃;fix 立即把标记 disarm。
|
|
431
|
+
|
|
432
|
+
遥测闭环:fix 的 currentVersionInfo 带 `crashRescue: true`,markSuccess 后
|
|
433
|
+
JS 紧跟着上报一条 `crashRescue` 回执(logcat 实测 23:00:16.180 markSuccess
|
|
434
|
+
→ 23:00:16.181 crashRescue)。
|
|
435
|
+
|
|
436
|
+
对比 2026-08-12 上午同一台设备的旧结论:230ms 砖连续 4 次冷启动不收敛。
|
|
437
|
+
10.52.0 下**一次崩溃即救回**——崩溃本身触发 hold,进度不再随进程死亡丢弃。
|
|
438
|
+
鸿蒙真机复测待补(只有续传+零延迟无 hold)。
|
|
439
|
+
|
|
440
|
+
### 2026-08-12 iOS 模拟器实测:同一场景救回(Release-iphonesimulator + 本地服务端)
|
|
441
|
+
|
|
442
|
+
e2e 基建复用:本地 rnu 副本刷到 10.52.0 源码 → pod install → Release 模拟器
|
|
443
|
+
构建(e2e-ios 的常态形态,`#if !DEBUG` 门控激活);Detox 逮不住 JS 起不来的
|
|
444
|
+
app,绕开它直接 simctl + 文件系统/崩溃报告观察。实验脚手架已入库:
|
|
445
|
+
`e2e/entry.brick.ts` / `e2e/entry.fix.ts` / `scripts/ios-rescue-server.ts`
|
|
446
|
+
(端口 31337,链:base→brick(带 forceBoot 投放)→fix(**刻意不带 forceBoot**))。
|
|
447
|
+
|
|
448
|
+
砖状态与 Android 同构:brick 经 forceBoot 装上、首启健康 markSuccess
|
|
449
|
+
(isFirstTime 消费、isFirstLoadOK=true)、8s 后 arm 标记;磁盘上预下载的
|
|
450
|
+
fix 版本目录删除,逼救援窗口真下载。
|
|
451
|
+
|
|
452
|
+
armed 冷启动结果(procLaunch 23:24:44.233,崩溃报告 .ips 为证):
|
|
453
|
+
|
|
454
|
+
- JS fatal 重抛在 **com.meta.react.turbomodulemanager.queue**(后台线程 →
|
|
455
|
+
10s 预算档;此前对"JS 崩落在哪个线程"的分析在 bridgeless 下得到证实)
|
|
456
|
+
- 救援窗口内完成整轮:服务端记录到 checkUpdate(hash=brick)→ 下发 fix →
|
|
457
|
+
**fix.ppk 真实下载** → commit;本地服务端下全程 <0.9s(captureTime
|
|
458
|
+
23:24:45.156,远低于预算——4.4s 是生产网络的数字)
|
|
459
|
+
- **强制激活的独立证据**:fix 响应无 forceBoot、app 配置
|
|
460
|
+
checkStrategy:null/afterDownload:none——常规路径绝不会激活,而
|
|
461
|
+
currentVersion 已切到 fix 且 hashInfo 带 `crashRescue:true`,只能来自
|
|
462
|
+
crashRescueActive
|
|
463
|
+
- 链式礼仪:hold 结束后前任 handler 照常执行,SIGABRT 崩溃报告正常生成
|
|
464
|
+
(崩溃上报不丢)
|
|
465
|
+
- 下次启动进 fix、disarm 标记、markSuccess
|
|
466
|
+
|
|
467
|
+
**主线程 3.5s 预算档不做人工实测,理由记录**:iOS 上落主线程的 RCTFatal 只有
|
|
468
|
+
bundle 加载失败一族(RCTInstance 先 RCTExecuteOnMainQueue 再 RCTFatal),而
|
|
469
|
+
加载失败的包永远跑不到 markSuccess,一律被既有 first_time 回滚接住,不构成
|
|
470
|
+
真实砖形态;JS 运行时错误(砖的实际形态)实证落在后台线程。另:主线程档
|
|
471
|
+
3.5s 是按 Android ANR 定的,iOS watchdog 上限 ~20s,未来可放宽。
|
|
472
|
+
|
|
473
|
+
**iOS 覆盖边界补记**:若宿主 app 调用了 `RCTSetFatalHandler`,RCTFatal 走
|
|
474
|
+
handler 分支不再抛异常,crash-rescue 不会触发(Android 无对应抢占点)。
|
|
475
|
+
文档口径需含此项。
|
|
476
|
+
|
|
477
|
+
## 2026-08-13 鸿蒙模拟器实测:两个实证 + 一个 10.51 以来的功能性断裂
|
|
478
|
+
|
|
479
|
+
DevEco api20 模拟器(HarmonyOS 6.0 / arm64)+ harmony_use_pushy(RN 0.72 +
|
|
480
|
+
RNOH 0.72.96)+ 本地 e2e 服务端。探针脚手架入库:
|
|
481
|
+
`harmony_use_pushy/e2e/entry.crashprobe.ts`(+1s 未捕获 JS 错误)、
|
|
482
|
+
`entry.diag.ts`(TM 方法表诊断)。
|
|
483
|
+
|
|
484
|
+
**实证一(缺口 0 的分叉答案):RNOH 未捕获 JS 错误不杀进程。** +1s 抛错后
|
|
485
|
+
进程存活 40s+ 无恙,错误只落 #RNOH_JS/#RNOH_ARK 日志。Hermes 在 RNOH 自管
|
|
486
|
+
线程上,异常不重抛 ArkTS 主线程,errorManager 根本不参与。因此**鸿蒙不需要
|
|
487
|
+
crash hold**:ets 编排器在 JS 死后照常跑完整轮。此前 §11.5 的
|
|
488
|
+
errorManager/appRecovery 论述前提不成立,已改写。
|
|
489
|
+
|
|
490
|
+
**实证二(端到端救砖):** crashprobe 作基座(每次启动 JS +1s 崩),服务端
|
|
491
|
+
forceBoot 下发 v1:+5s 轮次照常检查→下载 v1.ppk→激活(currentVersion 写
|
|
492
|
+
入),重启直接运行 e2e-full-v1,砖消失。JS 崩溃对轮次零影响,无预算压力。
|
|
493
|
+
|
|
494
|
+
**功能性断裂(已修,severity 高):`PushyTurboModule.cpp` 的 C++ 方法表漏
|
|
495
|
+
注册 10.50+ 的全部四个新方法**(syncNativeConfig / getNativeCheckCache /
|
|
496
|
+
getBundleHash / resetToPackagedBundle)。RNOH 的 ArkTS TM 只有经 C++
|
|
497
|
+
methodMap 注册的方法才对 JS 可见,缺失 = JS 侧 undefined → feature-detect
|
|
498
|
+
判"老原生"静默跳过 → **原生冷启动检测在鸿蒙自 10.51.0 从未生效**
|
|
499
|
+
(nativeConfig 从未落盘,ets 编排器+本次的续传/零延迟全是死代码);
|
|
500
|
+
resetToPackagedBundle(10.50 Phase 1)在鸿蒙 JS 侧也一直不可用。诊断链:
|
|
501
|
+
健康启动 preferences 无 nativeConfig → entry.diag 打 typeof=undefined +
|
|
502
|
+
keys 只有 14 个老方法 → cpp 方法表对不上 ets 类。
|
|
503
|
+
|
|
504
|
+
**为什么 CI 没逮住**:harmony e2e 套件 testMatch 只含 `e2e/harmony/**`
|
|
505
|
+
(smoke + local-update),native-check.test.ts 从未在鸿蒙执行;而 JS 的
|
|
506
|
+
feature-detect 把缺失当"老原生"优雅跳过——这是[[no-graceful-degradation]]
|
|
507
|
+
教训的又一实例:兼容旧原生的降级路径把新原生的接线断裂藏了三个版本。
|
|
508
|
+
|
|
509
|
+
- [x] cpp 方法表补注册(含"新增 spec 方法必须同步注册"的醒目注释)
|
|
510
|
+
- [ ] harmony e2e 补 native-check 场景(driver 是 hdc+uitest 非 detox,
|
|
511
|
+
需移植;顺带把 `hdc rport` 写进用例基建——模拟器 127.0.0.1 不通宿主)
|
|
512
|
+
- [ ] 发版 10.52.1(鸿蒙 bridging 修复;Android/iOS 无变化)
|
|
513
|
+
- [ ] Logger.ts isDebug 硬编码 false,轮次全程无日志可观测,排障全靠副作用
|
|
514
|
+
(preferences/服务端流量);考虑 error 级关键节点或可配置开关
|
package/README-CN.md
CHANGED
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
|
|
33
33
|
### 原生冷启动检测
|
|
34
34
|
|
|
35
|
-
自 10.
|
|
35
|
+
自 10.52.1 起,每次冷启动后数秒会在后台线程执行一次**不依赖 app bundle** 的更新检查(下载、打补丁与状态切换全部在原生侧完成)。它的存在只为一件事:**当前热更版本坏到 JS 起不来时,仍有一条能把修复版拉下来的通路**——常规更新流程仍由应用内的 JS 负责,检查结果会被 JS 侧复用,不会重复请求。
|
|
36
36
|
|
|
37
37
|
几个需要知道的点:
|
|
38
38
|
|
|
39
39
|
- **不阻塞启动**:延迟数秒、跑在后台线程,成果在**下次启动**生效。
|
|
40
40
|
- **是否自动激活取决于你的配置**:`updateStrategy` 为 `silentAndNow` / `silentAndLater` 且未关闭自动检查(`checkStrategy` 不为 `null`)时,原生侧才会把下载好的版本设为下次启动生效;其余情况只下载,激活权仍在 JS。
|
|
41
41
|
- **救砖指令**:控制台可按版本标记「强制启动」,被标记的版本无视上述策略直接在下次启动生效——这是把已被坏版本卡死的设备捞回来的手段。设备本地的崩溃回滚保护仍然优先,已回滚过的版本不会被再装回去。
|
|
42
|
-
- **崩溃时刻救援**(
|
|
43
|
-
-
|
|
42
|
+
- **崩溃时刻救援**(Android 与 iOS):应用在启动阶段死于未捕获的 JS 错误时,SDK 会短暂扣住垂死的进程(数秒、有硬上限),把检查与下载做完——即使版本每次启动零点几秒就崩,也能被换掉。该窗口内下载到的修复版一律设为下次启动生效(JS 已经没有机会做决策了)。崩溃上报不受影响:SDK 以链式方式保存并在结束后调用原有的崩溃处理器。不覆盖:原生(非 JS)崩溃、ANR、OOM 击杀,以及 iOS 上安装了自定义 `RCTSetFatalHandler` 的应用(那时 React Native 不再抛出本机制拦截的异常)。
|
|
43
|
+
- **断点续传**:更新下载在进程死亡后保留进度、下次以 HTTP Range 续传,反复的短命启动也能单调累积进度;紧随中断轮次的下一次启动会跳过延迟立即续传。鸿蒙不需要崩溃时刻扣留:RNOH 下未捕获的 JS 错误不会杀死进程,JS 启动即崩时原生检测照常完成。
|
|
44
44
|
- **可以关闭**:`disableNativeCheck: true`。关闭后每次冷启动少一次后台请求,代价是**放弃上述自愈能力**——被坏热更卡死的设备将无法自动恢复。仅在这次请求本身构成问题时(流量/耗电预算、隐私清单申报、需用户同意后才可联网)才建议关闭。
|
|
45
45
|
|
|
46
46
|
### Diff 算法对比
|
package/README.md
CHANGED
|
@@ -30,15 +30,15 @@ See the docs:
|
|
|
30
30
|
|
|
31
31
|
## Native cold-start check
|
|
32
32
|
|
|
33
|
-
Since 10.
|
|
33
|
+
Since 10.52.1 every cold start runs one background update check a few seconds after launch that **does not depend on the app bundle** — the request, the download, the patch and the version switch all happen natively. It exists for exactly one reason: **when the running update is broken enough that JS never starts, something still has to be able to fetch the fix.** Normal updates remain the JS flow's job; the JS check reuses this result instead of issuing its own request.
|
|
34
34
|
|
|
35
35
|
What to know:
|
|
36
36
|
|
|
37
37
|
- **It never blocks startup**: it is delayed by a few seconds, runs off the main thread, and its result takes effect on the *next* launch.
|
|
38
38
|
- **Whether it activates depends on your configuration**: only with `updateStrategy` set to `silentAndNow` / `silentAndLater` *and* automatic checks left on (`checkStrategy` not `null`) will the native side mark a downloaded version for the next launch. Otherwise it downloads and leaves activation to JS.
|
|
39
39
|
- **Rescue directive**: the dashboard can mark a version "force boot", which activates on the next launch regardless of the strategies above — this is how a fleet stuck on a broken version is recovered. The device-local crash-rollback guard still wins: a version this device already rolled back from is never reinstalled.
|
|
40
|
-
- **Crash-moment rescue** (
|
|
41
|
-
- **Resumable downloads
|
|
40
|
+
- **Crash-moment rescue** (Android & iOS): when the app dies of an uncaught JS error during startup, the SDK briefly holds the dying process (a few seconds, bounded) to finish the check and download — so even a version that crashes a fraction of a second into every launch gets replaced. In that window the downloaded fix is always activated for the next launch, since JS is no longer around to decide. Crash reporters keep working: the SDK chains the previous crash handler and always hands the crash over afterwards. Not covered: native (non-JS) crashes, ANRs, OOM kills, and — on iOS — apps that install a custom `RCTSetFatalHandler` (React Native then no longer raises the exception this rescue intercepts).
|
|
41
|
+
- **Resumable downloads**: update downloads survive process death and resume from where they stopped (HTTP Range), so repeated short-lived launches still make monotonic progress; a launch that follows an interrupted round skips the startup delay and resumes immediately. HarmonyOS does not need the crash-moment hold: an uncaught JS error does not kill the process there, so the native check completes normally even when JS dies on launch.
|
|
42
42
|
- **It can be turned off**: `disableNativeCheck: true` removes one background request per cold start, at the cost of **giving up the recovery above** — a device bricked by a bad update can no longer heal itself. Choose it only when that request is itself the problem (traffic/battery budgets, privacy manifests, consent-gated networking).
|
|
43
43
|
|
|
44
44
|
## Diff Algorithm Comparison
|
|
@@ -60,6 +60,15 @@ PUSHY_ASYNC_METHOD(downloadPatchFromPpk)
|
|
|
60
60
|
PUSHY_ASYNC_METHOD(downloadPatchFromPackage)
|
|
61
61
|
PUSHY_ASYNC_METHOD(downloadFullUpdate)
|
|
62
62
|
PUSHY_ASYNC_METHOD(downloadAndInstallApk)
|
|
63
|
+
// 10.50+ additions. This table is the only bridge RNOH gives JS into the
|
|
64
|
+
// ArkTS module: a method missing here is `undefined` on the JS side, and the
|
|
65
|
+
// JS feature-detects then treat the whole capability as "old native" and
|
|
66
|
+
// silently skip it — which is how the native cold-start check shipped dark
|
|
67
|
+
// on Harmony. Every new spec method MUST be registered here.
|
|
68
|
+
PUSHY_ASYNC_METHOD(syncNativeConfig)
|
|
69
|
+
PUSHY_ASYNC_METHOD(getNativeCheckCache)
|
|
70
|
+
PUSHY_ASYNC_METHOD(getBundleHash)
|
|
71
|
+
PUSHY_ASYNC_METHOD(resetToPackagedBundle)
|
|
63
72
|
|
|
64
73
|
#undef PUSHY_SYNC_METHOD
|
|
65
74
|
#undef PUSHY_ASYNC_METHOD
|
|
@@ -93,4 +102,9 @@ PushyTurboModule::PushyTurboModule(
|
|
|
93
102
|
"downloadAndInstallApk", 1, HostFunction_downloadAndInstallApk);
|
|
94
103
|
registerMethod("addListener", 1, HostFunction_addListener);
|
|
95
104
|
registerMethod("removeListeners", 1, HostFunction_removeListeners);
|
|
105
|
+
registerMethod("syncNativeConfig", 1, HostFunction_syncNativeConfig);
|
|
106
|
+
registerMethod("getNativeCheckCache", 0, HostFunction_getNativeCheckCache);
|
|
107
|
+
registerMethod("getBundleHash", 0, HostFunction_getBundleHash);
|
|
108
|
+
registerMethod(
|
|
109
|
+
"resetToPackagedBundle", 0, HostFunction_resetToPackagedBundle);
|
|
96
110
|
}
|
package/harmony/pushy.har
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -76,6 +76,10 @@ const SERVER_PRESETS = {
|
|
|
76
76
|
main: [
|
|
77
77
|
'https://update.react-native.cn/api',
|
|
78
78
|
'https://update.reactnative.cn/api',
|
|
79
|
+
'https://1.rnupdate.online/api',
|
|
80
|
+
'https://2.rnupdate.online/api',
|
|
81
|
+
'https://3.rnupdate.online/api',
|
|
82
|
+
'https://4.rnupdate.online/api',
|
|
79
83
|
],
|
|
80
84
|
queryUrls: [
|
|
81
85
|
'https://gitee.com/sunnylqm/react-native-pushy/raw/master/endpoints.json',
|
|
@@ -1103,7 +1107,11 @@ export class Pushy {
|
|
|
1103
1107
|
callback(payload);
|
|
1104
1108
|
});
|
|
1105
1109
|
};
|
|
1106
|
-
|
|
1110
|
+
// RN >= 0.87 types native event listeners as `(...args: readonly Object[])`,
|
|
1111
|
+
// which a `(data: ProgressData) => void` callback is not assignable to. Take
|
|
1112
|
+
// the raw event and narrow it here so this compiles on every RN version.
|
|
1113
|
+
const onNativeProgress = (event: unknown) => {
|
|
1114
|
+
const progressData = event as ProgressData;
|
|
1107
1115
|
if (progressData.hash === hash) {
|
|
1108
1116
|
dispatchProgress(progressData);
|
|
1109
1117
|
}
|
|
@@ -1325,7 +1333,8 @@ export class Pushy {
|
|
|
1325
1333
|
sharedState.progressHandlers[progressKey] =
|
|
1326
1334
|
pushyNativeEventEmitter.addListener(
|
|
1327
1335
|
'RCTPushyDownloadProgress',
|
|
1328
|
-
(
|
|
1336
|
+
(event: unknown) => {
|
|
1337
|
+
const progressData = event as ProgressData;
|
|
1329
1338
|
if (progressData.hash === progressKey) {
|
|
1330
1339
|
onDownloadProgress(progressData);
|
|
1331
1340
|
}
|
package/src/permissions.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
// RN >= 0.87 (generated types) no longer exports the `PermissionsAndroidStatic`
|
|
2
|
+
// interface, so derive the shape from the exported value instead — that spelling
|
|
3
|
+
// works on every RN version we support.
|
|
4
|
+
import type { PermissionsAndroid as RNPermissionsAndroid } from 'react-native';
|
|
2
5
|
import { emptyModule } from './utils';
|
|
3
6
|
|
|
4
7
|
export const PermissionsAndroid =
|
|
5
|
-
emptyModule as unknown as
|
|
8
|
+
emptyModule as unknown as typeof RNPermissionsAndroid;
|
package/src/provider.tsx
CHANGED
|
@@ -456,7 +456,8 @@ export const UpdateProvider = ({
|
|
|
456
456
|
if (!assertWeb()) {
|
|
457
457
|
return;
|
|
458
458
|
}
|
|
459
|
-
|
|
459
|
+
// RN >= 0.87 widens getInitialURL() to `string | null | undefined`.
|
|
460
|
+
const parseLinking = (url?: string | null) => {
|
|
460
461
|
if (!url) {
|
|
461
462
|
return;
|
|
462
463
|
}
|