Skip to content

Commit 9c21489

Browse files
rubennortefacebook-github-bot
authored andcommitted
Define JSI bridging function for ShadowNode::Shared (#51675)
Summary: Pull Request resolved: #51675 Changelog: [internal] This defines a new bridging method to convert ShadowNode::Shared from and to JS. This has some benefits over the existing `shadowNodeFromValue` and `valueFromShadowNode` functions: 1. It's more convenient, as we can just use `ShadowNode::Shared` in classes implementing the codegen, and the runtime will do the conversion automatically. 2. It's safer, as it checks for nullability and throws JS exceptions except of having segmentation faults down the line. Reviewed By: javache Differential Revision: D75597542 fbshipit-source-id: 37c0c43cbde0f4de9a740d9da910f215ae50efbd
1 parent 3a41cdf commit 9c21489

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ add_react_common_subdir(react/renderer/mounting)
9393
add_react_common_subdir(react/renderer/scheduler)
9494
add_react_common_subdir(react/renderer/telemetry)
9595
add_react_common_subdir(react/renderer/uimanager)
96+
add_react_common_subdir(react/renderer/bridging)
9697
add_react_common_subdir(react/renderer/core)
9798
add_react_common_subdir(react/renderer/consistency)
9899
add_react_common_subdir(react/renderer/css)

packages/react-native/ReactCommon/React-Fabric.podspec

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ Pod::Spec.new do |s|
6969
ss.header_dir = "react/renderer/attributedstring"
7070
end
7171

72+
s.subspec "bridging" do |ss|
73+
ss.source_files = "react/renderer/bridging/**/*.{m,mm,cpp,h}"
74+
ss.exclude_files = "react/renderer/bridging/tests"
75+
ss.header_dir = "react/renderer/bridging"
76+
end
77+
7278
s.subspec "core" do |ss|
7379
header_search_path = [
7480
"\"$(PODS_TARGET_SRCROOT)/ReactCommon\"",
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
#
3+
# This source code is licensed under the MIT license found in the
4+
# LICENSE file in the root directory of this source tree.
5+
6+
cmake_minimum_required(VERSION 3.13)
7+
set(CMAKE_VERBOSE_MAKEFILE on)
8+
9+
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
10+
11+
add_library(react_renderer_bridging INTERFACE)
12+
13+
target_include_directories(react_renderer_bridging INTERFACE ${REACT_COMMON_DIR})
14+
target_compile_reactnative_options(react_renderer_bridging INTERFACE)
15+
target_compile_options(react_renderer_bridging INTERFACE -Wpedantic)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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+
#pragma once
9+
10+
#include <jsi/jsi.h>
11+
#include <react/bridging/Base.h>
12+
#include <react/renderer/core/ShadowNode.h>
13+
14+
namespace facebook::react {
15+
16+
template <>
17+
struct Bridging<ShadowNode::Shared> {
18+
static ShadowNode::Shared fromJs(
19+
jsi::Runtime& rt,
20+
const jsi::Value& jsiValue) {
21+
auto object = jsiValue.asObject(rt);
22+
23+
// Using `jsi::NativeState` instead of `ShadowNodeWrapper` to avoid doing a
24+
// dynamic pointer cast twice (as we're calling `hasNativeState` and then
25+
// `getNativeState`). When we use `NativeState`, JSI doesn't need to do any
26+
// dynamic casts and we can do a single one on our own after the checks.
27+
if (!object.hasNativeState<jsi::NativeState>(rt)) {
28+
throw jsi::JSINativeException("Value is not a ShadowNode reference");
29+
}
30+
31+
auto nativeState = object.getNativeState<jsi::NativeState>(rt);
32+
auto shadowNodeWrapper =
33+
std::dynamic_pointer_cast<ShadowNodeWrapper>(nativeState);
34+
if (shadowNodeWrapper == nullptr ||
35+
shadowNodeWrapper->shadowNode == nullptr) {
36+
throw jsi::JSINativeException(
37+
"Value state is nullptr, expected a ShadowNode reference");
38+
}
39+
40+
return shadowNodeWrapper->shadowNode;
41+
}
42+
43+
static jsi::Value toJs(jsi::Runtime& rt, const ShadowNode::Shared& value) {
44+
jsi::Object obj(rt);
45+
obj.setNativeState(rt, std::make_shared<ShadowNodeWrapper>(value));
46+
return obj;
47+
}
48+
};
49+
50+
} // namespace facebook::react

0 commit comments

Comments
 (0)