react-native-update 10.47.0 → 10.48.0

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 (59) hide show
  1. package/android/jni/Android.mk +2 -0
  2. package/android/jni/hpatch.c +57 -2
  3. package/android/lib/arm64-v8a/librnupdate.so +0 -0
  4. package/android/lib/armeabi-v7a/librnupdate.so +0 -0
  5. package/android/lib/x86/librnupdate.so +0 -0
  6. package/android/lib/x86_64/librnupdate.so +0 -0
  7. package/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java +19 -4
  8. package/android/src/main/java/cn/reactnative/modules/update/DownloadTaskParams.java +2 -0
  9. package/android/src/main/java/cn/reactnative/modules/update/ErrorCodes.java +1 -0
  10. package/android/src/main/java/cn/reactnative/modules/update/NativeUpdateCore.java +12 -0
  11. package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +30 -0
  12. package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleImpl.java +13 -0
  13. package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleSupport.java +1 -0
  14. package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +5 -0
  15. package/android/src/oldarch/cn/reactnative/modules/update/UpdateModule.java +5 -0
  16. package/cpp/patch_core/error_codes.h +3 -0
  17. package/cpp/patch_core/hbc_transform.cpp +143 -0
  18. package/cpp/patch_core/hbc_transform.h +53 -0
  19. package/cpp/patch_core/hbc_transform_wire.cpp +321 -0
  20. package/cpp/patch_core/hbc_transform_wire.h +52 -0
  21. package/cpp/patch_core/patch_core.cpp +126 -4
  22. package/cpp/patch_core/patch_core.h +5 -0
  23. package/cpp/patch_core/patch_core_android.cpp +3 -1
  24. package/cpp/patch_core/tests/fixtures/rawstored.lzma2label.patch.bin +0 -0
  25. package/cpp/patch_core/tests/fixtures/rawstored.new.bin +0 -0
  26. package/cpp/patch_core/tests/fixtures/rawstored.old.bin +0 -0
  27. package/cpp/patch_core/tests/fixtures/v96.hbc +0 -0
  28. package/cpp/patch_core/tests/fixtures/v96.meta.json +1 -0
  29. package/cpp/patch_core/tests/fixtures/v96.streampatch.bin +0 -0
  30. package/cpp/patch_core/tests/fixtures/v96.t.hbc +0 -0
  31. package/cpp/patch_core/tests/fixtures/v96.tpatch.bin +0 -0
  32. package/cpp/patch_core/tests/fixtures/v96.tstreampatch.bin +0 -0
  33. package/cpp/patch_core/tests/fixtures/v96b.hbc +0 -0
  34. package/cpp/patch_core/tests/fixtures/v98.hbc +0 -0
  35. package/cpp/patch_core/tests/fixtures/v98.t.hbc +0 -0
  36. package/cpp/patch_core/tests/fixtures/v98b.hbc +0 -0
  37. package/cpp/patch_core/tests/fixtures/v98b.t.hbc +0 -0
  38. package/cpp/patch_core/tests/hbc_transform_test.cpp +229 -0
  39. package/cpp/patch_core/tests/patch_core_test.cpp +150 -1
  40. package/cpp/patch_core/update_core_android.cpp +10 -0
  41. package/harmony/pushy/src/main/cpp/CMakeLists.txt +2 -0
  42. package/harmony/pushy/src/main/cpp/pushy.cpp +18 -1
  43. package/harmony/pushy/src/main/ets/DownloadTask.ts +21 -0
  44. package/harmony/pushy/src/main/ets/NativePatchCore.ts +4 -0
  45. package/harmony/pushy/src/main/ets/PushyTurboModule.ts +12 -0
  46. package/harmony/pushy/src/main/ets/UpdateContext.ts +46 -0
  47. package/harmony/pushy.har +0 -0
  48. package/ios/RCTPushy/RCTPushy.mm +64 -0
  49. package/package.json +1 -1
  50. package/react-native-update.podspec +2 -0
  51. package/src/NativePushy.ts +1 -0
  52. package/src/client.ts +46 -0
  53. package/src/context.ts +4 -0
  54. package/src/core.ts +4 -0
  55. package/src/error.ts +1 -0
  56. package/src/locales/en.ts +2 -0
  57. package/src/locales/zh.ts +2 -0
  58. package/src/provider.tsx +9 -0
  59. package/src/type.ts +2 -0
@@ -2,6 +2,7 @@
2
2
  #import "RCTPushyDownloader.h"
3
3
  #import "ZipArchive.h"
4
4
  #include "../../cpp/patch_core/archive_patch_core.h"
5
+ #include "../../cpp/patch_core/hbc_transform_wire.h"
5
6
  #include "../../cpp/patch_core/error_codes.h"
6
7
  #include "../../cpp/patch_core/patch_core.h"
7
8
  #include "../../cpp/patch_core/state_core.h"
@@ -347,6 +348,9 @@ RCT_EXPORT_MODULE(RCTPushy);
347
348
  ret[@"rolledBackVersion"] = [defaults objectForKey:keyRolledBackMarked];
348
349
  ret[@"isFirstTime"] = [defaults objectForKey:keyFirstLoadMarked];
349
350
  ret[@"uuid"] = [defaults objectForKey:keyUuid];
351
+ // 原生 patch 内核可消费的 diff 轨道版本(2 = hdiffv2 轨道),
352
+ // JS 随 checkUpdate 以 diffV 上报,服务端按能力门控下发
353
+ ret[@"supportedDiffVersion"] = @(pushy::hbc::kSupportedDiffVersion);
350
354
  NSDictionary *pushyInfo = [defaults dictionaryForKey:keyPushyInfo];
351
355
  NSString *currentVersion = [pushyInfo objectForKey:paramCurrentVersion];
352
356
  ret[@"currentVersion"] = currentVersion;
@@ -514,6 +518,51 @@ RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
514
518
  #endif
515
519
  }
516
520
 
521
+ RCT_EXPORT_METHOD(resetToPackagedBundle:(RCTPromiseResolveBlock)resolve
522
+ rejecter:(RCTPromiseRejectBlock)reject)
523
+ {
524
+ // Reset to the bundle packaged in the binary: wipe the whole update state
525
+ // (so the next launch resolves to the built-in bundle) and delete every
526
+ // downloaded version. Only the client uuid survives — it identifies the
527
+ // install for gray release bucketing and must not change on reset.
528
+ PushyWithStateLock(^{
529
+ NSUserDefaults *defaults = PushyDefaults();
530
+
531
+ // A default-constructed State is exactly the reset state (no current /
532
+ // last version, first_time=false, first_time_ok=true); keep the binary
533
+ // identity so the next launch does not re-trigger the package-updated
534
+ // sync path.
535
+ pushy::state::State state;
536
+ state.package_version = PushyToStdString([RCTPushy packageVersion]);
537
+ state.build_time = PushyToStdString([RCTPushy buildTime]);
538
+ PushyApplyStateToDefaults(defaults, state);
539
+
540
+ for (NSString *key in [defaults dictionaryRepresentation].allKeys) {
541
+ if ([key hasPrefix:keyHashInfo]) {
542
+ [defaults removeObjectForKey:key];
543
+ }
544
+ }
545
+ [defaults removeObjectForKey:keyFirstLoadMarked];
546
+ [defaults removeObjectForKey:KeyPackageUpdatedMarked];
547
+ ignoreRollback = false;
548
+ });
549
+
550
+ dispatch_async(_fileQueue, ^{
551
+ // maxAgeDays=0 and no versions to keep: remove every downloaded entry.
552
+ pushy::patch::Status status = pushy::patch::CleanupOldEntries(
553
+ PushyToStdString([RCTPushy downloadDir]),
554
+ "",
555
+ "",
556
+ 0
557
+ );
558
+ if (!status.ok) {
559
+ RCTLogWarn(@"Pushy reset cleanup error: %s", status.message.c_str());
560
+ }
561
+ });
562
+
563
+ resolve(@true);
564
+ }
565
+
517
566
 
518
567
 
519
568
  #pragma mark - private
@@ -742,6 +791,21 @@ RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
742
791
  return;
743
792
  }
744
793
 
794
+ // __diff.json 的 hbcTransform 元数据(HBC 变换域 patch,hdiffv2 轨道):
795
+ // 存在时透传给 patch 内核执行 T(origin) → hpatch → T⁻¹;缺失走现状路径。
796
+ NSDictionary *hbcTransform = json[@"hbcTransform"];
797
+ if ([hbcTransform isKindOfClass:[NSDictionary class]]) {
798
+ NSDictionary *meta = hbcTransform[BUNDLE_PATCH_NAME];
799
+ if ([meta isKindOfClass:[NSDictionary class]]) {
800
+ NSError *metaError = nil;
801
+ NSData *metaData = [NSJSONSerialization dataWithJSONObject:meta options:0 error:&metaError];
802
+ if (metaData != nil && metaError == nil) {
803
+ NSString *metaString = [[NSString alloc] initWithData:metaData encoding:NSUTF8StringEncoding];
804
+ options.bundle_hbc_transform_meta = PushyToStdString(metaString);
805
+ }
806
+ }
807
+ }
808
+
745
809
  pushy::patch::Status status = pushy::patch::ApplyPatchFromFileSource(options);
746
810
  if (!status.ok) {
747
811
  callback(PushyNSErrorFromStatus(status));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-update",
3
- "version": "10.47.0",
3
+ "version": "10.48.0",
4
4
  "description": "react-native hot update",
5
5
  "main": "src/index",
6
6
  "types": "src/index.ts",
@@ -111,6 +111,8 @@ Pod::Spec.new do |s|
111
111
  s.subspec 'RCTPushy' do |ss|
112
112
  ss.source_files = ['ios/RCTPushy/*.{h,m,mm}',
113
113
  'cpp/patch_core/archive_patch_core.{h,cpp}',
114
+ 'cpp/patch_core/hbc_transform.{h,cpp}',
115
+ 'cpp/patch_core/hbc_transform_wire.{h,cpp}',
114
116
  'cpp/patch_core/patch_core.{h,cpp}',
115
117
  'cpp/patch_core/state_core.{h,cpp}',
116
118
  'android/jni/hpatch.{h,c}',
@@ -19,6 +19,7 @@ export interface Spec extends TurboModule {
19
19
  restartApp(): Promise<void>;
20
20
  setNeedUpdate(options: { hash: string }): Promise<void>;
21
21
  markSuccess(): Promise<void>;
22
+ resetToPackagedBundle(): Promise<void>;
22
23
  downloadPatchFromPpk(options: {
23
24
  updateUrl: string;
24
25
  hash: string;
package/src/client.ts CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  cInfo,
10
10
  currentVersion,
11
11
  currentVersionInfo,
12
+ supportedDiffVersion,
12
13
  isFirstTime,
13
14
  isRolledBack,
14
15
  packageVersion,
@@ -572,6 +573,8 @@ export class Pushy {
572
573
  hash: currentVersion,
573
574
  buildTime,
574
575
  cInfo,
576
+ // 可消费的 diff 轨道版本(2 = hdiffv2 轨道),服务端据此门控下发
577
+ ...(supportedDiffVersion ? { diffV: supportedDiffVersion } : {}),
575
578
  ...extra,
576
579
  };
577
580
  if (__DEV__) {
@@ -948,6 +951,49 @@ export class Pushy {
948
951
  }
949
952
  return PushyModule.restartApp();
950
953
  };
954
+ /**
955
+ * Reset to the bundle packaged in the binary: wipes every downloaded update
956
+ * and the whole update state on the native side, so the app loads the
957
+ * built-in bundle on the next launch (or immediately with
958
+ * `{ restart: true }`). The client uuid is preserved.
959
+ *
960
+ * Returns whether the reset actually happened. Like the other update-flow
961
+ * APIs it never throws by default — failures land in lastError/onError with
962
+ * code RESET_FAILED — but the boolean must not be ignored: a false means the
963
+ * app is still running the hot-updated bundle. Set `throwError` to throw.
964
+ */
965
+ resetToPackagedBundle = async (options?: {
966
+ restart?: boolean;
967
+ }): Promise<boolean> => {
968
+ if (typeof PushyModule.resetToPackagedBundle !== 'function') {
969
+ // The JS layer can arrive via hot update onto an older binary whose
970
+ // native module predates this method.
971
+ const err = new UpdateError(
972
+ this.t('error_reset_not_supported'),
973
+ 'RESET_FAILED',
974
+ );
975
+ this.emitError(err, 'errorReset');
976
+ this.throwIfEnabled(err);
977
+ return false;
978
+ }
979
+ try {
980
+ await PushyModule.resetToPackagedBundle();
981
+ } catch (e) {
982
+ const err = toUpdateError(e, 'RESET_FAILED');
983
+ this.emitError(err, 'errorReset');
984
+ this.throwIfEnabled(err);
985
+ return false;
986
+ }
987
+ // The downloaded versions are gone; drop JS bookkeeping referring to them
988
+ // so a stale downloadedHash cannot be switched to.
989
+ sharedState.downloadedHash = undefined;
990
+ sharedState.marked = false;
991
+ this.report({ type: 'reset' });
992
+ if (options?.restart) {
993
+ await this.restartApp();
994
+ }
995
+ return true;
996
+ };
951
997
  }
952
998
 
953
999
  // for international users
package/src/context.ts CHANGED
@@ -15,6 +15,7 @@ export const defaultContext = {
15
15
  downloadUpdate: asyncNoop,
16
16
  downloadAndInstallApk: asyncNoop,
17
17
  restartApp: asyncNoop,
18
+ resetToPackagedBundle: asyncNoop,
18
19
  getCurrentVersionInfo: () => Promise.resolve({}),
19
20
  parseTestQrCode: () => false,
20
21
  currentHash: '',
@@ -43,6 +44,9 @@ export const UpdateContext = createContext<{
43
44
  } | null;
44
45
  parseTestQrCode: (code: string) => boolean;
45
46
  restartApp: () => Promise<void>;
47
+ resetToPackagedBundle: (options?: {
48
+ restart?: boolean;
49
+ }) => Promise<boolean | void>;
46
50
  currentHash: string;
47
51
  packageVersion: string;
48
52
  client?: Pushy | Cresc;
package/src/core.ts CHANGED
@@ -65,6 +65,10 @@ export const rolledBackVersion: string = PushyConstants.rolledBackVersion;
65
65
  export const isRolledBack: boolean = !!rolledBackVersion;
66
66
 
67
67
  export const buildTime: string = PushyConstants.buildTime;
68
+ // 原生 patch 内核可消费的 diff 轨道版本(2 = hdiffv2 轨道:HBC 变换 +
69
+ // 流式容器);旧原生无此常量时为 0(不上报,服务端只发 baseline)
70
+ export const supportedDiffVersion: number =
71
+ PushyConstants.supportedDiffVersion || 0;
68
72
  let uuid = PushyConstants.uuid;
69
73
 
70
74
  async function getLocalHashInfo(hash: string) {
package/src/error.ts CHANGED
@@ -26,6 +26,7 @@ export type UpdateErrorCode =
26
26
  | 'PATCH_FAILED'
27
27
  | 'FILE_OPERATION_FAILED'
28
28
  | 'RESTART_FAILED'
29
+ | 'RESET_FAILED'
29
30
  | 'INVALID_HASH_INFO'
30
31
  | 'UNSUPPORTED_PLATFORM';
31
32
 
package/src/locales/en.ts CHANGED
@@ -61,6 +61,8 @@ export default {
61
61
  error_storage_permission_rejected:
62
62
  'Storage permission denied, unable to download the APK',
63
63
  error_apk_download_failed: 'Failed to download or install the APK',
64
+ error_reset_not_supported:
65
+ 'resetToPackagedBundle is not available in the installed native module. Please rebuild the app with the latest react-native-update.',
64
66
 
65
67
  // Development messages
66
68
  dev_debug_disabled:
package/src/locales/zh.ts CHANGED
@@ -56,6 +56,8 @@ export default {
56
56
  error_apk_pending_install: '安装包已下载完成,请在系统安装界面完成安装',
57
57
  error_storage_permission_rejected: '存储权限被拒绝,无法下载安装包',
58
58
  error_apk_download_failed: '安装包下载或安装失败',
59
+ error_reset_not_supported:
60
+ '当前安装的原生模块不支持 resetToPackagedBundle,请使用最新版 react-native-update 重新打包后再试。',
59
61
 
60
62
  // Development messages
61
63
  dev_debug_disabled:
package/src/provider.tsx CHANGED
@@ -388,6 +388,13 @@ export const UpdateProvider = ({
388
388
  return client.restartApp();
389
389
  }, [client]);
390
390
 
391
+ const resetToPackagedBundle = useCallback(
392
+ async (resetOptions?: { restart?: boolean }) => {
393
+ return client.resetToPackagedBundle(resetOptions);
394
+ },
395
+ [client],
396
+ );
397
+
391
398
  useEffect(() => {
392
399
  if (!assertWeb()) {
393
400
  return;
@@ -438,6 +445,7 @@ export const UpdateProvider = ({
438
445
  currentVersionInfo,
439
446
  parseTestQrCode,
440
447
  restartApp,
448
+ resetToPackagedBundle,
441
449
  }),
442
450
  [
443
451
  checkUpdate,
@@ -452,6 +460,7 @@ export const UpdateProvider = ({
452
460
  downloadAndInstallApk,
453
461
  parseTestQrCode,
454
462
  restartApp,
463
+ resetToPackagedBundle,
455
464
  ],
456
465
  );
457
466
 
package/src/type.ts CHANGED
@@ -55,6 +55,8 @@ export type EventType =
55
55
  | 'errorUpdate'
56
56
  | 'markSuccess'
57
57
  | 'errorMarkSuccess'
58
+ | 'reset'
59
+ | 'errorReset'
58
60
  | 'errorSwitchVersion'
59
61
  | 'downloadingApk'
60
62
  | 'rejectStoragePermission'