Skip to content

Commit d06174f

Browse files
generatedunixname1563563004708334meta-codesync[bot]
authored andcommitted
xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/jni/react/jni/ModuleRegistryBuilder.cpp (#57457)
Summary: Pull Request resolved: #57457 Reviewed By: cortinico Differential Revision: D110876914 fbshipit-source-id: 6c65fce7ad97dc31dc8df71925ed1e155bc1109a
1 parent ce057d6 commit d06174f

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <react/jni/ModuleRegistryBuilder.h>
9+
10+
#include <fbjni/fbjni.h>
11+
#include <gtest/gtest.h>
12+
13+
#include <memory>
14+
15+
#ifndef RCT_REMOVE_LEGACY_ARCH
16+
17+
namespace facebook::react {
18+
19+
/**
20+
* Pure-C++ unit tests for the JNI-free slice of `ModuleRegistryBuilder.cpp`.
21+
*
22+
* The bulk of this translation unit is JNI-coupled: `ModuleHolder::getName`
23+
* and `ModuleHolder::getProvider` both call into a live JavaVM (via
24+
* `getClass()` / `jni::make_global(self())`), so their behaviour is
25+
* exercised by the Robolectric / instrumentation tests that run against a
26+
* real JVM.
27+
*
28+
* The one branch that can be validated host-side without an attached JavaVM
29+
* is `buildNativeModuleList`'s null-collection guard: when the incoming
30+
* `alias_ref<JCollection<...>>` is a null reference, the function must
31+
* short-circuit and return an empty vector rather than dereferencing the
32+
* null collection. `alias_ref` is default-constructible to a null state
33+
* whose `operator bool()` returns false, which is exactly what
34+
* `buildNativeModuleList`'s `if (javaModules)` check tests against, so we
35+
* can drive that path without touching JNI.
36+
*/
37+
38+
/*
39+
* Verifies the null-input contract of `buildNativeModuleList`: when the
40+
* `javaModules` collection is a null `alias_ref`, no `JavaNativeModule`
41+
* instances are constructed and the returned vector is empty.
42+
*
43+
* Bug this catches: if the `if (javaModules)` guard is ever removed or
44+
* inverted, the subsequent `for (const auto& jm : *javaModules)` would
45+
* dereference a null JNI reference and crash the process on every startup
46+
* path that leaves `javaModules` unset (for example, new-architecture
47+
* bring-up paths that legitimately pass no legacy Java modules). Because
48+
* the crash would only surface once the process actually reaches this
49+
* code with a null collection, catching it here — instead of relying on
50+
* a device-side smoke test — is the earliest signal available.
51+
*
52+
* The `Instance` weak_ptr and `MessageQueueThread` shared_ptr are supplied
53+
* as empty on purpose: the guard runs before either is dereferenced, so
54+
* their state must not affect the null-collection contract.
55+
*/
56+
TEST(
57+
ModuleRegistryBuilderTest,
58+
buildNativeModuleListReturnsEmptyForNullCollection) {
59+
std::weak_ptr<Instance> noInstance;
60+
std::shared_ptr<MessageQueueThread> noQueue;
61+
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject>
62+
nullCollection;
63+
ASSERT_FALSE(static_cast<bool>(nullCollection))
64+
<< "Precondition: default-constructed alias_ref must be null so that "
65+
"the guard under test is actually exercised.";
66+
67+
auto modules = buildNativeModuleList(noInstance, nullCollection, noQueue);
68+
69+
EXPECT_TRUE(modules.empty());
70+
}
71+
72+
} // namespace facebook::react
73+
74+
#endif

0 commit comments

Comments
 (0)