expo-dev-launcher 4.0.0 → 4.0.2

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 (33) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/android/build.gradle +1 -1
  3. package/android/src/debug/java/expo/modules/devlauncher/DevLauncherController.kt +43 -16
  4. package/android/src/debug/java/expo/modules/devlauncher/DevLauncherPackageDelegate.kt +1 -1
  5. package/android/src/debug/java/expo/modules/devlauncher/helpers/DevLauncherReactUtils.kt +158 -46
  6. package/android/src/debug/java/expo/modules/devlauncher/launcher/DevLauncherActivity.kt +10 -8
  7. package/android/src/debug/java/expo/modules/devlauncher/launcher/DevLauncherNetworkInterceptor.kt +12 -11
  8. package/android/src/debug/java/expo/modules/devlauncher/launcher/DevLauncherReactHost.kt +109 -0
  9. package/android/src/debug/java/expo/modules/devlauncher/launcher/{DevLauncherClientHost.kt → DevLauncherReactNativeHost.kt} +2 -2
  10. package/android/src/debug/java/expo/modules/devlauncher/launcher/errors/DevLauncherErrorActivity.kt +1 -1
  11. package/android/src/debug/java/expo/modules/devlauncher/launcher/errors/DevLauncherUncaughtExceptionHandler.kt +4 -3
  12. package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoader.kt +6 -6
  13. package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactory.kt +2 -3
  14. package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherExpoAppLoader.kt +2 -2
  15. package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherLocalAppLoader.kt +2 -2
  16. package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherPublishedAppLoader.kt +2 -2
  17. package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherReactNativeAppLoader.kt +2 -2
  18. package/android/src/debug/java/expo/modules/devlauncher/react/DevLauncherDevSupportManagerSwapper.kt +119 -57
  19. package/android/src/main/java/com/facebook/react/devsupport/NonFinalBridgeDevSupportManager.java +273 -0
  20. package/android/src/main/java/com/facebook/react/runtime/NonFinalBridgelessDevSupportManager.java +177 -0
  21. package/android/src/main/java/expo/modules/devlauncher/launcher/DevLauncherControllerInterface.kt +4 -4
  22. package/android/src/react-native-74/debug/expo/modules/devlauncher/rncompatibility/DevLauncherBridgeDevSupportManager.kt +75 -0
  23. package/android/src/react-native-74/debug/expo/modules/devlauncher/rncompatibility/DevLauncherBridgelessDevSupportManager.kt +55 -0
  24. package/android/src/react-native-74/debug/expo/modules/devlauncher/rncompatibility/DevLauncherDevSupportManagerFactory.kt +3 -3
  25. package/android/src/release/java/expo/modules/devlauncher/DevLauncherController.kt +13 -9
  26. package/android/src/release/java/expo/modules/devlauncher/launcher/DevLauncherReactHost.kt +11 -0
  27. package/android/src/release/java/expo/modules/devlauncher/launcher/{DevLauncherClientHost.kt → DevLauncherReactNativeHost.kt} +1 -1
  28. package/android/src/testDebug/java/expo/modules/devlauncher/DevLauncherControllerTest.kt +3 -3
  29. package/android/src/testDebug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactoryTest.kt +3 -4
  30. package/build/DevLauncherErrorManager.js.map +1 -1
  31. package/package.json +4 -4
  32. package/plugin/build/pluginConfig.js +2 -1
  33. package/android/src/react-native-74/debug/expo/modules/devlauncher/rncompatibility/DevLauncherDevSupportManager.kt +0 -286
@@ -0,0 +1,11 @@
1
+ package expo.modules.devlauncher.launcher
2
+
3
+ import android.app.Application
4
+ import com.facebook.react.ReactHost
5
+ import expo.modules.devlauncher.DEV_LAUNCHER_IS_NOT_AVAILABLE
6
+
7
+ object DevLauncherReactHost {
8
+ fun create(application: Application, launcherIp: String?): ReactHost {
9
+ throw IllegalStateException(DEV_LAUNCHER_IS_NOT_AVAILABLE)
10
+ }
11
+ }
@@ -5,7 +5,7 @@ import com.facebook.react.ReactNativeHost
5
5
  import com.facebook.react.ReactPackage
6
6
  import expo.modules.devlauncher.DEV_LAUNCHER_IS_NOT_AVAILABLE
7
7
 
8
- class DevLauncherClientHost(application: Application) : ReactNativeHost(application) {
8
+ class DevLauncherReactNativeHost(application: Application, launcherIp: String?) : ReactNativeHost(application) {
9
9
  override fun getPackages(): MutableList<ReactPackage> {
10
10
  throw IllegalStateException(DEV_LAUNCHER_IS_NOT_AVAILABLE)
11
11
  }
@@ -3,7 +3,7 @@ package expo.modules.devlauncher
3
3
  import android.content.Intent
4
4
  import android.net.Uri
5
5
  import androidx.test.core.app.ApplicationProvider
6
- import com.facebook.react.ReactNativeHost
6
+ import expo.interfaces.devmenu.ReactHostWrapper
7
7
  import expo.modules.devlauncher.koin.DevLauncherKoinContext
8
8
  import expo.modules.devlauncher.tests.DevLauncherTestInterceptor
9
9
  import expo.modules.devmenu.DevMenuManager
@@ -23,10 +23,10 @@ class DevLauncherControllerTest {
23
23
 
24
24
  @Before
25
25
  fun setup() {
26
- val reactNativeHost = mockk<ReactNativeHost>(relaxed = true)
26
+ val reactHost = mockk<ReactHostWrapper>(relaxed = true)
27
27
  DevLauncherKoinContext.reinitialize()
28
28
  DevLauncherKoinContext.app.koin.declare(DevLauncherTestInterceptorAllowReinitialization())
29
- DevLauncherController.initialize(ApplicationProvider.getApplicationContext(), reactNativeHost)
29
+ DevLauncherController.initialize(ApplicationProvider.getApplicationContext(), reactHost)
30
30
  }
31
31
 
32
32
  @Test
@@ -3,9 +3,9 @@ package expo.modules.devlauncher.launcher.loaders
3
3
  import android.content.Context
4
4
  import android.net.Uri
5
5
  import androidx.test.core.app.ApplicationProvider
6
- import com.facebook.react.ReactNativeHost
7
6
  import com.google.common.truth.Truth
8
7
  import expo.modules.devlauncher.helpers.DevLauncherInstallationIDHelper
8
+ import expo.interfaces.devmenu.ReactHostWrapper
9
9
  import expo.modules.devlauncher.helpers.loadUpdate
10
10
  import expo.modules.devlauncher.koin.DevLauncherKoinContext
11
11
  import expo.modules.devlauncher.launcher.DevLauncherControllerInterface
@@ -24,7 +24,6 @@ import org.junit.Test
24
24
  import org.junit.runner.RunWith
25
25
  import org.koin.dsl.module
26
26
  import org.robolectric.RobolectricTestRunner
27
- import java.lang.Exception
28
27
 
29
28
  @RunWith(RobolectricTestRunner::class)
30
29
  internal class DevLauncherAppLoaderFactoryTest {
@@ -36,13 +35,13 @@ internal class DevLauncherAppLoaderFactoryTest {
36
35
 
37
36
  @Before
38
37
  fun setup() {
39
- val reactNativeHost = mockk<ReactNativeHost>(relaxed = true)
38
+ val reactHost = mockk<ReactHostWrapper>(relaxed = true)
40
39
  val devLauncherController = mockk<DevLauncherControllerInterface>(relaxed = true)
41
40
  DevLauncherKoinContext.app.koin.loadModules(
42
41
  listOf(
43
42
  module {
44
43
  single<Context> { ApplicationProvider.getApplicationContext() }
45
- single { reactNativeHost }
44
+ single { reactHost }
46
45
  single { devLauncherController }
47
46
  single<UpdatesInterface?> { null }
48
47
  single { mockk<DevLauncherInstallationIDHelper>(relaxed = true) }
@@ -1 +1 @@
1
- {"version":3,"file":"DevLauncherErrorManager.js","sourceRoot":"","sources":["../src/DevLauncherErrorManager.ts"],"names":[],"mappings":"AAGA,IAAI,sBAAsB,GAAG,IAAI,CAAC;AAClC,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,gDAAgD;AAEpE,MAAM,iCAAiC,GAAG;;;;mGAIyD,CAAC;AAEpG,MAAM,gCAAgC,GAAG;;;mGAG0D,CAAC;AAEpG,SAAS,2BAA2B,CAAC,KAAiB;IACpD,KAAK,CAAC,OAAO,IAAI,MAAM,GAAG,iCAAiC,CAAC;AAC9D,CAAC;AAED,SAAS,+BAA+B,CAAC,KAAY;IACnD,KAAK,CAAC,OAAO,GAAG;;EAEhB,gCAAgC,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB;IAC/C,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QACpB,sCAAsC;QACtC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,2BAA2B,CAAC,KAAK,CAAC,CAAC;gBACnC,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;SAAM,IACL,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CAAC,IAAI,4BAA4B;QACtF,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,0DAA0D,CAAC,CAAC,mBAAmB;MACtG,CAAC;QACD,+BAA+B,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,eAAe,EAAE,KAAK,EAAE,OAAO;IACnD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,gGAAgG;QAChG,oGAAoG;QACpG,IAAI,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,6CAA6C,CAAC,EAAE,CAAC;YACrF,OAAO;QACT,CAAC;QACD,cAAc,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,GAAG,IAAI,CAAC;IACd,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,eAAe;IAChD,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,sBAAsB,EAAE,CAAC;YAC3B,YAAY,CAAC,eAAe,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,sBAAsB,GAAG,KAAK,CAAC;AACjC,CAAC","sourcesContent":["// Similar interface to the one used in expo modules.\ntype CodedError = Error & { code?: string };\n\nlet isErrorHandlingEnabled = true;\nlet wasHit = false; // whether the original error handler was called\n\nconst unavailableErrorPossibleSolutions = `Some possible solutions:\n- Make sure that the method is available on the current platform.\n- Make sure you're using the newest available version of this development client.\n- Make sure you're running a compatible version of your JavaScript code.\n- If you've installed a new library recently, you may need to make a new development client build.`;\n\nconst moduleIsMissingPossibleSolutions = `Some possible solutions:\n- Make sure you're using the newest available version of this development client.\n- Make sure you're running a compatible version of your JavaScript code.\n- If you've installed a new library recently, you may need to make a new development client build.`;\n\nfunction customizeUnavailableMessage(error: CodedError) {\n error.message += '\\n\\n' + unavailableErrorPossibleSolutions;\n}\n\nfunction customizeModuleIsMissingMessage(error: Error) {\n error.message = `Your JavaScript code tried to access a native module that doesn't exist in this development client. \n\n${moduleIsMissingPossibleSolutions}`;\n}\n\nfunction customizeError(error: Error | CodedError) {\n if ('code' in error) {\n // It's a CodedError from expo modules\n switch (error.code) {\n case 'ERR_UNAVAILABLE': {\n customizeUnavailableMessage(error);\n break;\n }\n }\n } else if (\n error.message.includes('Native module cannot be null') || // RN 0.64 and below message\n error.message.includes('`new NativeEventEmitter()` requires a non-null argument.') // RN 0.65+ message\n ) {\n customizeModuleIsMissingMessage(error);\n }\n}\n\nfunction errorHandler(originalHandler, error, isFatal) {\n if (error instanceof Error) {\n // Suppresses `\"main\" has not been registered` error only if it was caused by a different error.\n // Otherwise, we want to show it, cause the user may forget to call `AppRegistry.registerComponent`.\n if (wasHit && error.message?.includes('has not been registered. This can happen if')) {\n return;\n }\n customizeError(error);\n }\n\n wasHit = true;\n originalHandler(error, isFatal);\n}\n\n/**\n * @hidden\n */\nexport function createErrorHandler(originalHandler) {\n return (error, isFatal) => {\n if (isErrorHandlingEnabled) {\n errorHandler(originalHandler, error, isFatal);\n return;\n }\n\n originalHandler(error, isFatal);\n };\n}\n\n/**\n * @hidden\n */\nexport function disableErrorHandling() {\n isErrorHandlingEnabled = false;\n}\n"]}
1
+ {"version":3,"file":"DevLauncherErrorManager.js","sourceRoot":"","sources":["../src/DevLauncherErrorManager.ts"],"names":[],"mappings":"AAGA,IAAI,sBAAsB,GAAG,IAAI,CAAC;AAClC,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,gDAAgD;AAEpE,MAAM,iCAAiC,GAAG;;;;mGAIyD,CAAC;AAEpG,MAAM,gCAAgC,GAAG;;;mGAG0D,CAAC;AAEpG,SAAS,2BAA2B,CAAC,KAAiB;IACpD,KAAK,CAAC,OAAO,IAAI,MAAM,GAAG,iCAAiC,CAAC;AAC9D,CAAC;AAED,SAAS,+BAA+B,CAAC,KAAY;IACnD,KAAK,CAAC,OAAO,GAAG;;EAEhB,gCAAgC,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB;IAC/C,IAAI,MAAM,IAAI,KAAK,EAAE;QACnB,sCAAsC;QACtC,QAAQ,KAAK,CAAC,IAAI,EAAE;YAClB,KAAK,iBAAiB,CAAC,CAAC;gBACtB,2BAA2B,CAAC,KAAK,CAAC,CAAC;gBACnC,MAAM;aACP;SACF;KACF;SAAM,IACL,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CAAC,IAAI,4BAA4B;QACtF,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,0DAA0D,CAAC,CAAC,mBAAmB;MACtG;QACA,+BAA+B,CAAC,KAAK,CAAC,CAAC;KACxC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,eAAe,EAAE,KAAK,EAAE,OAAO;IACnD,IAAI,KAAK,YAAY,KAAK,EAAE;QAC1B,gGAAgG;QAChG,oGAAoG;QACpG,IAAI,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,6CAA6C,CAAC,EAAE;YACpF,OAAO;SACR;QACD,cAAc,CAAC,KAAK,CAAC,CAAC;KACvB;IAED,MAAM,GAAG,IAAI,CAAC;IACd,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,eAAe;IAChD,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,sBAAsB,EAAE;YAC1B,YAAY,CAAC,eAAe,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO;SACR;QAED,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,sBAAsB,GAAG,KAAK,CAAC;AACjC,CAAC","sourcesContent":["// Similar interface to the one used in expo modules.\ntype CodedError = Error & { code?: string };\n\nlet isErrorHandlingEnabled = true;\nlet wasHit = false; // whether the original error handler was called\n\nconst unavailableErrorPossibleSolutions = `Some possible solutions:\n- Make sure that the method is available on the current platform.\n- Make sure you're using the newest available version of this development client.\n- Make sure you're running a compatible version of your JavaScript code.\n- If you've installed a new library recently, you may need to make a new development client build.`;\n\nconst moduleIsMissingPossibleSolutions = `Some possible solutions:\n- Make sure you're using the newest available version of this development client.\n- Make sure you're running a compatible version of your JavaScript code.\n- If you've installed a new library recently, you may need to make a new development client build.`;\n\nfunction customizeUnavailableMessage(error: CodedError) {\n error.message += '\\n\\n' + unavailableErrorPossibleSolutions;\n}\n\nfunction customizeModuleIsMissingMessage(error: Error) {\n error.message = `Your JavaScript code tried to access a native module that doesn't exist in this development client. \n\n${moduleIsMissingPossibleSolutions}`;\n}\n\nfunction customizeError(error: Error | CodedError) {\n if ('code' in error) {\n // It's a CodedError from expo modules\n switch (error.code) {\n case 'ERR_UNAVAILABLE': {\n customizeUnavailableMessage(error);\n break;\n }\n }\n } else if (\n error.message.includes('Native module cannot be null') || // RN 0.64 and below message\n error.message.includes('`new NativeEventEmitter()` requires a non-null argument.') // RN 0.65+ message\n ) {\n customizeModuleIsMissingMessage(error);\n }\n}\n\nfunction errorHandler(originalHandler, error, isFatal) {\n if (error instanceof Error) {\n // Suppresses `\"main\" has not been registered` error only if it was caused by a different error.\n // Otherwise, we want to show it, cause the user may forget to call `AppRegistry.registerComponent`.\n if (wasHit && error.message?.includes('has not been registered. This can happen if')) {\n return;\n }\n customizeError(error);\n }\n\n wasHit = true;\n originalHandler(error, isFatal);\n}\n\n/**\n * @hidden\n */\nexport function createErrorHandler(originalHandler) {\n return (error, isFatal) => {\n if (isErrorHandlingEnabled) {\n errorHandler(originalHandler, error, isFatal);\n return;\n }\n\n originalHandler(error, isFatal);\n };\n}\n\n/**\n * @hidden\n */\nexport function disableErrorHandling() {\n isErrorHandlingEnabled = false;\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-dev-launcher",
3
3
  "title": "Expo Development Launcher",
4
- "version": "4.0.0",
4
+ "version": "4.0.2",
5
5
  "description": "Pre-release version of the Expo development launcher package for testing.",
6
6
  "main": "build/DevLauncher.js",
7
7
  "types": "build/DevLauncher.d.ts",
@@ -31,7 +31,7 @@
31
31
  "homepage": "https://docs.expo.dev",
32
32
  "dependencies": {
33
33
  "ajv": "8.11.0",
34
- "expo-dev-menu": "5.0.0",
34
+ "expo-dev-menu": "5.0.2",
35
35
  "expo-manifests": "~0.14.0",
36
36
  "resolve-from": "^5.0.0",
37
37
  "semver": "^7.6.0"
@@ -52,7 +52,7 @@
52
52
  "graphql": "^16.0.1",
53
53
  "graphql-request": "^3.6.1",
54
54
  "react": "18.2.0",
55
- "react-native": "0.74.0-rc.9",
55
+ "react-native": "0.74.0",
56
56
  "react-query": "^3.34.16",
57
57
  "url": "^0.11.0"
58
58
  },
@@ -66,5 +66,5 @@
66
66
  "./setupTests.ts"
67
67
  ]
68
68
  },
69
- "gitHead": "4165b8d72e1b9a1889c2767534cc619e21468110"
69
+ "gitHead": "0897aeadb926491a457bcd67d83360956994ee82"
70
70
  }
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.validateConfig = validateConfig;
6
+ exports.validateConfig = void 0;
7
7
  const ajv_1 = __importDefault(require("ajv"));
8
8
  const schema = {
9
9
  type: 'object',
@@ -67,6 +67,7 @@ function validateConfig(config) {
67
67
  }
68
68
  return config;
69
69
  }
70
+ exports.validateConfig = validateConfig;
70
71
  const warnMap = {};
71
72
  function warnOnce(message) {
72
73
  if (!warnMap[message]) {
@@ -1,286 +0,0 @@
1
- package expo.modules.devlauncher.rncompatibility
2
-
3
- import android.content.Context
4
- import android.os.Handler
5
- import android.os.Looper
6
- import android.util.Log
7
- import android.widget.Toast
8
- import com.facebook.common.logging.FLog
9
- import com.facebook.debug.holder.PrinterHolder
10
- import com.facebook.debug.tags.ReactDebugOverlayTags
11
- import com.facebook.infer.annotation.Assertions
12
- import com.facebook.react.R
13
- import com.facebook.react.bridge.JSBundleLoader
14
- import com.facebook.react.bridge.JavaJSExecutor
15
- import com.facebook.react.bridge.ReactMarker
16
- import com.facebook.react.bridge.ReactMarkerConstants
17
- import com.facebook.react.bridge.UiThreadUtil
18
- import com.facebook.react.common.ReactConstants
19
- import com.facebook.react.common.futures.SimpleSettableFuture
20
- import com.facebook.react.devsupport.DevLauncherInternalSettingsWrapper
21
- import com.facebook.react.devsupport.DevSupportManagerBase
22
- import com.facebook.react.devsupport.HMRClient
23
- import com.facebook.react.devsupport.ReactInstanceDevHelper
24
- import com.facebook.react.devsupport.WebsocketJavaScriptExecutor
25
- import com.facebook.react.devsupport.WebsocketJavaScriptExecutor.JSExecutorConnectCallback
26
- import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener
27
- import com.facebook.react.devsupport.interfaces.DevSplitBundleCallback
28
- import com.facebook.react.devsupport.interfaces.RedBoxHandler
29
- import com.facebook.react.packagerconnection.RequestHandler
30
- import expo.modules.devlauncher.DevLauncherController
31
- import expo.modules.devlauncher.koin.DevLauncherKoinComponent
32
- import expo.modules.devlauncher.koin.optInject
33
- import expo.modules.devlauncher.launcher.DevLauncherControllerInterface
34
- import expo.modules.devlauncher.launcher.errors.DevLauncherAppError
35
- import expo.modules.devlauncher.launcher.errors.DevLauncherErrorActivity
36
-
37
- import java.io.File
38
- import java.io.IOException
39
- import java.util.concurrent.ExecutionException
40
- import java.util.concurrent.TimeUnit
41
- import java.util.concurrent.TimeoutException
42
-
43
- class DevLauncherDevSupportManager(
44
- applicationContext: Context?,
45
- val reactInstanceManagerHelper: ReactInstanceDevHelper?,
46
- packagerPathForJSBundleName: String?,
47
- enableOnCreate: Boolean,
48
- redBoxHandler: RedBoxHandler?,
49
- devBundleDownloadListener: DevBundleDownloadListener?,
50
- minNumShakes: Int,
51
- customPackagerCommandHandlers: MutableMap<String, RequestHandler>?
52
- ) : DevSupportManagerBase(
53
- applicationContext,
54
- reactInstanceManagerHelper,
55
- packagerPathForJSBundleName,
56
- enableOnCreate,
57
- redBoxHandler,
58
- devBundleDownloadListener,
59
- minNumShakes,
60
- customPackagerCommandHandlers,
61
- null,
62
- null
63
- ),
64
- DevLauncherKoinComponent {
65
- private val controller: DevLauncherControllerInterface? by optInject()
66
-
67
- // copied from https://github.com/facebook/react-native/blob/aa4da248c12e3ba41ecc9f1c547b21c208d9a15f/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java#L65
68
- private var mIsSamplingProfilerEnabled = false
69
- private val devSettings: DevLauncherInternalSettingsWrapper = DevLauncherInternalSettingsWrapper(getDevSettings())
70
-
71
- // copied from https://github.com/facebook/react-native/blob/aa4da248c12e3ba41ecc9f1c547b21c208d9a15f/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java#L88-L128
72
- init {
73
- if (devSettings.isStartSamplingProfilerOnInit) {
74
- // Only start the profiler. If its already running, there is an error
75
- if (!mIsSamplingProfilerEnabled) {
76
- toggleJSSamplingProfiler()
77
- } else {
78
- Toast.makeText(
79
- applicationContext,
80
- "JS Sampling Profiler was already running, so did not start the sampling profiler",
81
- Toast.LENGTH_LONG
82
- )
83
- .show()
84
- }
85
- }
86
-
87
- addCustomDevOption(
88
- applicationContext!!.getString(R.string.catalyst_sample_profiler_toggle)
89
- ) { toggleJSSamplingProfiler() }
90
- }
91
-
92
- override fun showNewJavaError(message: String?, e: Throwable) {
93
- Log.e("DevLauncher", "$message", e)
94
- if (!DevLauncherController.wasInitialized()) {
95
- Log.e("DevLauncher", "DevLauncher wasn't initialized. Couldn't intercept native error handling.")
96
- super.showNewJavaError(message, e)
97
- return
98
- }
99
-
100
- val activity = reactInstanceManagerHelper?.currentActivity
101
- if (activity == null || activity.isFinishing || activity.isDestroyed) {
102
- return
103
- }
104
-
105
- controller?.onAppLoadedWithError()
106
- DevLauncherErrorActivity.showError(activity, DevLauncherAppError(message, e))
107
- }
108
-
109
- // copied from https://github.com/facebook/react-native/blob/aa4da248c12e3ba41ecc9f1c547b21c208d9a15f/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java#L131-L134
110
- override fun getUniqueTag() = "DevLauncherApp - Bridge"
111
-
112
- // copied from https://github.com/facebook/react-native/blob/aa4da248c12e3ba41ecc9f1c547b21c208d9a15f/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java#L136-L156
113
- override fun loadSplitBundleFromServer(
114
- bundlePath: String?,
115
- callback: DevSplitBundleCallback
116
- ) {
117
- fetchSplitBundleAndCreateBundleLoader(
118
- bundlePath,
119
- object : CallbackWithBundleLoader {
120
- override fun onSuccess(bundleLoader: JSBundleLoader) {
121
- bundleLoader.loadScript(currentContext!!.catalystInstance)
122
- var bundleURL = controller?.manifest?.getBundleURL() ?: devServerHelper.getDevServerSplitBundleURL(bundlePath)
123
- currentContext!!
124
- .getJSModule(HMRClient::class.java)
125
- .registerBundle(bundleURL)
126
- callback.onSuccess()
127
- }
128
-
129
- override fun onError(url: String, cause: Throwable) {
130
- callback.onError(url, cause)
131
- }
132
- }
133
- )
134
- }
135
-
136
- override fun startInspector() {
137
- // no-op for the default `startInspector` which would be implicitly called
138
- // right after `ReactInstanceManager` construction.
139
- // For dev-launcher, we should inject the correct dev server address and
140
- // call our customized `startInspectorWhenDevLauncherReady`.
141
- // Check `DevLauncherReactUtils.injectReactInterceptor()` for details.
142
- }
143
-
144
- fun startInspectorWhenDevLauncherReady() {
145
- super.startInspector()
146
- }
147
-
148
- // copied from https://github.com/facebook/react-native/blob/aa4da248c12e3ba41ecc9f1c547b21c208d9a15f/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java#L158-L165
149
- private fun getExecutorConnectCallback(
150
- future: SimpleSettableFuture<Boolean>
151
- ): JSExecutorConnectCallback {
152
- return object : JSExecutorConnectCallback {
153
- override fun onSuccess() {
154
- future.set(true)
155
- hideDevLoadingView()
156
- }
157
-
158
- override fun onFailure(cause: Throwable) {
159
- hideDevLoadingView()
160
- FLog.e(ReactConstants.TAG, "Failed to connect to debugger!", cause)
161
- future.setException(
162
- IOException(
163
- applicationContext.getString(R.string.catalyst_debug_error),
164
- cause
165
- )
166
- )
167
- }
168
- }
169
- }
170
-
171
- // copied from https://github.com/facebook/react-native/blob/aa4da248c12e3ba41ecc9f1c547b21c208d9a15f/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java#L179-L204
172
- private fun reloadJSInProxyMode() {
173
- // When using js proxy, there is no need to fetch JS bundle as proxy executor will do that
174
- // anyway
175
- devServerHelper.launchJSDevtools()
176
- val factory = JavaJSExecutor.Factory {
177
- val executor = WebsocketJavaScriptExecutor()
178
- val future = SimpleSettableFuture<Boolean>()
179
- executor.connect(
180
- devServerHelper.websocketProxyURL,
181
- getExecutorConnectCallback(future)
182
- )
183
- // TODO(t9349129) Don't use timeout
184
- try {
185
- future[90, TimeUnit.SECONDS]
186
- return@Factory executor
187
- } catch (e: ExecutionException) {
188
- throw (e.cause as Exception)
189
- } catch (e: InterruptedException) {
190
- throw RuntimeException(e)
191
- } catch (e: TimeoutException) {
192
- throw RuntimeException(e)
193
- }
194
- }
195
- reactInstanceDevHelper.onReloadWithJSDebugger(factory)
196
- }
197
-
198
- // copied from https://github.com/facebook/react-native/blob/aa4da248c12e3ba41ecc9f1c547b21c208d9a15f/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java#L206-L231
199
- override fun handleReloadJS() {
200
- UiThreadUtil.assertOnUiThread()
201
- ReactMarker.logMarker(
202
- ReactMarkerConstants.RELOAD,
203
- devSettings.packagerConnectionSettings.debugServerHost
204
- )
205
-
206
- // dismiss redbox if exists
207
- hideRedboxDialog()
208
- if (devSettings.isRemoteJSDebugEnabled) {
209
- PrinterHolder.getPrinter()
210
- .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from Proxy")
211
- showDevLoadingViewForRemoteJSEnabled()
212
- reloadJSInProxyMode()
213
- } else {
214
- PrinterHolder.getPrinter()
215
- .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from Server")
216
- val bundleURL = controller?.manifest?.getBundleURL() ?: devServerHelper
217
- .getDevServerBundleURL(Assertions.assertNotNull(jsAppBundleName))
218
- reloadJSFromServer(bundleURL)
219
- }
220
- }
221
-
222
- // copied from https://github.com/facebook/react-native/blob/aa4da248c12e3ba41ecc9f1c547b21c208d9a15f/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java#L233-L277
223
- /** Starts of stops the sampling profiler */
224
- private fun toggleJSSamplingProfiler() {
225
- val handler = Handler(Looper.getMainLooper())
226
- val javaScriptExecutorFactory = reactInstanceDevHelper.javaScriptExecutorFactory
227
- if (!mIsSamplingProfilerEnabled) {
228
- try {
229
- javaScriptExecutorFactory.startSamplingProfiler()
230
- handler.post {
231
- Toast.makeText(applicationContext, "Starting Sampling Profiler", Toast.LENGTH_SHORT)
232
- .show()
233
- }
234
- } catch (e: UnsupportedOperationException) {
235
- handler.post {
236
- Toast.makeText(
237
- applicationContext,
238
- javaScriptExecutorFactory.toString() + " does not support Sampling Profiler",
239
- Toast.LENGTH_LONG
240
- )
241
- .show()
242
- }
243
- } finally {
244
- mIsSamplingProfilerEnabled = true
245
- }
246
- } else {
247
- try {
248
- val outputPath: String = File.createTempFile(
249
- "sampling-profiler-trace",
250
- ".cpuprofile",
251
- applicationContext.cacheDir
252
- ).path
253
- javaScriptExecutorFactory.stopSamplingProfiler(outputPath)
254
- handler.post {
255
- Toast.makeText(
256
- applicationContext,
257
- "Saved results from Profiler to $outputPath",
258
- Toast.LENGTH_LONG
259
- )
260
- .show()
261
- }
262
- } catch (e: IOException) {
263
- FLog.e(
264
- ReactConstants.TAG,
265
- "Could not create temporary file for saving results from Sampling Profiler",
266
- e
267
- )
268
- } catch (e: UnsupportedOperationException) {
269
- handler.post {
270
- Toast.makeText(
271
- applicationContext,
272
- javaScriptExecutorFactory.toString() + " does not support Sampling Profiler",
273
- Toast.LENGTH_LONG
274
- )
275
- .show()
276
- }
277
- } finally {
278
- mIsSamplingProfilerEnabled = false
279
- }
280
- }
281
- }
282
-
283
- companion object {
284
- fun getDevHelperInternalFieldName() = "mReactInstanceDevHelper"
285
- }
286
- }