@symbiote-native/engine 0.4.0 → 1.0.0
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/README.md +39 -14
- package/android/CMakeLists.txt +51 -0
- package/android/build.gradle +90 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/cpp/SymbioteEngineJni.cpp +72 -0
- package/android/src/main/java/dev/symbiotenative/engine/SymbioteEngineModule.kt +43 -0
- package/android/src/main/java/dev/symbiotenative/engine/SymbioteEnginePackage.kt +35 -0
- package/build/accessibility-info/shared.js +1 -1
- package/build/accessibility-props.d.ts +1 -7
- package/build/accessibility-props.js +22 -21
- package/build/animated/animations/composition.d.ts +1 -1
- package/build/animated/animations/composition.js +18 -4
- package/build/animated/easing.d.ts +3 -2
- package/build/animated/easing.js +17 -88
- package/build/animated/event.js +6 -1
- package/build/animated/graph.d.ts +2 -0
- package/build/animated/graph.js +14 -0
- package/build/animated/host-binding.d.ts +39 -0
- package/build/animated/host-binding.js +278 -0
- package/build/animated/index.d.ts +1 -1
- package/build/animated/leaf-lifecycle.js +10 -22
- package/build/animated/mock.d.ts +1 -19
- package/build/animated/props.js +1 -1
- package/build/animated/rgba.js +16 -50
- package/build/events/index.js +123 -33
- package/build/fabric-props.d.ts +1 -1
- package/build/fabric-props.js +129 -182
- package/build/fabric.d.ts +10 -0
- package/build/fabric.js +40 -0
- package/build/host-access.d.ts +125 -0
- package/build/host-access.js +280 -0
- package/build/host-behavior.d.ts +107 -7
- package/build/host-behavior.js +309 -31
- package/build/image-source-write.d.ts +16 -0
- package/build/image-source-write.js +65 -0
- package/build/imperative.d.ts +49 -0
- package/build/imperative.js +258 -0
- package/build/index.d.ts +18 -10
- package/build/index.js +65 -10
- package/build/mutation-buffer.d.ts +222 -0
- package/build/mutation-buffer.js +491 -0
- package/build/native-engine.d.ts +182 -0
- package/build/native-engine.js +178 -0
- package/build/native-tree-host.d.ts +25 -0
- package/build/native-tree-host.js +66 -0
- package/build/node.d.ts +191 -60
- package/build/node.js +1034 -327
- package/build/pan-responder/index.d.ts +2 -2
- package/build/pan-responder/index.js +37 -56
- package/build/platform-color/index.d.ts +1 -1
- package/build/platform-color/index.js +11 -4
- package/build/process-background-image/index.js +30 -566
- package/build/process-background-longhands.d.ts +4 -0
- package/build/process-background-longhands.js +44 -0
- package/build/process-box-shadow/index.js +23 -187
- package/build/process-filter.js +27 -300
- package/build/process-transform/index.d.ts +1 -1
- package/build/process-transform/index.js +25 -107
- package/build/process-transform-origin/index.d.ts +1 -1
- package/build/process-transform-origin/index.js +29 -102
- package/build/registry.d.ts +36 -0
- package/build/registry.js +73 -0
- package/build/sound-manager/index.d.ts +3 -0
- package/build/sound-manager/index.js +36 -0
- package/build/structured-style.d.ts +10 -0
- package/build/structured-style.js +180 -0
- package/build/style-registry/index.d.ts +14 -0
- package/build/style-registry/index.js +60 -11
- package/build/styles.d.ts +5 -1
- package/build/surface.d.ts +31 -2
- package/build/surface.js +138 -42
- package/build/text-input-state.d.ts +1 -0
- package/build/text-input-state.js +17 -3
- package/build/tree-host.d.ts +307 -0
- package/build/tree-host.js +211 -0
- package/build/view-config.js +4 -4
- package/codegen-specs/NativeSymbioteEngine.ts +27 -0
- package/cpp/SymbioteDebug.cpp +51 -0
- package/cpp/SymbioteDebug.h +54 -0
- package/cpp/SymbioteEngineBindings.cpp +232 -0
- package/cpp/SymbioteEngineBindings.h +59 -0
- package/cpp/SymbioteFabricProps.cpp +2619 -0
- package/cpp/SymbioteFabricProps.h +223 -0
- package/cpp/SymbioteTree.cpp +2478 -0
- package/cpp/SymbioteTree.h +257 -0
- package/ios/SymbioteEngineModule.h +25 -0
- package/ios/SymbioteEngineModule.mm +44 -0
- package/package.json +31 -3
- package/react-native.config.cjs +23 -0
- package/symbiote-engine.podspec +42 -0
- package/build/animated/bezier.d.ts +0 -1
- package/build/animated/bezier.js +0 -102
- package/build/commit.d.ts +0 -49
- package/build/commit.js +0 -1030
- package/build/tags.d.ts +0 -2
- package/build/tags.js +0 -40
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#include "SymbioteEngineBindings.h"
|
|
2
|
+
|
|
3
|
+
#include "SymbioteDebug.h"
|
|
4
|
+
#include "SymbioteTree.h"
|
|
5
|
+
|
|
6
|
+
#include <react/renderer/mounting/ShadowTreeRegistry.h>
|
|
7
|
+
#include <react/renderer/uimanager/UIManager.h>
|
|
8
|
+
#include <react/renderer/uimanager/UIManagerBinding.h>
|
|
9
|
+
|
|
10
|
+
#include <cmath>
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
#include <cstdlib>
|
|
13
|
+
#include <memory>
|
|
14
|
+
#include <string>
|
|
15
|
+
#include <vector>
|
|
16
|
+
|
|
17
|
+
namespace symbiote {
|
|
18
|
+
|
|
19
|
+
using namespace facebook;
|
|
20
|
+
|
|
21
|
+
namespace {
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A block of `int32_t` owned by native and handed to JS as the backing store of an `Int32Array`.
|
|
25
|
+
*
|
|
26
|
+
* The node table's parent edge is already a flat `Int32Array` in JS (item 8b); the endpoint is that
|
|
27
|
+
* the SAME array is memory the native applier writes. A `MutableBuffer`-backed `jsi::ArrayBuffer` is
|
|
28
|
+
* the only JSI shape that gives JS a VIEW instead of a copy — every other route costs a crossing per
|
|
29
|
+
* element, and the census that sized this design counted ~4 000 reads for a two-row swap.
|
|
30
|
+
*
|
|
31
|
+
* Note what this does and does not fork. `node-table.ts` is byte-identical whichever store it gets:
|
|
32
|
+
* one implementation, two allocators. That is why the JS store may stand indefinitely, while the JS
|
|
33
|
+
* APPLIER may not — see `native-engine.ts`'s header for the distinction, which is load-bearing.
|
|
34
|
+
*
|
|
35
|
+
* Lifetime is the ArrayBuffer's: `jsi::ArrayBuffer` retains the `shared_ptr`, so the store outlives
|
|
36
|
+
* every JS view of it and is freed with the last one. A registry of live stores would be the leak
|
|
37
|
+
* rather than the fix.
|
|
38
|
+
*/
|
|
39
|
+
class Int32Store : public jsi::MutableBuffer {
|
|
40
|
+
public:
|
|
41
|
+
explicit Int32Store(size_t lengthInInts) : data_(lengthInInts, 0) {}
|
|
42
|
+
|
|
43
|
+
size_t size() const override {
|
|
44
|
+
return data_.size() * sizeof(int32_t);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
uint8_t *data() override {
|
|
48
|
+
return reinterpret_cast<uint8_t *>(data_.data());
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private:
|
|
52
|
+
std::vector<int32_t> data_;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
jsi::Value allocInt32Array(
|
|
56
|
+
jsi::Runtime &runtime,
|
|
57
|
+
const jsi::Value & /*thisValue*/,
|
|
58
|
+
const jsi::Value *arguments,
|
|
59
|
+
size_t count) {
|
|
60
|
+
if (count < 1 || !arguments[0].isNumber()) {
|
|
61
|
+
throw jsi::JSError(runtime, "allocInt32Array expects a length in elements");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const double requested = arguments[0].getNumber();
|
|
65
|
+
// A negative or fractional length reaches `std::vector` as a wildly wrong `size_t`. Reject it here,
|
|
66
|
+
// where there is a message, rather than at the allocation, where the failure is a bare crash.
|
|
67
|
+
if (!(requested >= 0) || requested != std::floor(requested)) {
|
|
68
|
+
throw jsi::JSError(runtime, "allocInt32Array expects a non-negative integer length");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
auto store = std::make_shared<Int32Store>(static_cast<size_t>(requested));
|
|
72
|
+
auto buffer = jsi::ArrayBuffer(runtime, store);
|
|
73
|
+
auto constructor = runtime.global().getPropertyAsFunction(runtime, "Int32Array");
|
|
74
|
+
return constructor.callAsConstructor(runtime, std::move(buffer));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* How many shadow trees the real `UIManager` is holding — or -1 when we could not reach one.
|
|
79
|
+
*
|
|
80
|
+
* This is item 8c-1's bring-up probe and it is deliberately NOT a commit hook. What it retires is
|
|
81
|
+
* the whole reach chain in one device run: that our pod compiles against ReactCommon's renderer
|
|
82
|
+
* headers, that it LINKS against the prebuilt `React.xcframework`, and that a plain JSI runtime
|
|
83
|
+
* handed to a third-party TurboModule can resolve the UIManager with no app-side wiring. Every one
|
|
84
|
+
* of those is a hard blocker for the native applier and none of them is visible from JS.
|
|
85
|
+
*
|
|
86
|
+
* -1 and 0 are different answers and that is the point. `getBinding` reads
|
|
87
|
+
* `global.nativeFabricUIManager` and returns null when it is absent, so -1 means the ORDERING is
|
|
88
|
+
* wrong — we were created before Fabric installed its binding. 0 means we reached a real UIManager
|
|
89
|
+
* that happens to hold no surface. A boolean would collapse the two and cost a second build.
|
|
90
|
+
*
|
|
91
|
+
* The ordering is in fact safe by construction, and this probe is what confirms it rather than
|
|
92
|
+
* assumes it: `getSlot()` (fabric.ts) reads `globalThis.nativeFabricUIManager` and throws when it is
|
|
93
|
+
* absent, and only THEN resolves our module — so by the time this file's install hook runs, the
|
|
94
|
+
* binding `getBinding` looks for is guaranteed to be there. That was luck when 8c-0 chose the seam.
|
|
95
|
+
*/
|
|
96
|
+
jsi::Value probeUIManager(
|
|
97
|
+
jsi::Runtime &runtime,
|
|
98
|
+
const jsi::Value & /*thisValue*/,
|
|
99
|
+
const jsi::Value * /*arguments*/,
|
|
100
|
+
size_t /*count*/) {
|
|
101
|
+
auto binding = react::UIManagerBinding::getBinding(runtime);
|
|
102
|
+
if (binding == nullptr) {
|
|
103
|
+
return jsi::Value(-1.0);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
int surfaces = 0;
|
|
107
|
+
binding->getUIManager().getShadowTreeRegistry().enumerate(
|
|
108
|
+
[&surfaces](const react::ShadowTree & /*shadowTree*/, bool & /*stop*/) { surfaces += 1; });
|
|
109
|
+
return jsi::Value(static_cast<double>(surfaces));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
} // namespace
|
|
113
|
+
|
|
114
|
+
void installBindings(jsi::Runtime &runtime) {
|
|
115
|
+
auto bindings = jsi::Object(runtime);
|
|
116
|
+
|
|
117
|
+
// THE SWITCH, pushed down from the same two places `debug.ts` reads. Done at install so a host
|
|
118
|
+
// that sets `__SYMBIOTE_DEBUG__` in its bootstrap (every example's `index.js` does) gets the C++
|
|
119
|
+
// half armed without calling anything; `setDebugEnabled` below is what a LATER toggle uses, since
|
|
120
|
+
// this read happens exactly once.
|
|
121
|
+
const auto flag = runtime.global().getProperty(runtime, "__SYMBIOTE_DEBUG__");
|
|
122
|
+
const char *const env = std::getenv("DEBUG");
|
|
123
|
+
setDebugEnabled(
|
|
124
|
+
(flag.isBool() && flag.getBool()) ||
|
|
125
|
+
(env != nullptr && std::string(env) == "1"));
|
|
126
|
+
|
|
127
|
+
bindings.setProperty(
|
|
128
|
+
runtime,
|
|
129
|
+
"setDebugEnabled",
|
|
130
|
+
jsi::Function::createFromHostFunction(
|
|
131
|
+
runtime,
|
|
132
|
+
jsi::PropNameID::forAscii(runtime, "setDebugEnabled"),
|
|
133
|
+
1,
|
|
134
|
+
[](jsi::Runtime & /*rt*/, const jsi::Value & /*thisVal*/, const jsi::Value *args, size_t count)
|
|
135
|
+
-> jsi::Value {
|
|
136
|
+
if (count > 0 && args[0].isBool()) setDebugEnabled(args[0].getBool());
|
|
137
|
+
return jsi::Value::undefined();
|
|
138
|
+
}));
|
|
139
|
+
|
|
140
|
+
// Drains what the C++ side logged. The reason the lines are retained at all: a diagnostic nobody
|
|
141
|
+
// can assert on is a diagnostic that rots — this is what lets a test say "the engine warned"
|
|
142
|
+
// rather than a human noticing a line scroll past.
|
|
143
|
+
bindings.setProperty(
|
|
144
|
+
runtime,
|
|
145
|
+
"takeDebugLog",
|
|
146
|
+
jsi::Function::createFromHostFunction(
|
|
147
|
+
runtime,
|
|
148
|
+
jsi::PropNameID::forAscii(runtime, "takeDebugLog"),
|
|
149
|
+
0,
|
|
150
|
+
[](jsi::Runtime &rt, const jsi::Value & /*thisVal*/, const jsi::Value * /*args*/, size_t /*count*/)
|
|
151
|
+
-> jsi::Value {
|
|
152
|
+
const std::vector<std::string> lines = takeDebugLog();
|
|
153
|
+
auto out = jsi::Array(rt, lines.size());
|
|
154
|
+
for (size_t at = 0; at < lines.size(); at += 1)
|
|
155
|
+
out.setValueAtIndex(rt, at, jsi::String::createFromUtf8(rt, lines[at]));
|
|
156
|
+
return out;
|
|
157
|
+
}));
|
|
158
|
+
|
|
159
|
+
bindings.setProperty(runtime, "version", jsi::Value(kNativeVersion));
|
|
160
|
+
bindings.setProperty(
|
|
161
|
+
runtime,
|
|
162
|
+
"allocInt32Array",
|
|
163
|
+
jsi::Function::createFromHostFunction(
|
|
164
|
+
runtime, jsi::PropNameID::forAscii(runtime, "allocInt32Array"), 1, allocInt32Array));
|
|
165
|
+
bindings.setProperty(
|
|
166
|
+
runtime,
|
|
167
|
+
"probeUIManager",
|
|
168
|
+
jsi::Function::createFromHostFunction(
|
|
169
|
+
runtime, jsi::PropNameID::forAscii(runtime, "probeUIManager"), 0, probeUIManager));
|
|
170
|
+
|
|
171
|
+
// One tree per runtime, and it holds NOTHING — a node's owner is the JS placeholder object,
|
|
172
|
+
// through `NativeState`. So this instance exists only to give the methods a `this` to hang off,
|
|
173
|
+
// and a per-call one would work identically. It is shared because an earlier version DID hold a
|
|
174
|
+
// table, and keeping the shape makes the diff that removed it readable.
|
|
175
|
+
auto tree = std::make_shared<Tree>();
|
|
176
|
+
|
|
177
|
+
// Installed by name rather than through a switch so a JS caller's mistake is `undefined is not a
|
|
178
|
+
// function` at the call site, instead of a runtime string comparison failing somewhere inside C++.
|
|
179
|
+
// `isBindings` in `native-engine.ts` checks these names one by one for the same reason.
|
|
180
|
+
const auto install = [&](const char *name,
|
|
181
|
+
unsigned int arity,
|
|
182
|
+
jsi::Value (Tree::*method)(jsi::Runtime &, const jsi::Value *, size_t)) {
|
|
183
|
+
bindings.setProperty(
|
|
184
|
+
runtime,
|
|
185
|
+
name,
|
|
186
|
+
jsi::Function::createFromHostFunction(
|
|
187
|
+
runtime,
|
|
188
|
+
jsi::PropNameID::forAscii(runtime, name),
|
|
189
|
+
arity,
|
|
190
|
+
[tree, method](
|
|
191
|
+
jsi::Runtime &rt,
|
|
192
|
+
const jsi::Value & /*thisValue*/,
|
|
193
|
+
const jsi::Value *arguments,
|
|
194
|
+
size_t count) { return (tree.get()->*method)(rt, arguments, count); }));
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// The one member on a commit path.
|
|
198
|
+
install("applyOps", 5, &Tree::applyOps);
|
|
199
|
+
|
|
200
|
+
// The reads — value and structural — and the imperative six. All of them take the same placeholder
|
|
201
|
+
// object `applyOps` attached the node to, and none is on a commit path: they run at gesture or
|
|
202
|
+
// lifecycle rate. `census` is deliberately absent; see `native-tree-host.ts`.
|
|
203
|
+
install("getProp", 2, &Tree::getProp);
|
|
204
|
+
install("getProps", 1, &Tree::getProps);
|
|
205
|
+
install("markPropsDirty", 1, &Tree::markPropsDirty);
|
|
206
|
+
install("getViewName", 1, &Tree::getViewName);
|
|
207
|
+
install("parentOf", 1, &Tree::parentOf);
|
|
208
|
+
install("childrenOf", 1, &Tree::childrenOf);
|
|
209
|
+
install("nextSiblingOf", 1, &Tree::nextSiblingOf);
|
|
210
|
+
install("parentsOf", 1, &Tree::parentsOf);
|
|
211
|
+
install("subtreesOf", 1, &Tree::subtreesOf);
|
|
212
|
+
install("ancestorsOf", 1, &Tree::ancestorsOf);
|
|
213
|
+
install("committedRecordOf", 1, &Tree::committedRecordOf);
|
|
214
|
+
// A TEST read, and it is on this list rather than behind a build flag because the bag it returns
|
|
215
|
+
// is already retained per node for diffing — see `Tree::committedPayloadOf` for why the complete
|
|
216
|
+
// props read-back cannot come from React Native's own `getDebugProps` or `rawProps`.
|
|
217
|
+
install("committedPayloadOf", 1, &Tree::committedPayloadOf);
|
|
218
|
+
|
|
219
|
+
install("dispatchCommand", 3, &Tree::dispatchCommand);
|
|
220
|
+
install("sendAccessibilityEvent", 2, &Tree::sendAccessibilityEvent);
|
|
221
|
+
install("measure", 2, &Tree::measure);
|
|
222
|
+
install("measureInWindow", 2, &Tree::measureInWindow);
|
|
223
|
+
install("measureLayout", 4, &Tree::measureLayout);
|
|
224
|
+
install("setIsJSResponder", 3, &Tree::setIsJSResponder);
|
|
225
|
+
|
|
226
|
+
// Diagnostic, read on demand rather than per op. See `Tree::readSurfaceTelemetry`.
|
|
227
|
+
install("readSurfaceTelemetry", 1, &Tree::readSurfaceTelemetry);
|
|
228
|
+
|
|
229
|
+
runtime.global().setProperty(runtime, "__symbioteEngineNative", std::move(bindings));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
} // namespace symbiote
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// The engine's native half, PLATFORM-SHARED. Every line that does real work lives here; the per-
|
|
2
|
+
// platform files under `ios/` (and, when item 8c-1 lands, `android/`) do nothing but register a
|
|
3
|
+
// module and call `installBindings`.
|
|
4
|
+
//
|
|
5
|
+
// That split is not tidiness, it is the arithmetic that decides whether Android is affordable.
|
|
6
|
+
// React Native's own equivalent — `AnimatedModule`, which reaches the runtime through the same
|
|
7
|
+
// `TurboModuleWithJSIBindings` hook and applies its per-frame edits with `ShadowNode::cloneMultiple`
|
|
8
|
+
// inside a registered commit hook — is a pure C++ TurboModule in `ReactCommon/react/renderer/`, with
|
|
9
|
+
// no platform directory at all. Every one of the eight `registerCommitHook` call sites in RN is
|
|
10
|
+
// likewise shared code. So the applier this file will eventually carry is ONE implementation for both
|
|
11
|
+
// platforms, and Android's cost is a JNI registration shim rather than a second applier.
|
|
12
|
+
//
|
|
13
|
+
// Why we still need a platform shim at all, when RN's own modules do not: RN registers its C++
|
|
14
|
+
// modules from inside its own TurboModule manager. A third-party package has no such hook in 0.86 —
|
|
15
|
+
// the codegen generator has no `cxxModules` path — so the module must be an ObjC class on iOS and a
|
|
16
|
+
// Java/JNI one on Android. That shim is the only thing that is written twice.
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
#include <jsi/jsi.h>
|
|
21
|
+
|
|
22
|
+
namespace symbiote {
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The ABI the JS side checks before it will use any of this.
|
|
26
|
+
*
|
|
27
|
+
* The two halves ship as separate artefacts — a CocoaPods sandbox and an npm package — with separate
|
|
28
|
+
* install steps, so an `npm install` without a `pod install` leaves them disagreeing. That is the
|
|
29
|
+
* ordinary state of this repo's local-dev loop, not an exotic one, which is why the version is a
|
|
30
|
+
* gate rather than a diagnostic.
|
|
31
|
+
*
|
|
32
|
+
* 1 -> 2: nodes stopped being addressed by an integer id out of a C++ table and became JS objects
|
|
33
|
+
* carrying their own `shared_ptr` as `NativeState`. Every method NAME survived that, so the JS
|
|
34
|
+
* shape guard cannot see the difference — only this number can. A v1 pod given a v2 batch ignores
|
|
35
|
+
* the `handles` argument and commits nothing; a v2 pod given v1 calls reads an integer as an object.
|
|
36
|
+
* Must move with `SUPPORTED_NATIVE_VERSION` in `core/engine/src/native-engine.ts`.
|
|
37
|
+
*
|
|
38
|
+
* 3 -> 4: the bindings stopped replaying FABRIC operations (`Applier`) and started owning the shadow
|
|
39
|
+
* tree (`Tree`). The three structural reads are new NAMES, which the JS shape guard would refuse on
|
|
40
|
+
* its own — but `applyOps` went from six arguments to five under the SAME name, and a v3 binary
|
|
41
|
+
* reads argument 1 as an `Int32Array` of child ids where JS now passes a string table. That read
|
|
42
|
+
* succeeds against the wrong object and commits a wrong tree rather than throwing, which is exactly
|
|
43
|
+
* the class this number exists to refuse. A refusal by luck, on the reads, is not a refusal.
|
|
44
|
+
*
|
|
45
|
+
* It does NOT move for a diagnostic: `readSurfaceTelemetry` changes no layout and no calling
|
|
46
|
+
* convention, and JS reads it optionally, so a pod without it degrades to "no answer" rather than
|
|
47
|
+
* throwing. Same reasoning `native-engine.ts` records for `probeUIManager`.
|
|
48
|
+
*/
|
|
49
|
+
constexpr double kNativeVersion = 4;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Install `global.__symbioteEngineNative`.
|
|
53
|
+
*
|
|
54
|
+
* Called once, from whichever platform shim got hold of the runtime. Everything JS can reach on the
|
|
55
|
+
* native side goes through the object this installs.
|
|
56
|
+
*/
|
|
57
|
+
void installBindings(facebook::jsi::Runtime &runtime);
|
|
58
|
+
|
|
59
|
+
} // namespace symbiote
|