expo-modules-core 0.13.0 → 0.13.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.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,18 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.13.2 — 2022-10-28
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - Fixed `new NativeEventEmitter() was called with a non-null argument without the required addListener method.` warnings on Android. ([#19704](https://github.com/expo/expo/pull/19704) by [@kudo](https://github.com/kudo), [@kudo](https://github.com/kudo))
18
+
19
+ ## 0.13.1 — 2022-10-27
20
+
21
+ ### 🐛 Bug fixes
22
+
23
+ - Fixed `~CallbackWrapper()` dangling pointer crashes when reloading the app on Android. ([#19699](https://github.com/expo/expo/pull/19699) by [@kudo](https://github.com/kudo), [@kudo](https://github.com/kudo))
24
+
13
25
  ## 0.13.0 — 2022-10-25
14
26
 
15
27
  ### 🛠 Breaking changes
@@ -6,7 +6,7 @@ apply plugin: 'maven-publish'
6
6
  apply plugin: "de.undercouch.download"
7
7
 
8
8
  group = 'host.exp.exponent'
9
- version = '0.13.0'
9
+ version = '0.13.2'
10
10
 
11
11
  buildscript {
12
12
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -186,7 +186,7 @@ android {
186
186
  targetSdkVersion safeExtGet("targetSdkVersion", 31)
187
187
  consumerProguardFiles 'proguard-rules.pro'
188
188
  versionCode 1
189
- versionName "0.13.0"
189
+ versionName "0.13.2"
190
190
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
191
191
 
192
192
  testInstrumentationRunner "expo.modules.TestRunner"
@@ -72,6 +72,7 @@ void JavaScriptModuleObject::registerSyncFunction(
72
72
 
73
73
  methodsMetadata.try_emplace(
74
74
  cName,
75
+ longLivedObjectCollection_,
75
76
  cName,
76
77
  args,
77
78
  false,
@@ -90,6 +91,7 @@ void JavaScriptModuleObject::registerAsyncFunction(
90
91
 
91
92
  methodsMetadata.try_emplace(
92
93
  cName,
94
+ longLivedObjectCollection_,
93
95
  cName,
94
96
  args,
95
97
  true,
@@ -107,6 +109,7 @@ void JavaScriptModuleObject::registerProperty(
107
109
  auto cName = name->toStdString();
108
110
 
109
111
  auto getterMetadata = MethodMetadata(
112
+ longLivedObjectCollection_,
110
113
  cName,
111
114
  0,
112
115
  false,
@@ -117,6 +120,7 @@ void JavaScriptModuleObject::registerProperty(
117
120
  auto types = std::vector<std::unique_ptr<AnyType>>();
118
121
  types.push_back(std::make_unique<AnyType>(jni::make_local(expectedArgType)));
119
122
  auto setterMetadata = MethodMetadata(
123
+ longLivedObjectCollection_,
120
124
  cName,
121
125
  1,
122
126
  false,
@@ -145,6 +149,7 @@ JavaScriptModuleObject::HostObject::~HostObject() {
145
149
  jsModule->methodsMetadata.clear();
146
150
  jsModule->constants.clear();
147
151
  jsModule->properties.clear();
152
+ jsModule->longLivedObjectCollection_->clear();
148
153
  }
149
154
 
150
155
  jsi::Value JavaScriptModuleObject::HostObject::get(jsi::Runtime &runtime,
@@ -226,4 +231,10 @@ std::vector<jsi::PropNameID> JavaScriptModuleObject::HostObject::getPropertyName
226
231
 
227
232
  return result;
228
233
  }
234
+
235
+ JavaScriptModuleObject::JavaScriptModuleObject(jni::alias_ref<jhybridobject> jThis)
236
+ : javaPart_(jni::make_global(jThis)) {
237
+ longLivedObjectCollection_ = std::make_shared<react::LongLivedObjectCollection>();
238
+ }
239
+
229
240
  } // namespace expo
@@ -4,6 +4,7 @@
4
4
 
5
5
  #include <fbjni/fbjni.h>
6
6
  #include <jsi/jsi.h>
7
+ #include <react/bridging/LongLivedObject.h>
7
8
  #include <react/jni/ReadableNativeArray.h>
8
9
  #include <jni/JCallback.h>
9
10
 
@@ -116,6 +117,9 @@ public:
116
117
  JavaScriptModuleObject *jsModule;
117
118
  };
118
119
 
120
+ private:
121
+ explicit JavaScriptModuleObject(jni::alias_ref<jhybridobject> jThis);
122
+
119
123
  private:
120
124
  friend HybridBase;
121
125
  /**
@@ -141,7 +145,10 @@ private:
141
145
  */
142
146
  std::map<std::string, std::pair<MethodMetadata, MethodMetadata>> properties;
143
147
 
144
- explicit JavaScriptModuleObject(jni::alias_ref<jhybridobject> jThis)
145
- : javaPart_(jni::make_global(jThis)) {}
148
+ /**
149
+ * The `LongLivedObjectCollection` to hold `LongLivedObject` (callbacks or promises) for this module.
150
+ */
151
+ std::shared_ptr<react::LongLivedObjectCollection> longLivedObjectCollection_;
152
+
146
153
  };
147
154
  } // namespace expo
@@ -25,12 +25,18 @@ namespace expo {
25
25
  // https://github.com/facebook/react-native/blob/7dceb9b63c0bfd5b13bf6d26f9530729506e9097/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp#L57
26
26
  jni::local_ref<JavaCallback::JavaPart> createJavaCallbackFromJSIFunction(
27
27
  jsi::Function &&function,
28
+ std::weak_ptr<react::LongLivedObjectCollection> longLivedObjectCollection,
28
29
  jsi::Runtime &rt,
29
30
  JSIInteropModuleRegistry *moduleRegistry,
30
31
  bool isRejectCallback = false
31
32
  ) {
32
33
  std::shared_ptr<react::CallInvoker> jsInvoker = moduleRegistry->runtimeHolder->jsInvoker;
33
- auto weakWrapper = react::CallbackWrapper::createWeak(std::move(function), rt,
34
+ auto strongLongLiveObjectCollection = longLivedObjectCollection.lock();
35
+ if (!strongLongLiveObjectCollection) {
36
+ throw std::runtime_error("The LongLivedObjectCollection for MethodMetadata is not alive.");
37
+ }
38
+ auto weakWrapper = react::CallbackWrapper::createWeak(strongLongLiveObjectCollection,
39
+ std::move(function), rt,
34
40
  std::move(jsInvoker));
35
41
 
36
42
  // This needs to be a shared_ptr because:
@@ -148,6 +154,7 @@ jobjectArray MethodMetadata::convertJSIArgsToJNI(
148
154
  }
149
155
 
150
156
  MethodMetadata::MethodMetadata(
157
+ std::weak_ptr<react::LongLivedObjectCollection> longLivedObjectCollection,
151
158
  std::string name,
152
159
  int args,
153
160
  bool isAsync,
@@ -156,7 +163,8 @@ MethodMetadata::MethodMetadata(
156
163
  ) : name(std::move(name)),
157
164
  args(args),
158
165
  isAsync(isAsync),
159
- jBodyReference(std::move(jBodyReference)) {
166
+ jBodyReference(std::move(jBodyReference)),
167
+ longLivedObjectCollection_(longLivedObjectCollection) {
160
168
  argTypes.reserve(args);
161
169
  for (size_t i = 0; i < args; i++) {
162
170
  auto expectedType = expectedArgTypes->getElement(i);
@@ -167,6 +175,7 @@ MethodMetadata::MethodMetadata(
167
175
  }
168
176
 
169
177
  MethodMetadata::MethodMetadata(
178
+ std::weak_ptr<react::LongLivedObjectCollection> longLivedObjectCollection,
170
179
  std::string name,
171
180
  int args,
172
181
  bool isAsync,
@@ -176,8 +185,9 @@ MethodMetadata::MethodMetadata(
176
185
  args(args),
177
186
  isAsync(isAsync),
178
187
  argTypes(std::move(expectedArgTypes)),
179
- jBodyReference(std::move(jBodyReference)
180
- ) {}
188
+ jBodyReference(std::move(jBodyReference)),
189
+ longLivedObjectCollection_(longLivedObjectCollection) {
190
+ }
181
191
 
182
192
  std::shared_ptr<jsi::Function> MethodMetadata::toJSFunction(
183
193
  jsi::Runtime &runtime,
@@ -402,12 +412,14 @@ jsi::Function MethodMetadata::createPromiseBody(
402
412
 
403
413
  jobject resolve = createJavaCallbackFromJSIFunction(
404
414
  std::move(resolveJSIFn),
415
+ longLivedObjectCollection_,
405
416
  rt,
406
417
  moduleRegistry
407
418
  ).release();
408
419
 
409
420
  jobject reject = createJavaCallbackFromJSIFunction(
410
421
  std::move(rejectJSIFn),
422
+ longLivedObjectCollection_,
411
423
  rt,
412
424
  moduleRegistry,
413
425
  true
@@ -9,6 +9,7 @@
9
9
  #include <jsi/jsi.h>
10
10
  #include <fbjni/fbjni.h>
11
11
  #include <ReactCommon/TurboModuleUtils.h>
12
+ #include <react/bridging/LongLivedObject.h>
12
13
  #include <react/jni/ReadableNativeArray.h>
13
14
  #include <memory>
14
15
  #include <vector>
@@ -45,6 +46,7 @@ public:
45
46
  std::vector<std::unique_ptr<AnyType>> argTypes;
46
47
 
47
48
  MethodMetadata(
49
+ std::weak_ptr<react::LongLivedObjectCollection> longLivedObjectCollection,
48
50
  std::string name,
49
51
  int args,
50
52
  bool isAsync,
@@ -53,6 +55,7 @@ public:
53
55
  );
54
56
 
55
57
  MethodMetadata(
58
+ std::weak_ptr<react::LongLivedObjectCollection> longLivedObjectCollection,
56
59
  std::string name,
57
60
  int args,
58
61
  bool isAsync,
@@ -111,6 +114,8 @@ private:
111
114
  */
112
115
  std::shared_ptr<jsi::Function> body = nullptr;
113
116
 
117
+ std::weak_ptr<react::LongLivedObjectCollection> longLivedObjectCollection_;
118
+
114
119
  jsi::Function toSyncFunction(jsi::Runtime &runtime, JSIInteropModuleRegistry *moduleRegistry);
115
120
 
116
121
  jsi::Function toAsyncFunction(jsi::Runtime &runtime, JSIInteropModuleRegistry *moduleRegistry);
@@ -20,11 +20,11 @@ class ViewEventDelegate<T>(
20
20
 
21
21
  operator fun getValue(thisRef: View, property: KProperty<*>): ViewEventCallback<T> {
22
22
  if (!isValidated) {
23
- throw IllegalStateException("You have to export this property as a callback in the `ViewManager`.")
23
+ throw IllegalStateException("You have to export '${property.name}' property as a event in the `View` component")
24
24
  }
25
25
 
26
26
  val view = viewHolder.get()
27
- ?: throw IllegalStateException("Can't send an event from the view that is deallocated.")
27
+ ?: throw IllegalStateException("Can't send the '${property.name}' event from the view that is deallocated")
28
28
  return ViewEvent(property.name, type, view, coalescingKey)
29
29
  }
30
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EventEmitter.d.ts","sourceRoot":"","sources":["../src/EventEmitter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,cAAc,CAAC;AAI3E,aAAK,YAAY,GAAG;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC;AAGF,oBAAY,YAAY,GAAG;IACzB;;OAEG;IACH,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAEF,qBAAa,YAAY;IACvB,cAAc,SAAK;IACnB,aAAa,EAAE,YAAY,CAAC;IAC5B,aAAa,EAAE,kBAAkB,CAAC;gBAEtB,YAAY,EAAE,YAAY;IAsBtC,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,YAAY;IAgB7E,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAmB3C,kBAAkB,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IA0BpD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI;CAGhD"}
1
+ {"version":3,"file":"EventEmitter.d.ts","sourceRoot":"","sources":["../src/EventEmitter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,cAAc,CAAC;AAI3E,aAAK,YAAY,GAAG;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC;AAGF,oBAAY,YAAY,GAAG;IACzB;;OAEG;IACH,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAEF,qBAAa,YAAY;IACvB,cAAc,SAAK;IACnB,aAAa,EAAE,YAAY,CAAC;IAC5B,aAAa,EAAE,kBAAkB,CAAC;gBAEtB,YAAY,EAAE,YAAY;IAuCtC,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,YAAY;IAgB7E,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAmB3C,kBAAkB,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IA0BpD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI;CAGhD"}
@@ -14,6 +14,23 @@ export class EventEmitter {
14
14
  nativeModule.addListener = (...args) => NativeModules.EXReactNativeEventEmitter.addProxiedListener(nativeModule.__expo_module_name__, ...args);
15
15
  nativeModule.removeListeners = (...args) => NativeModules.EXReactNativeEventEmitter.removeProxiedListeners(nativeModule.__expo_module_name__, ...args);
16
16
  }
17
+ // Fix the `NativeEventEmitter` warnings on Android.
18
+ // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `addListener` method.
19
+ // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `removeListeners` method.
20
+ if (Platform.OS === 'android') {
21
+ Object.defineProperties(nativeModule, {
22
+ addListener: {
23
+ value: () => { },
24
+ writable: true,
25
+ enumerable: true,
26
+ },
27
+ removeListeners: {
28
+ value: () => { },
29
+ writable: true,
30
+ enumerable: true,
31
+ },
32
+ });
33
+ }
17
34
  this._nativeModule = nativeModule;
18
35
  this._eventEmitter = new NativeEventEmitter(nativeModule);
19
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EventEmitter.js","sourceRoot":"","sources":["../src/EventEmitter.ts"],"names":[],"mappings":"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","sourcesContent":["import invariant from 'invariant';\nimport { NativeEventEmitter, NativeModules, Platform } from 'react-native';\n\nconst nativeEmitterSubscriptionKey = '@@nativeEmitterSubscription@@';\n\ntype NativeModule = {\n __expo_module_name__?: string;\n startObserving?: () => void;\n stopObserving?: () => void;\n addListener: (eventName: string) => void;\n removeListeners: (count: number) => void;\n};\n\n// @needsAudit\nexport type Subscription = {\n /**\n * A method to unsubscribe the listener.\n */\n remove: () => void;\n};\n\nexport class EventEmitter {\n _listenerCount = 0;\n _nativeModule: NativeModule;\n _eventEmitter: NativeEventEmitter;\n\n constructor(nativeModule: NativeModule) {\n // Expo modules installed through the JSI don't have `addListener` and `removeListeners` set,\n // so if someone wants to use them with `EventEmitter`, make sure to provide these functions\n // as they are required by `NativeEventEmitter`. This is only temporary — in the future\n // JSI modules will have event emitter built in.\n if (nativeModule.__expo_module_name__ && NativeModules.EXReactNativeEventEmitter) {\n nativeModule.addListener = (...args) =>\n NativeModules.EXReactNativeEventEmitter.addProxiedListener(\n nativeModule.__expo_module_name__,\n ...args\n );\n nativeModule.removeListeners = (...args) =>\n NativeModules.EXReactNativeEventEmitter.removeProxiedListeners(\n nativeModule.__expo_module_name__,\n ...args\n );\n }\n\n this._nativeModule = nativeModule;\n this._eventEmitter = new NativeEventEmitter(nativeModule as any);\n }\n\n addListener<T>(eventName: string, listener: (event: T) => void): Subscription {\n if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.startObserving) {\n this._nativeModule.startObserving();\n }\n\n this._listenerCount++;\n const nativeEmitterSubscription = this._eventEmitter.addListener(eventName, listener);\n const subscription = {\n [nativeEmitterSubscriptionKey]: nativeEmitterSubscription,\n remove: () => {\n this.removeSubscription(subscription);\n },\n };\n return subscription;\n }\n\n removeAllListeners(eventName: string): void {\n // @ts-ignore: the EventEmitter interface has been changed in react-native@0.64.0\n const removedListenerCount = this._eventEmitter.listenerCount\n ? // @ts-ignore: this is available since 0.64\n this._eventEmitter.listenerCount(eventName)\n : // @ts-ignore: this is available in older versions\n this._eventEmitter.listeners(eventName).length;\n this._eventEmitter.removeAllListeners(eventName);\n this._listenerCount -= removedListenerCount;\n invariant(\n this._listenerCount >= 0,\n `EventEmitter must have a non-negative number of listeners`\n );\n\n if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.stopObserving) {\n this._nativeModule.stopObserving();\n }\n }\n\n removeSubscription(subscription: Subscription): void {\n const nativeEmitterSubscription = subscription[nativeEmitterSubscriptionKey];\n if (!nativeEmitterSubscription) {\n return;\n }\n\n if ('remove' in nativeEmitterSubscription) {\n // `react-native-web@0.17.1` doesn't support `removeSubscription`\n nativeEmitterSubscription.remove();\n } else if ('removeSubscription' in this._eventEmitter) {\n this._eventEmitter.removeSubscription(nativeEmitterSubscription!);\n }\n this._listenerCount--;\n\n // Ensure that the emitter's internal state remains correct even if `removeSubscription` is\n // called again with the same subscription\n delete subscription[nativeEmitterSubscriptionKey];\n\n // Release closed-over references to the emitter\n subscription.remove = () => {};\n\n if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.stopObserving) {\n this._nativeModule.stopObserving();\n }\n }\n\n emit(eventName: string, ...params: any[]): void {\n this._eventEmitter.emit(eventName, ...params);\n }\n}\n"]}
1
+ {"version":3,"file":"EventEmitter.js","sourceRoot":"","sources":["../src/EventEmitter.ts"],"names":[],"mappings":"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","sourcesContent":["import invariant from 'invariant';\nimport { NativeEventEmitter, NativeModules, Platform } from 'react-native';\n\nconst nativeEmitterSubscriptionKey = '@@nativeEmitterSubscription@@';\n\ntype NativeModule = {\n __expo_module_name__?: string;\n startObserving?: () => void;\n stopObserving?: () => void;\n addListener: (eventName: string) => void;\n removeListeners: (count: number) => void;\n};\n\n// @needsAudit\nexport type Subscription = {\n /**\n * A method to unsubscribe the listener.\n */\n remove: () => void;\n};\n\nexport class EventEmitter {\n _listenerCount = 0;\n _nativeModule: NativeModule;\n _eventEmitter: NativeEventEmitter;\n\n constructor(nativeModule: NativeModule) {\n // Expo modules installed through the JSI don't have `addListener` and `removeListeners` set,\n // so if someone wants to use them with `EventEmitter`, make sure to provide these functions\n // as they are required by `NativeEventEmitter`. This is only temporary — in the future\n // JSI modules will have event emitter built in.\n if (nativeModule.__expo_module_name__ && NativeModules.EXReactNativeEventEmitter) {\n nativeModule.addListener = (...args) =>\n NativeModules.EXReactNativeEventEmitter.addProxiedListener(\n nativeModule.__expo_module_name__,\n ...args\n );\n nativeModule.removeListeners = (...args) =>\n NativeModules.EXReactNativeEventEmitter.removeProxiedListeners(\n nativeModule.__expo_module_name__,\n ...args\n );\n }\n // Fix the `NativeEventEmitter` warnings on Android.\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `addListener` method.\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `removeListeners` method.\n if (Platform.OS === 'android') {\n Object.defineProperties(nativeModule, {\n addListener: {\n value: () => {},\n writable: true,\n enumerable: true,\n },\n removeListeners: {\n value: () => {},\n writable: true,\n enumerable: true,\n },\n });\n }\n\n this._nativeModule = nativeModule;\n this._eventEmitter = new NativeEventEmitter(nativeModule as any);\n }\n\n addListener<T>(eventName: string, listener: (event: T) => void): Subscription {\n if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.startObserving) {\n this._nativeModule.startObserving();\n }\n\n this._listenerCount++;\n const nativeEmitterSubscription = this._eventEmitter.addListener(eventName, listener);\n const subscription = {\n [nativeEmitterSubscriptionKey]: nativeEmitterSubscription,\n remove: () => {\n this.removeSubscription(subscription);\n },\n };\n return subscription;\n }\n\n removeAllListeners(eventName: string): void {\n // @ts-ignore: the EventEmitter interface has been changed in react-native@0.64.0\n const removedListenerCount = this._eventEmitter.listenerCount\n ? // @ts-ignore: this is available since 0.64\n this._eventEmitter.listenerCount(eventName)\n : // @ts-ignore: this is available in older versions\n this._eventEmitter.listeners(eventName).length;\n this._eventEmitter.removeAllListeners(eventName);\n this._listenerCount -= removedListenerCount;\n invariant(\n this._listenerCount >= 0,\n `EventEmitter must have a non-negative number of listeners`\n );\n\n if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.stopObserving) {\n this._nativeModule.stopObserving();\n }\n }\n\n removeSubscription(subscription: Subscription): void {\n const nativeEmitterSubscription = subscription[nativeEmitterSubscriptionKey];\n if (!nativeEmitterSubscription) {\n return;\n }\n\n if ('remove' in nativeEmitterSubscription) {\n // `react-native-web@0.17.1` doesn't support `removeSubscription`\n nativeEmitterSubscription.remove();\n } else if ('removeSubscription' in this._eventEmitter) {\n this._eventEmitter.removeSubscription(nativeEmitterSubscription!);\n }\n this._listenerCount--;\n\n // Ensure that the emitter's internal state remains correct even if `removeSubscription` is\n // called again with the same subscription\n delete subscription[nativeEmitterSubscriptionKey];\n\n // Release closed-over references to the emitter\n subscription.remove = () => {};\n\n if (!this._listenerCount && Platform.OS !== 'ios' && this._nativeModule.stopObserving) {\n this._nativeModule.stopObserving();\n }\n }\n\n emit(eventName: string, ...params: any[]): void {\n this._eventEmitter.emit(eventName, ...params);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "description": "The core of Expo Modules architecture",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -42,5 +42,5 @@
42
42
  "@testing-library/react-hooks": "^7.0.1",
43
43
  "expo-module-scripts": "^3.0.0"
44
44
  },
45
- "gitHead": "eab2b09c735fb0fc2bf734a3f29a6593adba3838"
45
+ "gitHead": "59081bb17e727b10f2a00cd07bb45cd283a6f6a5"
46
46
  }
@@ -41,6 +41,23 @@ export class EventEmitter {
41
41
  ...args
42
42
  );
43
43
  }
44
+ // Fix the `NativeEventEmitter` warnings on Android.
45
+ // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `addListener` method.
46
+ // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `removeListeners` method.
47
+ if (Platform.OS === 'android') {
48
+ Object.defineProperties(nativeModule, {
49
+ addListener: {
50
+ value: () => {},
51
+ writable: true,
52
+ enumerable: true,
53
+ },
54
+ removeListeners: {
55
+ value: () => {},
56
+ writable: true,
57
+ enumerable: true,
58
+ },
59
+ });
60
+ }
44
61
 
45
62
  this._nativeModule = nativeModule;
46
63
  this._eventEmitter = new NativeEventEmitter(nativeModule as any);