expo-modules-core 3.0.10 → 3.0.12

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 (38) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/cpp/JavaCallback.h +1 -1
  4. package/android/src/main/cpp/MethodMetadata.cpp +1 -1
  5. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +10 -3
  6. package/android/src/main/java/expo/modules/kotlin/defaultmodules/JSLoggerModule.kt +92 -0
  7. package/build/index.d.ts +1 -1
  8. package/build/index.d.ts.map +1 -1
  9. package/build/requireNativeModule.d.ts.map +1 -1
  10. package/build/sweet/NativeJSLogger.d.ts +3 -0
  11. package/build/sweet/NativeJSLogger.d.ts.map +1 -0
  12. package/build/sweet/setUpJsLogger.fx.d.ts +2 -0
  13. package/build/sweet/setUpJsLogger.fx.d.ts.map +1 -0
  14. package/build/sweet/setUpJsLogger.fx.web.d.ts +2 -0
  15. package/build/sweet/setUpJsLogger.fx.web.d.ts.map +1 -0
  16. package/common/cpp/fabric/ExpoViewShadowNode.cpp +9 -0
  17. package/ios/Core/AppContext.swift +11 -0
  18. package/ios/Core/Modules/JSLoggerModule.swift +65 -0
  19. package/ios/Core/Views/SwiftUI/ExpoSystemColors.swift +1 -1
  20. package/ios/Core/Views/SwiftUI/SwiftUIViewDefinition.swift +5 -0
  21. package/ios/Core/Views/SwiftUI/SwiftUIViewProps.swift +2 -0
  22. package/ios/JSI/EXJSIConversions.mm +1 -1
  23. package/ios/Tests/JavaScriptRuntimeSpec.swift +5 -5
  24. package/package.json +3 -3
  25. package/src/index.ts +1 -1
  26. package/src/requireNativeModule.ts +12 -6
  27. package/src/sweet/NativeJSLogger.ts +3 -0
  28. package/src/sweet/setUpJsLogger.fx.ts +56 -0
  29. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +0 -34
  30. package/build/sweet/NativeErrorManager.d.ts +0 -3
  31. package/build/sweet/NativeErrorManager.d.ts.map +0 -1
  32. package/build/sweet/setUpErrorManager.fx.d.ts +0 -2
  33. package/build/sweet/setUpErrorManager.fx.d.ts.map +0 -1
  34. package/build/sweet/setUpErrorManager.fx.web.d.ts +0 -2
  35. package/build/sweet/setUpErrorManager.fx.web.d.ts.map +0 -1
  36. package/src/sweet/NativeErrorManager.ts +0 -2
  37. package/src/sweet/setUpErrorManager.fx.ts +0 -23
  38. /package/src/sweet/{setUpErrorManager.fx.web.ts → setUpJsLogger.fx.web.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -10,6 +10,30 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 3.0.12 — 2025-09-03
14
+
15
+ ### 💡 Others
16
+
17
+ - Use new LongLivedObject.h and CallbackWrapper.h headers namespace ([#39344](https://github.com/expo/expo/pull/39344) by [@gabrieldonadel](https://github.com/gabrieldonadel))
18
+
19
+ ## 3.0.11 — 2025-09-02
20
+
21
+ ### 🎉 New features
22
+
23
+ - Add `disableForceFlatten` prop to control flattening of display contents views. ([#39262](https://github.com/expo/expo/pull/39262) by [@nishan](https://github.com/intergalacticspacehighway))
24
+ - Add logging from native to JS, compliant with the Logger interface, via `appContext.jsLogger`. ([#39159](https://github.com/expo/expo/pull/39159) by [@behenate](https://github.com/behenate))
25
+
26
+ ### 🐛 Bug fixes
27
+
28
+ - Fix Color extension on macOS. ([#39280](https://github.com/expo/expo/pull/39280) by [@gabrieldonadel](https://github.com/gabrieldonadel))
29
+ - Fix ErrorManager not receiving events. ([#39290](https://github.com/expo/expo/pull/39290) by [@behenate](https://github.com/behenate))
30
+
31
+ ### 💡 Others
32
+
33
+ - Fix JavaScriptRuntimeSpec tests ([#39281](https://github.com/expo/expo/pull/39281) by [@gabrieldonadel](https://github.com/gabrieldonadel))
34
+ - Added `appContext` to `ExpoSwiftUI.ViewProps`. ([#39231](https://github.com/expo/expo/pull/39231) by [@kudo](https://github.com/kudo))
35
+ - `requireOptionalNativeModule` will now catch errors which occur while requiring a module. ([#39290](https://github.com/expo/expo/pull/39290) by [@behenate](https://github.com/behenate))
36
+
13
37
  ## 3.0.10 — 2025-08-31
14
38
 
15
39
  _This version does not introduce any user-facing changes._
@@ -25,7 +25,7 @@ if (shouldIncludeCompose) {
25
25
  }
26
26
 
27
27
  group = 'host.exp.exponent'
28
- version = '3.0.10'
28
+ version = '3.0.12'
29
29
 
30
30
  def isExpoModulesCoreTests = {
31
31
  Gradle gradle = getGradle()
@@ -75,7 +75,7 @@ android {
75
75
  defaultConfig {
76
76
  consumerProguardFiles 'proguard-rules.pro'
77
77
  versionCode 1
78
- versionName "3.0.10"
78
+ versionName "3.0.12"
79
79
  buildConfigField "String", "EXPO_MODULES_CORE_VERSION", "\"${versionName}\""
80
80
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
81
81
 
@@ -14,7 +14,7 @@
14
14
  #include <react/jni/WritableNativeMap.h>
15
15
  #include <fbjni/detail/CoreClasses.h>
16
16
  #include <ReactCommon/CallInvoker.h>
17
- #include <ReactCommon/LongLivedObject.h>
17
+ #include <react/bridging/LongLivedObject.h>
18
18
 
19
19
  namespace jni = facebook::jni;
20
20
  namespace react = facebook::react;
@@ -14,7 +14,7 @@
14
14
  #include <unistd.h>
15
15
  #include <optional>
16
16
 
17
- #include <ReactCommon/LongLivedObject.h>
17
+ #include <react/bridging/LongLivedObject.h>
18
18
 
19
19
  namespace jni = facebook::jni;
20
20
  namespace jsi = facebook::jsi;
@@ -29,6 +29,7 @@ import expo.modules.kotlin.activityresult.DefaultAppContextActivityResultCaller
29
29
  import expo.modules.kotlin.defaultmodules.AppDirectoriesModule
30
30
  import expo.modules.kotlin.defaultmodules.ErrorManagerModule
31
31
  import expo.modules.kotlin.defaultmodules.FilePermissionModule
32
+ import expo.modules.kotlin.defaultmodules.JSLoggerModule
32
33
  import expo.modules.kotlin.defaultmodules.NativeModulesProxyModule
33
34
  import expo.modules.kotlin.events.EventEmitter
34
35
  import expo.modules.kotlin.events.EventName
@@ -109,8 +110,8 @@ class AppContext(
109
110
  // Registering modules has to happen at the very end of `AppContext` creation. Some modules need to access
110
111
  // `AppContext` during their initialisation, so we need to ensure all `AppContext`'s
111
112
  // properties are initialized first. Not having that would trigger NPE.
112
- registry.register(ErrorManagerModule())
113
113
  registry.register(NativeModulesProxyModule())
114
+ registry.register(JSLoggerModule())
114
115
 
115
116
  // Registering modules that were previously provided by legacy FileSystem module.
116
117
  legacyModuleRegistry.registerInternalModule(FilePermissionModule())
@@ -248,8 +249,14 @@ class AppContext(
248
249
  return KEventEmitterWrapper(legacyEventEmitter, hostingRuntimeContext.reactContextHolder)
249
250
  }
250
251
 
251
- val errorManager: ErrorManagerModule?
252
- get() = hostingRuntimeContext.registry.getModule()
252
+ @Deprecated("Use AppContext.jsLogger instead")
253
+ val errorManager: ErrorManagerModule? by lazy {
254
+ hostingRuntimeContext.registry.getModule()
255
+ }
256
+
257
+ val jsLogger by lazy {
258
+ hostingRuntimeContext.registry.getModule<JSLoggerModule>()?.logger
259
+ }
253
260
 
254
261
  internal fun onDestroy() = trace("AppContext.onDestroy") {
255
262
  hostingRuntimeContext.reactContext?.removeLifecycleEventListener(reactLifecycleDelegate)
@@ -0,0 +1,92 @@
1
+ package expo.modules.kotlin.defaultmodules
2
+
3
+ import android.os.Bundle
4
+ import expo.modules.core.logging.LogHandler
5
+ import expo.modules.core.logging.LogType
6
+ import expo.modules.core.logging.Logger
7
+ import expo.modules.kotlin.exception.CodedException
8
+ import expo.modules.kotlin.modules.Module
9
+ import expo.modules.kotlin.modules.ModuleDefinition
10
+ import java.lang.ref.WeakReference
11
+
12
+ private const val moduleName = "ExpoModulesCoreJSLogger"
13
+ private const val onNewError = "$moduleName.onNewError"
14
+ private const val onNewWarning = "$moduleName.onNewWarning"
15
+ private const val onNewDebug = "$moduleName.onNewDebug"
16
+ private const val onNewInfo = "$moduleName.onNewInfo"
17
+ private const val onNewTrace = "$moduleName.onNewTrace"
18
+
19
+ @Deprecated("Use JSLoggerModule instead")
20
+ typealias ErrorManagerModule = JSLoggerModule
21
+
22
+ class JSLoggerModule : Module() {
23
+ private class JSLogHandler(module: JSLoggerModule) : LogHandler() {
24
+ private val moduleReference = WeakReference(module)
25
+
26
+ override fun log(type: LogType, message: String, cause: Throwable?) {
27
+ val finalMessage = if (cause != null) {
28
+ "$message. ${cause.message}"
29
+ } else {
30
+ message
31
+ }
32
+ moduleReference.get()?.reportToLogBox(type, finalMessage)
33
+ }
34
+ }
35
+
36
+ var logger: Logger? = null
37
+ private set
38
+
39
+ override fun definition() = ModuleDefinition {
40
+ Name(moduleName)
41
+
42
+ Events(onNewError, onNewWarning, onNewDebug, onNewInfo, onNewTrace)
43
+
44
+ OnCreate {
45
+ val logHandler = JSLogHandler(this@JSLoggerModule)
46
+ logger = Logger(listOf(logHandler))
47
+ }
48
+ }
49
+
50
+ @Deprecated("Use appContext.jsLogger.warn(...) instead")
51
+ fun reportWarningToLogBox(warning: String) {
52
+ sendEvent(
53
+ onNewWarning,
54
+ createMessageBundle(warning)
55
+ )
56
+ }
57
+
58
+ @Deprecated("Use appContext.jsLogger.error(...) instead")
59
+ fun reportExceptionToLogBox(codedException: CodedException) {
60
+ sendEvent(
61
+ onNewError,
62
+ createMessageBundle(codedException.message ?: codedException.toString())
63
+ )
64
+ }
65
+
66
+ private fun createMessageBundle(message: String): Bundle {
67
+ return Bundle().apply {
68
+ putString("message", message)
69
+ }
70
+ }
71
+
72
+ private fun reportToLogBox(type: LogType, message: String) {
73
+ sendEvent(
74
+ type.eventName,
75
+ Bundle().apply {
76
+ putString("message", message)
77
+ }
78
+ )
79
+ }
80
+ }
81
+
82
+ private val LogType.eventName: String
83
+ get() = when (this) {
84
+ LogType.Trace -> onNewTrace
85
+ LogType.Timer -> onNewDebug
86
+ LogType.Stacktrace -> onNewTrace
87
+ LogType.Debug -> onNewDebug
88
+ LogType.Info -> onNewInfo
89
+ LogType.Warn -> onNewWarning
90
+ LogType.Error -> onNewError
91
+ LogType.Fatal -> onNewError
92
+ }
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import './sweet/setUpErrorManager.fx';
1
+ import './sweet/setUpJsLogger.fx';
2
2
  import './polyfill';
3
3
  export type * from './ts-declarations/global';
4
4
  export { EventEmitter, type EventSubscription } from './EventEmitter';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,8BAA8B,CAAC;AACtC,OAAO,YAAY,CAAC;AAEpB,mBAAmB,0BAA0B,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEzC,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AAEpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAElC,cAAc,QAAQ,CAAC;AAEvB,cAAc,kCAAkC,CAAC;AACjD,cAAc,UAAU,CAAC;AAGzB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,0BAA0B,CAAC;AAClC,OAAO,YAAY,CAAC;AAEpB,mBAAmB,0BAA0B,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEzC,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AAEpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAElC,cAAc,QAAQ,CAAC;AAEvB,cAAc,kCAAkC,CAAC;AACjD,cAAc,UAAU,CAAC;AAGzB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"requireNativeModule.d.ts","sourceRoot":"","sources":["../src/requireNativeModule.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,GAAG,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAOpF;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,GAAG,GAAG,EAC1D,UAAU,EAAE,MAAM,GACjB,UAAU,GAAG,IAAI,CASnB"}
1
+ {"version":3,"file":"requireNativeModule.d.ts","sourceRoot":"","sources":["../src/requireNativeModule.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,GAAG,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAOpF;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,GAAG,GAAG,EAC1D,UAAU,EAAE,MAAM,GACjB,UAAU,GAAG,IAAI,CAenB"}
@@ -0,0 +1,3 @@
1
+ declare const _default: any;
2
+ export default _default;
3
+ //# sourceMappingURL=NativeJSLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeJSLogger.d.ts","sourceRoot":"","sources":["../../src/sweet/NativeJSLogger.ts"],"names":[],"mappings":";AAEA,wBAAsE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=setUpJsLogger.fx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setUpJsLogger.fx.d.ts","sourceRoot":"","sources":["../../src/sweet/setUpJsLogger.fx.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=setUpJsLogger.fx.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setUpJsLogger.fx.web.d.ts","sourceRoot":"","sources":["../../src/sweet/setUpJsLogger.fx.web.ts"],"names":[],"mappings":""}
@@ -31,6 +31,15 @@ void ExpoViewShadowNode::initialize() noexcept {
31
31
  } else {
32
32
  traits_.unset(react::ShadowNodeTraits::Trait::ChildrenFormStackingContext);
33
33
  }
34
+
35
+ if (YGNodeStyleGetDisplay(&yogaNode_) == YGDisplayContents) {
36
+ auto it = viewProps.propsMap.find("disableForceFlatten");
37
+ bool disableForceFlatten = (it != viewProps.propsMap.end()) ? it->second.getBool() : false;
38
+
39
+ if (disableForceFlatten) {
40
+ traits_.unset(react::ShadowNodeTraits::Trait::ForceFlattenView);
41
+ }
42
+ }
34
43
  }
35
44
 
36
45
  } // namespace expo
@@ -17,6 +17,15 @@ public final class AppContext: NSObject {
17
17
  */
18
18
  public let config: AppContextConfig
19
19
 
20
+ public lazy var jsLogger: Logger = {
21
+ let loggerModule = self.moduleRegistry.get(moduleWithName: JSLoggerModule.name) as? JSLoggerModule
22
+ guard let logger = loggerModule?.logger else {
23
+ log.error("Failed to get the JSLoggerModule logger. Falling back to OS logger.")
24
+ return log
25
+ }
26
+ return logger
27
+ }()
28
+
20
29
  /**
21
30
  The module registry for the app context.
22
31
  */
@@ -126,6 +135,8 @@ public final class AppContext: NSObject {
126
135
  self.config = config ?? AppContextConfig(documentDirectory: nil, cacheDirectory: nil, appGroups: appCodeSignEntitlements.appGroups)
127
136
 
128
137
  super.init()
138
+
139
+ self.moduleRegistry.register(module: JSLoggerModule(appContext: self))
129
140
  listenToClientAppNotifications()
130
141
  }
131
142
 
@@ -0,0 +1,65 @@
1
+ private let onNewError = "\(JSLoggerModule.name).onNewError"
2
+ private let onNewWarning = "\(JSLoggerModule.name).onNewWarning"
3
+ private let onNewDebug = "\(JSLoggerModule.name).onNewDebug"
4
+ private let onNewInfo = "\(JSLoggerModule.name).onNewInfo"
5
+ private let onNewTrace = "\(JSLoggerModule.name).onNewTrace"
6
+
7
+ public final class JSLoggerModule: Module {
8
+ public static let name = "ExpoModulesCoreJSLogger"
9
+
10
+ // We could have made the JSLoggerModule implement the LogHandler interface, but the Logger
11
+ // holds a strong reference to the LogHandlers, which would lead to a reference cycle.
12
+ private class JSLogHandler: LogHandler {
13
+ weak var module: JSLoggerModule?
14
+
15
+ init(module: JSLoggerModule) {
16
+ self.module = module
17
+ }
18
+
19
+ func log(type: LogType, _ message: String) {
20
+ module?.reportToLogBox(type: type, message)
21
+ }
22
+ }
23
+
24
+ public var logger: Logger?
25
+
26
+ public func definition() -> ModuleDefinition {
27
+ Name(Self.name)
28
+
29
+ Events(onNewError, onNewWarning, onNewDebug, onNewInfo, onNewTrace)
30
+
31
+ OnCreate {
32
+ let logHandler = JSLogHandler(module: self)
33
+ self.logger = Logger(logHandlers: [logHandler])
34
+ }
35
+ }
36
+
37
+ private func reportToLogBox(type: LogType, _ message: String) {
38
+ self.sendEvent(type.eventName, [
39
+ "message": message
40
+ ])
41
+ }
42
+ }
43
+
44
+ private extension LogType {
45
+ var eventName: String {
46
+ switch self {
47
+ case .trace:
48
+ onNewTrace
49
+ case .timer:
50
+ onNewDebug
51
+ case .stacktrace:
52
+ onNewTrace
53
+ case .debug:
54
+ onNewDebug
55
+ case .info:
56
+ onNewInfo
57
+ case .warn:
58
+ onNewWarning
59
+ case .error:
60
+ onNewError
61
+ case .fatal:
62
+ onNewError
63
+ }
64
+ }
65
+ }
@@ -5,7 +5,7 @@ import SwiftUI
5
5
  // Wrap system colors to hide platform differences
6
6
 
7
7
  public extension Color {
8
- #if os(tvOS)
8
+ #if os(tvOS) || os(macOS)
9
9
  private static let _systemGray6: Color = Color(.systemGray.withAlphaComponent(0.5))
10
10
  private static let _systemGray5: Color = Color(.systemGray.withAlphaComponent(0.6))
11
11
  private static let _systemGray4: Color = Color(.systemGray.withAlphaComponent(0.7))
@@ -65,6 +65,10 @@ public extension ExpoSwiftUIView {
65
65
  static func getDynamicType() -> AnyDynamicType {
66
66
  return DynamicSwiftUIViewType(innerType: Self.self)
67
67
  }
68
+
69
+ var appContext: AppContext? {
70
+ return props.appContext
71
+ }
68
72
  }
69
73
 
70
74
  extension ExpoSwiftUI {
@@ -88,6 +92,7 @@ extension ExpoSwiftUI {
88
92
  public override func createView(appContext: AppContext) -> AppleView? {
89
93
  #if RCT_NEW_ARCH_ENABLED
90
94
  let props = Props()
95
+ props.appContext = appContext
91
96
 
92
97
  if ViewType.self is WithHostingView.Type {
93
98
  let view = HostingView(viewType: ViewType.self, props: props, appContext: appContext)
@@ -17,6 +17,8 @@ extension ExpoSwiftUI {
17
17
  */
18
18
  @Field public var children: [any AnyChild]?
19
19
 
20
+ public internal(set) weak var appContext: AppContext?
21
+
20
22
  /**
21
23
  A global event dispatcher that allows views to call `view.dispatchEvent(_:payload)` directly
22
24
  */
@@ -1,6 +1,6 @@
1
1
  // Copyright 2018-present 650 Industries. All rights reserved.
2
2
 
3
- #import <ReactCommon/CallbackWrapper.h>
3
+ #import <react/bridging/CallbackWrapper.h>
4
4
  #import <ExpoModulesCore/EXJavaScriptValue.h>
5
5
  #import <ExpoModulesCore/EXJavaScriptObject.h>
6
6
  #import <ExpoModulesCore/EXJavaScriptWeakObject.h>
@@ -86,11 +86,11 @@ class JavaScriptRuntimeSpec: ExpoSpec {
86
86
  it("throws evaluation exception") {
87
87
  expect({ try runtime.eval("foo") }).to(throwError { error in
88
88
  expect(error).to(beAKindOf(JavaScriptEvalException.self))
89
- #if canImport(reacthermes)
90
- expect((error as! JavaScriptEvalException).reason).to(contain("Property 'foo' doesn't exist"))
91
- #else
92
- expect((error as! JavaScriptEvalException).reason).to(contain("Can't find variable: foo"))
93
- #endif
89
+ if runtime.global().hasProperty("HermesInternal") {
90
+ expect((error as! JavaScriptEvalException).reason).to(contain("Property 'foo' doesn't exist"))
91
+ } else {
92
+ expect((error as! JavaScriptEvalException).reason).to(contain("Can't find variable: foo"))
93
+ }
94
94
  })
95
95
  }
96
96
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "3.0.10",
3
+ "version": "3.0.12",
4
4
  "description": "The core of Expo Modules architecture",
5
5
  "main": "src/index.ts",
6
6
  "types": "build/index.d.ts",
@@ -63,7 +63,7 @@
63
63
  },
64
64
  "devDependencies": {
65
65
  "@testing-library/react-native": "^13.2.0",
66
- "expo-module-scripts": "^5.0.5"
66
+ "expo-module-scripts": "^5.0.6"
67
67
  },
68
- "gitHead": "1dafdaa317c182191909a94a355c8b08a2654783"
68
+ "gitHead": "f97e6d1cae0cb14d5eed1b08fad6d12a7144af3a"
69
69
  }
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import './sweet/setUpErrorManager.fx';
1
+ import './sweet/setUpJsLogger.fx';
2
2
  import './polyfill';
3
3
 
4
4
  export type * from './ts-declarations/global';
@@ -34,10 +34,16 @@ export function requireOptionalNativeModule<ModuleType = any>(
34
34
  ): ModuleType | null {
35
35
  ensureNativeModulesAreInstalled();
36
36
 
37
- return (
38
- globalThis.expo?.modules?.[moduleName] ??
39
- NativeModulesProxy[moduleName] ??
40
- createTurboModuleToExpoProxy(TurboModuleRegistry.get(moduleName), moduleName) ??
41
- null
42
- );
37
+ try {
38
+ return (
39
+ globalThis.expo?.modules?.[moduleName] ??
40
+ NativeModulesProxy[moduleName] ??
41
+ createTurboModuleToExpoProxy(TurboModuleRegistry.get(moduleName), moduleName) ??
42
+ null
43
+ );
44
+ } catch (e) {
45
+ const error = e as Error;
46
+ console.warn(`An error occurred while requiring the '${moduleName}' module: ${error.message}`);
47
+ return null;
48
+ }
43
49
  }
@@ -0,0 +1,3 @@
1
+ import { requireOptionalNativeModule } from '../requireNativeModule';
2
+
3
+ export default requireOptionalNativeModule('ExpoModulesCoreJSLogger');
@@ -0,0 +1,56 @@
1
+ import NativeJSLogger from './NativeJSLogger';
2
+ import Platform from '../Platform';
3
+ import { CodedError } from '../errors/CodedError';
4
+
5
+ type LogListener = {
6
+ action: (...data: any[]) => void;
7
+ eventName: string;
8
+ };
9
+
10
+ if (__DEV__ && (Platform.OS === 'android' || Platform.OS === 'ios') && NativeJSLogger) {
11
+ const onNewException: LogListener = {
12
+ eventName: 'ExpoModulesCoreJSLogger.onNewError',
13
+ action: console.error,
14
+ };
15
+
16
+ const onNewWarning: LogListener = {
17
+ eventName: 'ExpoModulesCoreJSLogger.onNewWarning',
18
+ action: console.warn,
19
+ };
20
+
21
+ const onNewDebug: LogListener = {
22
+ eventName: 'ExpoModulesCoreJSLogger.onNewDebug',
23
+ action: console.debug,
24
+ };
25
+
26
+ const onNewInfo: LogListener = {
27
+ eventName: 'ExpoModulesCoreJSLogger.onNewInfo',
28
+ action: console.info,
29
+ };
30
+
31
+ const onNewTrace: LogListener = {
32
+ eventName: 'ExpoModulesCoreJSLogger.onNewTrace',
33
+ action: console.trace,
34
+ };
35
+
36
+ const listeners: LogListener[] = [
37
+ onNewException,
38
+ onNewWarning,
39
+ onNewDebug,
40
+ onNewInfo,
41
+ onNewTrace,
42
+ ];
43
+
44
+ for (const listener of listeners) {
45
+ NativeJSLogger.addListener(listener.eventName, ({ message }: { message: string }) => {
46
+ listener.action(message);
47
+ });
48
+ }
49
+ }
50
+
51
+ declare namespace globalThis {
52
+ let ExpoModulesCore_CodedError: undefined | typeof CodedError;
53
+ }
54
+
55
+ // We have to export `CodedError` via global object to use in later in the C++ code.
56
+ globalThis.ExpoModulesCore_CodedError = CodedError;
@@ -1,34 +0,0 @@
1
- package expo.modules.kotlin.defaultmodules
2
-
3
- import android.os.Bundle
4
- import expo.modules.kotlin.exception.CodedException
5
- import expo.modules.kotlin.modules.Module
6
- import expo.modules.kotlin.modules.ModuleDefinition
7
-
8
- private const val onNewException = "ExpoModulesCoreErrorManager.onNewException"
9
- private const val onNewWarning = "ExpoModulesCoreErrorManager.onNewWarning"
10
-
11
- class ErrorManagerModule : Module() {
12
- override fun definition() = ModuleDefinition {
13
- Name("ExpoModulesCoreErrorManager")
14
- Events(onNewException, onNewWarning)
15
- }
16
-
17
- fun reportExceptionToLogBox(codedException: CodedException) {
18
- sendEvent(
19
- onNewException,
20
- Bundle().apply {
21
- putString("message", codedException.message ?: codedException.toString())
22
- }
23
- )
24
- }
25
-
26
- fun reportWarningToLogBox(warning: String) {
27
- sendEvent(
28
- onNewWarning,
29
- Bundle().apply {
30
- putString("message", warning)
31
- }
32
- )
33
- }
34
- }
@@ -1,3 +0,0 @@
1
- declare const _default: import("..").ProxyNativeModule;
2
- export default _default;
3
- //# sourceMappingURL=NativeErrorManager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NativeErrorManager.d.ts","sourceRoot":"","sources":["../../src/sweet/NativeErrorManager.ts"],"names":[],"mappings":";AACA,wBAA8D"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=setUpErrorManager.fx.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"setUpErrorManager.fx.d.ts","sourceRoot":"","sources":["../../src/sweet/setUpErrorManager.fx.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=setUpErrorManager.fx.web.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"setUpErrorManager.fx.web.d.ts","sourceRoot":"","sources":["../../src/sweet/setUpErrorManager.fx.web.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- import NativeModulesProxy from '../NativeModulesProxy';
2
- export default NativeModulesProxy.ExpoModulesCoreErrorManager;
@@ -1,23 +0,0 @@
1
- import NativeErrorManager from './NativeErrorManager';
2
- import Platform from '../Platform';
3
- import { CodedError } from '../errors/CodedError';
4
-
5
- if (__DEV__ && Platform.OS === 'android' && NativeErrorManager) {
6
- const onNewException = 'ExpoModulesCoreErrorManager.onNewException';
7
- const onNewWarning = 'ExpoModulesCoreErrorManager.onNewWarning';
8
-
9
- NativeErrorManager.addListener(onNewException, ({ message }: { message: string }) => {
10
- console.error(message);
11
- });
12
-
13
- NativeErrorManager.addListener(onNewWarning, ({ message }: { message: string }) => {
14
- console.warn(message);
15
- });
16
- }
17
-
18
- declare namespace globalThis {
19
- let ExpoModulesCore_CodedError: undefined | typeof CodedError;
20
- }
21
-
22
- // We have to export `CodedError` via global object to use in later in the C++ code.
23
- globalThis.ExpoModulesCore_CodedError = CodedError;