In a 2018 post, Facebook engineers claim that:
React Native was designed to return a single JSON message that lists mutations to perform, like
[["createView", attrs], ["manageChildren", ...]]
. We designed the entire system to never rely on getting a synchronous response back and to ensure everything in that list could be fully serialized to JSON and back.
Where in the React Native codebase* is the exact code responsible for this very feature (building the JSON)? Or is the quoted claim maybe a lie "simplification"?
I'm desperately trying to find it, but seem to be running in circles; whenever I find a track which initially seems to look promising, it never seems to be able to lead me to a place where such JSON would be generated :(
* Please note, I'm specifically interested in the Android codebase; and ideally, RN v0.55, the most recent version as of writing.
If possible, I'm also interested in the complementary "reverse" code. I mean, I assume that the "native" (Java in case of Android) code must also send some "event" signals back to JS at some point, and I assume they're also JSON. So, again, where does this code live? (I'm interested in the JS code which receives and deserializes that JSON.)
(Also, I'd be extra grateful to learn if those "low level" features (sending and receiving the JSON) are accessible in raw form from JS in an Expo-based app; but this is 100% optional in an answer, as I'm reasonably confident that I'll be able to find that out by myself, once I know the answer to the main question above.)
Note: for full disclosure, I've also cross-posted this question on HN, but no answers there yet as of writing. I plan to remove this note from here when the discussion thread on HN gets stale.
Edit No.1
Based a "Related" question suggested by SO, I'm starting to get a fuzzy feeling that a concept/keyword named "BatchedBridge
" may be something very close to what I'm looking for. My intuition seems to tell me this might be the first serious step in the right direction. I've found a blog article describing how to observe messages flying both ways through BatchedBridge, which reportedly results in logs like below:
{type: 1, module: "WebSocketModule", method: "addListener", args: Array(1)}
{type: 1, module: "WebSocketModule", method: "connect", args: Array(4)}
{type: 0, module: "RCTDeviceEventEmitter", method: "emit", args: Array(2)}
{type: 1, module: "Timing", method: "createTimer", args: Array(4)}
And another article on the same blog shows how to send events from Java to JS over this "bridge", and listen to them in JS. This could answer half of the final, optional part of my question, about how to subscribe to Java events from JS in Expo. (In Java: this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("onSessionConnect", params);
, in JS: DeviceEventEmitter.addListener('onSessionConnect', (event) => { console.log(event); });
)
Another interesting article on RN internals, resulting from googling with 'react-native BatchedBridge' as keywords.
Edit 2, tentative
The place where JSON is built might be line 556 below, though I'm not very sure:
550 void JSCExecutor::callNativeModules(Value&& value) {
...
556 auto calls = value.toJSONString();
557 m_delegate->callNativeModules(*this, folly::parseJson(calls), true);
called e.g. from l.642 below:
624 void JSCExecutor::invokeCallback(
625 const double callbackId,
626 const folly::dynamic& arguments) {
...
628 auto result = [&] {
...
634 return m_invokeCallbackAndReturnFlushedQueueJS->callAsFunction(
635 {Value::makeNumber(m_context, callbackId),
636 Value::fromDynamic(m_context, std::move(arguments))});
...
642 callNativeModules(std::move(result));