@bravemobile/react-native-code-push 12.4.1 → 13.1.0-beta.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 (111) hide show
  1. package/CodePush.podspec +47 -2
  2. package/README.md +118 -3
  3. package/THIRD-PARTY-NOTICES +96 -0
  4. package/android/app/build.gradle +26 -0
  5. package/android/app/proguard-rules.pro +5 -0
  6. package/android/app/src/main/cpp/CMakeLists.txt +38 -0
  7. package/android/app/src/main/cpp/binarypatch_jni.c +181 -0
  8. package/android/app/src/main/java/com/microsoft/codepush/react/BinaryPatchAttempt.java +92 -0
  9. package/android/app/src/main/java/com/microsoft/codepush/react/BinaryPatchResult.java +64 -0
  10. package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +46 -11
  11. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushBinaryPatch.java +293 -0
  12. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +25 -0
  13. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +79 -88
  14. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +159 -4
  15. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +13 -0
  16. package/android/app/src/main/java/com/microsoft/codepush/react/HDiffPatchNative.java +52 -0
  17. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushBinaryPatchTest.java +393 -0
  18. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushUpdateManagerBinaryPatchTest.java +207 -0
  19. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushUpdateManagerDownloadTest.java +449 -0
  20. package/android/codepush-export.gradle +115 -0
  21. package/cli/commands/bundleCommand/bundleCodePush.ts +39 -7
  22. package/cli/commands/bundleCommand/index.ts +9 -1
  23. package/cli/commands/releaseCommand/addToReleaseHistory.ts +7 -0
  24. package/cli/commands/releaseCommand/index.test.ts +118 -0
  25. package/cli/commands/releaseCommand/index.ts +20 -2
  26. package/cli/commands/releaseCommand/release.test.ts +582 -0
  27. package/cli/commands/releaseCommand/release.ts +232 -15
  28. package/cli/dist/commands/bundleCommand/bundleCodePush.js +26 -7
  29. package/cli/dist/commands/bundleCommand/index.js +5 -1
  30. package/cli/dist/commands/releaseCommand/addToReleaseHistory.js +6 -1
  31. package/cli/dist/commands/releaseCommand/index.js +8 -1
  32. package/cli/dist/commands/releaseCommand/index.test.js +96 -0
  33. package/cli/dist/commands/releaseCommand/release.js +165 -17
  34. package/cli/dist/commands/releaseCommand/release.test.js +367 -0
  35. package/cli/dist/functions/makeBinaryPatchBundle.js +248 -0
  36. package/cli/dist/functions/makeBinaryPatchBundle.test.js +321 -0
  37. package/cli/dist/functions/makeCodePushBundle.js +4 -2
  38. package/cli/dist/functions/runHermesEmitBinaryCommand.js +98 -27
  39. package/cli/dist/functions/runHermesEmitBinaryCommand.test.js +100 -0
  40. package/cli/dist/jest.globalSetup.js +38 -0
  41. package/cli/dist/utils/binaryPatch.js +86 -0
  42. package/cli/dist/utils/binaryPatch.test.js +190 -0
  43. package/cli/functions/makeBinaryPatchBundle.test.ts +410 -0
  44. package/cli/functions/makeBinaryPatchBundle.ts +367 -0
  45. package/cli/functions/makeCodePushBundle.ts +4 -2
  46. package/cli/functions/runHermesEmitBinaryCommand.test.ts +124 -0
  47. package/cli/functions/runHermesEmitBinaryCommand.ts +112 -26
  48. package/cli/jest.globalSetup.ts +43 -0
  49. package/cli/utils/binaryPatch.test.ts +234 -0
  50. package/cli/utils/binaryPatch.ts +103 -0
  51. package/cpp/binarypatch/binarypatch_zstd_decompressor.c +187 -0
  52. package/cpp/binarypatch/binarypatch_zstd_decompressor.h +47 -0
  53. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/checksum_plugin.h +52 -0
  54. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/hpatch_mt/hpatch_mt.h +147 -0
  55. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/patch.c +3315 -0
  56. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/patch.h +268 -0
  57. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/patch_private.h +297 -0
  58. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/patch_types.h +434 -0
  59. package/cpp/binarypatch/vendor/zstd/common/allocations.h +55 -0
  60. package/cpp/binarypatch/vendor/zstd/common/bits.h +205 -0
  61. package/cpp/binarypatch/vendor/zstd/common/bitstream.h +454 -0
  62. package/cpp/binarypatch/vendor/zstd/common/compiler.h +464 -0
  63. package/cpp/binarypatch/vendor/zstd/common/cpu.h +249 -0
  64. package/cpp/binarypatch/vendor/zstd/common/debug.c +30 -0
  65. package/cpp/binarypatch/vendor/zstd/common/debug.h +107 -0
  66. package/cpp/binarypatch/vendor/zstd/common/entropy_common.c +340 -0
  67. package/cpp/binarypatch/vendor/zstd/common/error_private.c +64 -0
  68. package/cpp/binarypatch/vendor/zstd/common/error_private.h +158 -0
  69. package/cpp/binarypatch/vendor/zstd/common/fse.h +625 -0
  70. package/cpp/binarypatch/vendor/zstd/common/fse_decompress.c +315 -0
  71. package/cpp/binarypatch/vendor/zstd/common/huf.h +277 -0
  72. package/cpp/binarypatch/vendor/zstd/common/mem.h +422 -0
  73. package/cpp/binarypatch/vendor/zstd/common/pool.c +371 -0
  74. package/cpp/binarypatch/vendor/zstd/common/pool.h +81 -0
  75. package/cpp/binarypatch/vendor/zstd/common/portability_macros.h +171 -0
  76. package/cpp/binarypatch/vendor/zstd/common/threading.c +182 -0
  77. package/cpp/binarypatch/vendor/zstd/common/threading.h +142 -0
  78. package/cpp/binarypatch/vendor/zstd/common/xxhash.c +18 -0
  79. package/cpp/binarypatch/vendor/zstd/common/xxhash.h +7094 -0
  80. package/cpp/binarypatch/vendor/zstd/common/zstd_common.c +48 -0
  81. package/cpp/binarypatch/vendor/zstd/common/zstd_deps.h +123 -0
  82. package/cpp/binarypatch/vendor/zstd/common/zstd_internal.h +324 -0
  83. package/cpp/binarypatch/vendor/zstd/common/zstd_trace.h +156 -0
  84. package/cpp/binarypatch/vendor/zstd/decompress/huf_decompress.c +1944 -0
  85. package/cpp/binarypatch/vendor/zstd/decompress/zstd_ddict.c +244 -0
  86. package/cpp/binarypatch/vendor/zstd/decompress/zstd_ddict.h +44 -0
  87. package/cpp/binarypatch/vendor/zstd/decompress/zstd_decompress.c +2410 -0
  88. package/cpp/binarypatch/vendor/zstd/decompress/zstd_decompress_block.c +2209 -0
  89. package/cpp/binarypatch/vendor/zstd/decompress/zstd_decompress_block.h +73 -0
  90. package/cpp/binarypatch/vendor/zstd/decompress/zstd_decompress_internal.h +240 -0
  91. package/cpp/binarypatch/vendor/zstd/zstd.h +3206 -0
  92. package/cpp/binarypatch/vendor/zstd/zstd_errors.h +107 -0
  93. package/ios/CodePush/CodePush.h +58 -9
  94. package/ios/CodePush/{CodePush.m → CodePush.mm} +77 -63
  95. package/ios/CodePush/CodePushBinaryPatch.h +80 -0
  96. package/ios/CodePush/CodePushBinaryPatch.m +473 -0
  97. package/ios/CodePush/CodePushPackage.m +183 -2
  98. package/ios/CodePush/CodePushUpdateUtils.m +49 -1
  99. package/ios/CodePush.xcodeproj/project.pbxproj +6 -6
  100. package/package.json +28 -4
  101. package/react-native.config.js +3 -1
  102. package/scripts/binary-patch/build-hdiffpatch.sh +86 -0
  103. package/scripts/export-embedded-bundle.sh +76 -0
  104. package/src/CodePush.js +190 -96
  105. package/src/CodePush.test.js +382 -0
  106. package/src/native/NativeCodePush.ts +162 -0
  107. package/src/package-mixins.js +24 -11
  108. package/src/specs/NativeCodePush.ts +43 -0
  109. package/typings/react-native-code-push.d.ts +77 -0
  110. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushDialog.java +0 -102
  111. package/src/AlertAdapter.js +0 -24
@@ -0,0 +1,107 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
11
+ #ifndef ZSTD_ERRORS_H_398273423
12
+ #define ZSTD_ERRORS_H_398273423
13
+
14
+ #if defined (__cplusplus)
15
+ extern "C" {
16
+ #endif
17
+
18
+ /* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */
19
+ #ifndef ZSTDERRORLIB_VISIBLE
20
+ /* Backwards compatibility with old macro name */
21
+ # ifdef ZSTDERRORLIB_VISIBILITY
22
+ # define ZSTDERRORLIB_VISIBLE ZSTDERRORLIB_VISIBILITY
23
+ # elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
24
+ # define ZSTDERRORLIB_VISIBLE __attribute__ ((visibility ("default")))
25
+ # else
26
+ # define ZSTDERRORLIB_VISIBLE
27
+ # endif
28
+ #endif
29
+
30
+ #ifndef ZSTDERRORLIB_HIDDEN
31
+ # if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
32
+ # define ZSTDERRORLIB_HIDDEN __attribute__ ((visibility ("hidden")))
33
+ # else
34
+ # define ZSTDERRORLIB_HIDDEN
35
+ # endif
36
+ #endif
37
+
38
+ #if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
39
+ # define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBLE
40
+ #elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
41
+ # define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
42
+ #else
43
+ # define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBLE
44
+ #endif
45
+
46
+ /*-*********************************************
47
+ * Error codes list
48
+ *-*********************************************
49
+ * Error codes _values_ are pinned down since v1.3.1 only.
50
+ * Therefore, don't rely on values if you may link to any version < v1.3.1.
51
+ *
52
+ * Only values < 100 are considered stable.
53
+ *
54
+ * note 1 : this API shall be used with static linking only.
55
+ * dynamic linking is not yet officially supported.
56
+ * note 2 : Prefer relying on the enum than on its value whenever possible
57
+ * This is the only supported way to use the error list < v1.3.1
58
+ * note 3 : ZSTD_isError() is always correct, whatever the library version.
59
+ **********************************************/
60
+ typedef enum {
61
+ ZSTD_error_no_error = 0,
62
+ ZSTD_error_GENERIC = 1,
63
+ ZSTD_error_prefix_unknown = 10,
64
+ ZSTD_error_version_unsupported = 12,
65
+ ZSTD_error_frameParameter_unsupported = 14,
66
+ ZSTD_error_frameParameter_windowTooLarge = 16,
67
+ ZSTD_error_corruption_detected = 20,
68
+ ZSTD_error_checksum_wrong = 22,
69
+ ZSTD_error_literals_headerWrong = 24,
70
+ ZSTD_error_dictionary_corrupted = 30,
71
+ ZSTD_error_dictionary_wrong = 32,
72
+ ZSTD_error_dictionaryCreation_failed = 34,
73
+ ZSTD_error_parameter_unsupported = 40,
74
+ ZSTD_error_parameter_combination_unsupported = 41,
75
+ ZSTD_error_parameter_outOfBound = 42,
76
+ ZSTD_error_tableLog_tooLarge = 44,
77
+ ZSTD_error_maxSymbolValue_tooLarge = 46,
78
+ ZSTD_error_maxSymbolValue_tooSmall = 48,
79
+ ZSTD_error_cannotProduce_uncompressedBlock = 49,
80
+ ZSTD_error_stabilityCondition_notRespected = 50,
81
+ ZSTD_error_stage_wrong = 60,
82
+ ZSTD_error_init_missing = 62,
83
+ ZSTD_error_memory_allocation = 64,
84
+ ZSTD_error_workSpace_tooSmall= 66,
85
+ ZSTD_error_dstSize_tooSmall = 70,
86
+ ZSTD_error_srcSize_wrong = 72,
87
+ ZSTD_error_dstBuffer_null = 74,
88
+ ZSTD_error_noForwardProgress_destFull = 80,
89
+ ZSTD_error_noForwardProgress_inputEmpty = 82,
90
+ /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
91
+ ZSTD_error_frameIndex_tooLarge = 100,
92
+ ZSTD_error_seekableIO = 102,
93
+ ZSTD_error_dstBuffer_wrong = 104,
94
+ ZSTD_error_srcBuffer_wrong = 105,
95
+ ZSTD_error_sequenceProducer_failed = 106,
96
+ ZSTD_error_externalSequences_invalid = 107,
97
+ ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
98
+ } ZSTD_ErrorCode;
99
+
100
+ ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */
101
+
102
+
103
+ #if defined (__cplusplus)
104
+ }
105
+ #endif
106
+
107
+ #endif /* ZSTD_ERRORS_H_398273423 */
@@ -1,14 +1,40 @@
1
- #if __has_include(<React/RCTEventEmitter.h>)
2
- #import <React/RCTEventEmitter.h>
3
- #elif __has_include("RCTEventEmitter.h")
4
- #import "RCTEventEmitter.h"
1
+ #import <Foundation/Foundation.h>
2
+
3
+ #ifdef RCT_NEW_ARCH_ENABLED
4
+ #if defined(__cplusplus)
5
+ #if __has_include(<RNCodePushSpec/RNCodePushSpec.h>)
6
+ #import <RNCodePushSpec/RNCodePushSpec.h>
7
+ #elif __has_include("RNCodePushSpec.h")
8
+ #import "RNCodePushSpec.h"
9
+ #endif
10
+ #else
11
+ #if __has_include(<React/RCTBridgeModule.h>)
12
+ #import <React/RCTBridgeModule.h>
13
+ #elif __has_include("RCTBridgeModule.h")
14
+ #import "RCTBridgeModule.h"
15
+ #else
16
+ #import "React/RCTBridgeModule.h"
17
+ #endif
18
+ #endif
5
19
  #else
6
- #import "React/RCTEventEmitter.h" // Required when used as a Pod in a Swift project
20
+ #if __has_include(<React/RCTEventEmitter.h>)
21
+ #import <React/RCTEventEmitter.h>
22
+ #elif __has_include("RCTEventEmitter.h")
23
+ #import "RCTEventEmitter.h"
24
+ #else
25
+ #import "React/RCTEventEmitter.h" // Required when used as a Pod in a Swift project
26
+ #endif
7
27
  #endif
8
28
 
9
- #import <Foundation/Foundation.h>
10
-
29
+ #ifdef RCT_NEW_ARCH_ENABLED
30
+ #if defined(__cplusplus)
31
+ @interface CodePush : NativeCodePushSpecBase
32
+ #else
33
+ @interface CodePush : NSObject <RCTBridgeModule>
34
+ #endif
35
+ #else
11
36
  @interface CodePush : RCTEventEmitter
37
+ #endif
12
38
 
13
39
  + (NSURL *)binaryBundleURL;
14
40
  /*
@@ -68,7 +94,7 @@
68
94
  * This information will be used to decide whether the application
69
95
  * should ignore the update or not.
70
96
  */
71
- + (NSDictionary*)getRollbackInfo;
97
+ + (NSDictionary*)getLatestRollbackInfo;
72
98
  /*
73
99
  * This method is used to save information about the latest rollback.
74
100
  * This information will be used to decide whether the application
@@ -137,11 +163,16 @@ failCallback:(void (^)(NSError *err))failCallback;
137
163
 
138
164
  @interface CodePushPackage : NSObject
139
165
 
166
+ /*
167
+ * doneCallback is given what the attempt at installing the update from its binary patch
168
+ * archive ended in, or nil when the update had no patch archive to attempt. The result
169
+ * describes the download and not the update: it is never part of the update's metadata.
170
+ */
140
171
  + (void)downloadPackage:(NSDictionary *)updatePackage
141
172
  expectedBundleFileName:(NSString *)expectedBundleFileName
142
173
  operationQueue:(dispatch_queue_t)operationQueue
143
174
  progressCallback:(void (^)(long long, long long))progressCallback
144
- doneCallback:(void (^)())doneCallback
175
+ doneCallback:(void (^)(NSDictionary *binaryPatchResult))doneCallback
145
176
  failCallback:(void (^)(NSError *err))failCallback;
146
177
 
147
178
  + (NSDictionary *)getCurrentPackage:(NSError **)error;
@@ -180,6 +211,18 @@ failCallback:(void (^)(NSError *err))failCallback;
180
211
 
181
212
  @interface CodePushUpdateUtils : NSObject
182
213
 
214
+ /*
215
+ * The SHA-256 of some bytes, written the way every hash of an update's
216
+ * contents is: lower case hex.
217
+ */
218
+ + (NSString *)computeHashForData:(NSData *)inputData;
219
+
220
+ /*
221
+ * The same hash, of the contents of a file. Returns nil when the file
222
+ * cannot be read.
223
+ */
224
+ + (NSString *)computeHashForFileAtPath:(NSString *)filePath;
225
+
183
226
  + (BOOL)copyEntriesInFolder:(NSString *)sourceFolder
184
227
  destFolder:(NSString *)destFolder
185
228
  error:(NSError **)error;
@@ -203,7 +246,13 @@ failCallback:(void (^)(NSError *err))failCallback;
203
246
 
204
247
  @end
205
248
 
249
+ #if defined(__cplusplus)
250
+ extern "C" {
251
+ #endif
206
252
  void CPLog(NSString *formatString, ...);
253
+ #if defined(__cplusplus)
254
+ }
255
+ #endif
207
256
 
208
257
  typedef NS_ENUM(NSInteger, CodePushInstallMode) {
209
258
  CodePushInstallModeImmediate,
@@ -8,7 +8,11 @@
8
8
 
9
9
  #import "CodePush.h"
10
10
 
11
- @interface CodePush () <RCTBridgeModule, RCTFrameUpdateObserver>
11
+ @interface CodePush () <RCTFrameUpdateObserver
12
+ #ifdef RCT_NEW_ARCH_ENABLED
13
+ , NativeCodePushSpec
14
+ #endif
15
+ >
12
16
  @end
13
17
 
14
18
  @implementation CodePush {
@@ -57,11 +61,16 @@ static NSString *const BinaryBundleDateKey = @"binaryDate";
57
61
  static NSString *const PackageHashKey = @"packageHash";
58
62
  static NSString *const PackageIsPendingKey = @"isPending";
59
63
 
64
+ // Not one of those keys: the field a download that tried a binary patch reports its outcome
65
+ // under, on the package it resolves with and on no package it stores.
66
+ static NSString *const BinaryPatchResultKey = @"binaryPatchResult";
67
+
60
68
  #pragma mark - Static variables
61
69
 
62
70
  static BOOL isRunningBinaryVersion = NO;
63
71
  static BOOL needToReportRollback = NO;
64
72
  static BOOL testConfigurationFlag = NO;
73
+ static BOOL hasInitializedUpdateAfterRestartForCurrentLoad = NO;
65
74
 
66
75
  // These values are used to save the NS bundle, name, extension and subdirectory
67
76
  // for the JS bundle in the binary.
@@ -246,6 +255,9 @@ static NSString *const LatestRollbackCountKey = @"count";
246
255
 
247
256
  #pragma mark - Private API methods
248
257
 
258
+ #ifdef RCT_NEW_ARCH_ENABLED
259
+ @synthesize bridge = _bridge;
260
+ #endif
249
261
  @synthesize methodQueue = _methodQueue;
250
262
  @synthesize pauseCallback = _pauseCallback;
251
263
  @synthesize paused = _paused;
@@ -269,7 +281,7 @@ static NSString *const LatestRollbackCountKey = @"count";
269
281
  - (void)clearDebugUpdates
270
282
  {
271
283
  dispatch_async(dispatch_get_main_queue(), ^{
272
- if ([super.bridge.bundleURL.scheme hasPrefix:@"http"]) {
284
+ if ([self.bridge.bundleURL.scheme hasPrefix:@"http"]) {
273
285
  NSError *error;
274
286
  NSString *binaryAppVersion = [[CodePushConfig current] appVersion];
275
287
  NSDictionary *currentPackageMetadata = [CodePushPackage getCurrentPackage:&error];
@@ -283,28 +295,6 @@ static NSString *const LatestRollbackCountKey = @"count";
283
295
  });
284
296
  }
285
297
 
286
- /*
287
- * This method is used by the React Native bridge to allow
288
- * our plugin to expose constants to the JS-side. In our case
289
- * we're simply exporting enum values so that the JS and Native
290
- * sides of the plugin can be in sync.
291
- */
292
- - (NSDictionary *)constantsToExport
293
- {
294
- // Export the values of the CodePushInstallMode and CodePushUpdateState
295
- // enums so that the script-side can easily stay in sync
296
- return @{
297
- @"codePushInstallModeOnNextRestart":@(CodePushInstallModeOnNextRestart),
298
- @"codePushInstallModeImmediate": @(CodePushInstallModeImmediate),
299
- @"codePushInstallModeOnNextResume": @(CodePushInstallModeOnNextResume),
300
- @"codePushInstallModeOnNextSuspend": @(CodePushInstallModeOnNextSuspend),
301
-
302
- @"codePushUpdateStateRunning": @(CodePushUpdateStateRunning),
303
- @"codePushUpdateStatePending": @(CodePushUpdateStatePending),
304
- @"codePushUpdateStateLatest": @(CodePushUpdateStateLatest)
305
- };
306
- };
307
-
308
298
  + (BOOL)requiresMainQueueSetup
309
299
  {
310
300
  return YES;
@@ -319,13 +309,16 @@ static NSString *const LatestRollbackCountKey = @"count";
319
309
 
320
310
  - (void)dispatchDownloadProgressEvent {
321
311
  // Notify the script-side about the progress
322
- [self sendEventWithName:DownloadProgressEvent
323
- body:@{
324
- @"totalBytes" : [NSNumber
325
- numberWithLongLong:_latestExpectedContentLength],
326
- @"receivedBytes" : [NSNumber
327
- numberWithLongLong:_latestReceivedConentLength]
328
- }];
312
+ NSDictionary *progress = @{
313
+ @"totalBytes" : [NSNumber numberWithLongLong:_latestExpectedContentLength],
314
+ @"receivedBytes" : [NSNumber numberWithLongLong:_latestReceivedConentLength]
315
+ };
316
+
317
+ #ifndef RCT_NEW_ARCH_ENABLED
318
+ [self sendEventWithName:DownloadProgressEvent body:progress];
319
+ #else
320
+ [self emitOnDownloadProgress:progress];
321
+ #endif
329
322
  }
330
323
 
331
324
  - (void)dispatchThrottledDownloadProgressEventWithForce:(BOOL)force
@@ -385,7 +378,12 @@ static NSString *const LatestRollbackCountKey = @"count";
385
378
 
386
379
  self = [super init];
387
380
  if (self) {
388
- [self initializeUpdateAfterRestart];
381
+ @synchronized([CodePush class]) {
382
+ if (!hasInitializedUpdateAfterRestartForCurrentLoad) {
383
+ hasInitializedUpdateAfterRestartForCurrentLoad = YES;
384
+ [self initializeUpdateAfterRestart];
385
+ }
386
+ }
389
387
  }
390
388
 
391
389
  return self;
@@ -535,6 +533,10 @@ static NSString *const LatestRollbackCountKey = @"count";
535
533
  */
536
534
  - (void)loadBundle
537
535
  {
536
+ @synchronized([CodePush class]) {
537
+ hasInitializedUpdateAfterRestartForCurrentLoad = NO;
538
+ }
539
+
538
540
  // This needs to be async dispatched because the bridge is not set on init
539
541
  // when the app first starts, therefore rollbacks will not take effect.
540
542
  dispatch_async(dispatch_get_main_queue(), ^{
@@ -542,8 +544,8 @@ static NSString *const LatestRollbackCountKey = @"count";
542
544
  // is debugging and therefore, shouldn't be redirected to a local
543
545
  // file (since Chrome wouldn't support it). Otherwise, update
544
546
  // the current bundle URL to point at the latest update
545
- if ([CodePush isUsingTestConfiguration] || ![super.bridge.bundleURL.scheme hasPrefix:@"http"]) {
546
- [super.bridge setValue:[CodePush bundleURL] forKey:@"bundleURL"];
547
+ if ([CodePush isUsingTestConfiguration] || ![self.bridge.bundleURL.scheme hasPrefix:@"http"]) {
548
+ [self.bridge setValue:[CodePush bundleURL] forKey:@"bundleURL"];
547
549
  }
548
550
 
549
551
  RCTTriggerReloadCommandListeners(@"CodePush reload");
@@ -713,8 +715,8 @@ static NSString *const LatestRollbackCountKey = @"count";
713
715
  */
714
716
  RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
715
717
  notifyProgress:(BOOL)notifyProgress
716
- resolver:(RCTPromiseResolveBlock)resolve
717
- rejecter:(RCTPromiseRejectBlock)reject)
718
+ resolve:(RCTPromiseResolveBlock)resolve
719
+ reject:(RCTPromiseRejectBlock)reject)
718
720
  {
719
721
  NSDictionary *mutableUpdatePackage = [updatePackage mutableCopy];
720
722
  NSURL *binaryBundleURL = [CodePush binaryBundleURL];
@@ -757,13 +759,24 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
757
759
  }
758
760
  }
759
761
  // The download completed
760
- doneCallback:^{
762
+ doneCallback:^(NSDictionary *binaryPatchResult) {
761
763
  NSError *err;
762
764
  NSDictionary *newPackage = [CodePushPackage getPackage:mutableUpdatePackage[PackageHashKey] error:&err];
763
765
 
764
766
  if (err) {
765
767
  return reject([NSString stringWithFormat: @"%lu", (long)err.code], err.localizedDescription, err);
766
768
  }
769
+
770
+ if (binaryPatchResult) {
771
+ // The result describes this download rather than the update, so it is put on
772
+ // what this call resolves with and nowhere else: the metadata that was
773
+ // written for the update knows nothing about it, and whoever asked for the
774
+ // download decides what the result is worth.
775
+ NSMutableDictionary *downloadedPackage = [newPackage mutableCopy];
776
+ downloadedPackage[BinaryPatchResultKey] = binaryPatchResult;
777
+ return resolve(downloadedPackage);
778
+ }
779
+
767
780
  resolve(newPackage);
768
781
  }
769
782
  // The download failed
@@ -813,7 +826,7 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
813
826
  * app version, as well as the deployment key that was configured in the Info.plist file.
814
827
  */
815
828
  RCT_EXPORT_METHOD(getConfiguration:(RCTPromiseResolveBlock)resolve
816
- rejecter:(RCTPromiseRejectBlock)reject)
829
+ reject:(RCTPromiseRejectBlock)reject)
817
830
  {
818
831
  NSDictionary *configuration = [[CodePushConfig current] configuration];
819
832
  NSError *error;
@@ -846,10 +859,11 @@ RCT_EXPORT_METHOD(getConfiguration:(RCTPromiseResolveBlock)resolve
846
859
  /*
847
860
  * This method is the native side of the CodePush.getUpdateMetadata method.
848
861
  */
849
- RCT_EXPORT_METHOD(getUpdateMetadata:(CodePushUpdateState)updateState
850
- resolver:(RCTPromiseResolveBlock)resolve
851
- rejecter:(RCTPromiseRejectBlock)reject)
862
+ RCT_EXPORT_METHOD(getUpdateMetadata:(double)updateStateValue
863
+ resolve:(RCTPromiseResolveBlock)resolve
864
+ reject:(RCTPromiseRejectBlock)reject)
852
865
  {
866
+ CodePushUpdateState updateState = (CodePushUpdateState)updateStateValue;
853
867
  NSError *error;
854
868
  NSMutableDictionary *package = [[CodePushPackage getCurrentPackage:&error] mutableCopy];
855
869
 
@@ -895,11 +909,13 @@ RCT_EXPORT_METHOD(getUpdateMetadata:(CodePushUpdateState)updateState
895
909
  * This method is the native side of the LocalPackage.install method.
896
910
  */
897
911
  RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage
898
- installMode:(CodePushInstallMode)installMode
899
- minimumBackgroundDuration:(int)minimumBackgroundDuration
900
- resolver:(RCTPromiseResolveBlock)resolve
901
- rejecter:(RCTPromiseRejectBlock)reject)
912
+ installMode:(double)installModeValue
913
+ minimumBackgroundDuration:(double)minimumBackgroundDurationValue
914
+ resolve:(RCTPromiseResolveBlock)resolve
915
+ reject:(RCTPromiseRejectBlock)reject)
902
916
  {
917
+ CodePushInstallMode installMode = (CodePushInstallMode)installModeValue;
918
+ int minimumBackgroundDuration = (int)minimumBackgroundDurationValue;
903
919
  NSError *error;
904
920
  [CodePushPackage installPackage:updatePackage
905
921
  removePendingUpdate:[[self class] isPendingUpdate:nil]
@@ -965,7 +981,7 @@ RCT_EXPORT_METHOD(setLatestRollbackInfo:(NSString *)packageHash
965
981
 
966
982
 
967
983
  RCT_EXPORT_METHOD(getLatestRollbackInfo:(RCTPromiseResolveBlock)resolve
968
- rejecter:(RCTPromiseRejectBlock)reject)
984
+ reject:(RCTPromiseRejectBlock)reject)
969
985
  {
970
986
  NSDictionary *latestRollbackInfo = [[self class] getLatestRollbackInfo];
971
987
  resolve(latestRollbackInfo);
@@ -977,7 +993,7 @@ RCT_EXPORT_METHOD(getLatestRollbackInfo:(RCTPromiseResolveBlock)resolve
977
993
  */
978
994
  RCT_EXPORT_METHOD(isFirstRun:(NSString *)packageHash
979
995
  resolve:(RCTPromiseResolveBlock)resolve
980
- rejecter:(RCTPromiseRejectBlock)reject)
996
+ reject:(RCTPromiseRejectBlock)reject)
981
997
  {
982
998
  NSError *error;
983
999
  BOOL isFirstRun = _isFirstRunAfterUpdate
@@ -992,14 +1008,13 @@ RCT_EXPORT_METHOD(isFirstRun:(NSString *)packageHash
992
1008
  * This method is the native side of the CodePush.notifyApplicationReady() method.
993
1009
  */
994
1010
  RCT_EXPORT_METHOD(notifyApplicationReady:(RCTPromiseResolveBlock)resolve
995
- rejecter:(RCTPromiseRejectBlock)reject)
1011
+ reject:(RCTPromiseRejectBlock)reject)
996
1012
  {
997
1013
  [CodePush removePendingUpdate];
998
1014
  resolve(nil);
999
1015
  }
1000
1016
 
1001
- RCT_EXPORT_METHOD(allow:(RCTPromiseResolveBlock)resolve
1002
- rejecter:(RCTPromiseRejectBlock)reject)
1017
+ RCT_EXPORT_METHOD(allow)
1003
1018
  {
1004
1019
  CPLog(@"Re-allowing restarts.");
1005
1020
  _allowed = YES;
@@ -1010,34 +1025,25 @@ RCT_EXPORT_METHOD(allow:(RCTPromiseResolveBlock)resolve
1010
1025
  [_restartQueue removeObjectAtIndex:0];
1011
1026
  [self restartAppInternal:buf];
1012
1027
  }
1013
-
1014
- resolve(nil);
1015
1028
  }
1016
1029
 
1017
- RCT_EXPORT_METHOD(clearPendingRestart:(RCTPromiseResolveBlock)resolve
1018
- rejecter:(RCTPromiseRejectBlock)reject)
1030
+ RCT_EXPORT_METHOD(clearPendingRestart)
1019
1031
  {
1020
1032
  [_restartQueue removeAllObjects];
1021
- resolve(nil);
1022
1033
  }
1023
1034
 
1024
- RCT_EXPORT_METHOD(disallow:(RCTPromiseResolveBlock)resolve
1025
- rejecter:(RCTPromiseRejectBlock)reject)
1035
+ RCT_EXPORT_METHOD(disallow)
1026
1036
  {
1027
1037
  CPLog(@"Disallowing restarts.");
1028
1038
  _allowed = NO;
1029
- resolve(nil);
1030
1039
  }
1031
1040
 
1032
1041
  /*
1033
1042
  * This method is the native side of the CodePush.restartApp() method.
1034
1043
  */
1035
- RCT_EXPORT_METHOD(restartApp:(BOOL)onlyIfUpdateIsPending
1036
- resolve:(RCTPromiseResolveBlock)resolve
1037
- rejecter:(RCTPromiseRejectBlock)reject)
1044
+ RCT_EXPORT_METHOD(restartApp:(BOOL)onlyIfUpdateIsPending)
1038
1045
  {
1039
1046
  [self restartAppInternal:onlyIfUpdateIsPending];
1040
- resolve(nil);
1041
1047
  }
1042
1048
 
1043
1049
  /*
@@ -1071,7 +1077,7 @@ RCT_EXPORT_METHOD(downloadAndReplaceCurrentBundle:(NSString *)remoteBundleUrl)
1071
1077
  * or an update failed) and return its details (version label, status).
1072
1078
  */
1073
1079
  RCT_EXPORT_METHOD(getNewStatusReport:(RCTPromiseResolveBlock)resolve
1074
- rejecter:(RCTPromiseRejectBlock)reject)
1080
+ reject:(RCTPromiseRejectBlock)reject)
1075
1081
  {
1076
1082
  if (needToReportRollback) {
1077
1083
  needToReportRollback = NO;
@@ -1128,4 +1134,12 @@ RCT_EXPORT_METHOD(saveStatusReportForRetry:(NSDictionary *)statusReport)
1128
1134
  _didUpdateProgress = NO;
1129
1135
  }
1130
1136
 
1137
+ #ifdef RCT_NEW_ARCH_ENABLED
1138
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
1139
+ (const facebook::react::ObjCTurboModule::InitParams &)params
1140
+ {
1141
+ return std::make_shared<facebook::react::NativeCodePushSpecJSI>(params);
1142
+ }
1143
+ #endif
1144
+
1131
1145
  @end
@@ -0,0 +1,80 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ /*
4
+ * Why an update that was downloaded as a binary patch has to be downloaded in full
5
+ * instead.
6
+ *
7
+ * A failed restore is not an error the user ever hears about: it is the signal to
8
+ * download the update's full archive. These reasons are the vocabulary the appliers of
9
+ * every platform report, and the logs a rollout is judged from are read for exactly
10
+ * these words, so they must not be reworded.
11
+ */
12
+
13
+ /** The bundle inside the app binary could not be opened or read. */
14
+ extern NSString *const CodePushBinaryPatchReasonBaseBundleUnavailable;
15
+
16
+ /** The bundle inside the app binary is not the one the patch was computed against. */
17
+ extern NSString *const CodePushBinaryPatchReasonBaseHashMismatch;
18
+
19
+ /** The manifest is missing, malformed, points outside the archive, or asks for too much. */
20
+ extern NSString *const CodePushBinaryPatchReasonInvalidManifest;
21
+
22
+ /** The patch was produced by a format or a codec this client cannot apply. */
23
+ extern NSString *const CodePushBinaryPatchReasonUnsupportedFormat;
24
+
25
+ /** The applier refused the patch, or the restored bundle could not be written. */
26
+ extern NSString *const CodePushBinaryPatchReasonPatchApplyFailed;
27
+
28
+ /** The restored bundle is not the one the manifest promised. */
29
+ extern NSString *const CodePushBinaryPatchReasonTargetVerificationFailed;
30
+
31
+ /**
32
+ * The update restored from the patch did not pass the checks every update passes before
33
+ * it is installed - the folder hash above all.
34
+ *
35
+ * This one is reported by the caller rather than by the applier: by the time it applies,
36
+ * the applier has already handed back a bundle it was happy with.
37
+ */
38
+ extern NSString *const CodePushBinaryPatchReasonPackageVerificationFailed;
39
+
40
+ /**
41
+ * Rebuilds the JS bundle of an update that was downloaded as a binary patch archive.
42
+ *
43
+ * A patch archive holds everything the full archive holds except the JS bundle, which it
44
+ * carries as a patch against the bundle that shipped inside the app binary, plus a
45
+ * manifest describing how to rebuild it. Restoring means applying that patch, verifying
46
+ * the result, moving it to where the bundle belongs and deleting the two patch-only
47
+ * files. What is left is byte for byte the contents of the full archive, so the folder
48
+ * hash check that follows the install is unchanged and stays the last line of defence.
49
+ *
50
+ * Nothing here trusts the patch. Neither the diff format nor the zstd streams inside it
51
+ * carry a checksum of the data they produce, so an apply that reports success is not
52
+ * proof of a correct result: a base bundle of the right size but the wrong content, or a
53
+ * corrupted patch body, both produce wrong bytes without any error. The base bundle is
54
+ * hashed before the patch is applied and the restored bundle is hashed afterwards, and
55
+ * the restored bytes only reach the update contents once both checks have passed.
56
+ *
57
+ * Every failure is reported as a reason, never as an exception: the caller answers all
58
+ * of them the same way, by downloading the full archive instead.
59
+ */
60
+ @interface CodePushBinaryPatch : NSObject
61
+
62
+ /**
63
+ * Turns the contents of a downloaded patch archive into the contents of the full one.
64
+ *
65
+ * This reads and hashes whole bundles, so it belongs on the queue the download runs on
66
+ * and never on the main queue.
67
+ *
68
+ * @param unzippedFolderPath the unzipped archive, which is modified in place
69
+ * @param workingFolderPath scratch directory for the restored bundle, emptied before
70
+ * and after the attempt so an interrupted run leaves nothing
71
+ * @param baseBundleURL the JS bundle that shipped inside the app binary
72
+ * @param failureReason set to the reason the full archive has to be downloaded
73
+ * instead, whenever this returns NO
74
+ */
75
+ + (BOOL)restoreBundleInUnzippedFolder:(NSString *)unzippedFolderPath
76
+ workingFolder:(NSString *)workingFolderPath
77
+ baseBundleURL:(NSURL *)baseBundleURL
78
+ failureReason:(NSString **)failureReason;
79
+
80
+ @end