-
Notifications
You must be signed in to change notification settings - Fork 24k
/
TurboReactPackage.java
162 lines (139 loc) · 5.59 KB
/
TurboReactPackage.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.ModuleHolder;
import com.facebook.react.bridge.ModuleSpec;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.inject.Provider;
/** This will eventually replace {@link LazyReactPackage} when TurboModules are finally done. */
public abstract class TurboReactPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
throw new UnsupportedOperationException(
"In case of TurboModules, createNativeModules is not supported. NativeModuleRegistry should instead use getModuleList or getModule method");
}
/**
* The API needed for TurboModules. Given a module name, it returns an instance of {@link
* NativeModule} for the name
*
* @param name
* @param reactContext
* @return
*/
public abstract NativeModule getModule(String name, final ReactApplicationContext reactContext);
/**
* This is a temporary method till we implement TurboModules. Once we implement TurboModules, we
* will be able to directly call {@link TurboReactPackage#getModule(String,
* ReactApplicationContext)} This method will be removed when TurboModule implementation is
* complete
*
* @param reactContext
* @return
*/
public Iterable<ModuleHolder> getNativeModuleIterator(
final ReactApplicationContext reactContext) {
final Set<Map.Entry<String, ReactModuleInfo>> entrySet =
getReactModuleInfoProvider().getReactModuleInfos().entrySet();
final Iterator<Map.Entry<String, ReactModuleInfo>> entrySetIterator = entrySet.iterator();
return new Iterable<ModuleHolder>() {
@NonNull
@Override
// This should ideally be an IteratorConvertor, but we don't have any internal library for it
public Iterator<ModuleHolder> iterator() {
return new Iterator<ModuleHolder>() {
Map.Entry<String, ReactModuleInfo> nextEntry = null;
private void findNext() {
while (entrySetIterator.hasNext()) {
Map.Entry<String, ReactModuleInfo> entry = entrySetIterator.next();
ReactModuleInfo reactModuleInfo = entry.getValue();
// This Iterator is used to create the NativeModule registry. The NativeModule
// registry must not have TurboModules. Therefore, if TurboModules are enabled, and
// the current NativeModule is a TurboModule, we need to skip iterating over it.
if (ReactFeatureFlags.useTurboModules && reactModuleInfo.isTurboModule()) {
continue;
}
nextEntry = entry;
return;
}
nextEntry = null;
}
@Override
public boolean hasNext() {
if (nextEntry == null) {
findNext();
}
return nextEntry != null;
}
@Override
public ModuleHolder next() {
if (nextEntry == null) {
findNext();
}
if (nextEntry == null) {
throw new NoSuchElementException("ModuleHolder not found");
}
Map.Entry<String, ReactModuleInfo> entry = nextEntry;
// Advance iterator
findNext();
String name = entry.getKey();
ReactModuleInfo reactModuleInfo = entry.getValue();
return new ModuleHolder(reactModuleInfo, new ModuleHolderProvider(name, reactContext));
}
@Override
public void remove() {
throw new UnsupportedOperationException("Cannot remove native modules from the list");
}
};
}
};
}
/**
* @param reactContext react application context that can be used to create View Managers.
* @return list of module specs that can create the View Managers.
*/
protected List<ModuleSpec> getViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
List<ModuleSpec> viewManagerModuleSpecs = getViewManagers(reactContext);
if (viewManagerModuleSpecs == null || viewManagerModuleSpecs.isEmpty()) {
return Collections.emptyList();
}
List<ViewManager> viewManagers = new ArrayList<>();
for (ModuleSpec moduleSpec : viewManagerModuleSpecs) {
viewManagers.add((ViewManager) moduleSpec.getProvider().get());
}
return viewManagers;
}
public abstract ReactModuleInfoProvider getReactModuleInfoProvider();
private class ModuleHolderProvider implements Provider<NativeModule> {
private final String mName;
private final ReactApplicationContext mReactContext;
public ModuleHolderProvider(String name, ReactApplicationContext reactContext) {
mName = name;
mReactContext = reactContext;
}
@Override
public NativeModule get() {
return getModule(mName, mReactContext);
}
}
}