diff --git a/packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.cpp b/packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.cpp index 79cf1bf09db..9305b112876 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #ifdef RN_DISABLE_OSS_PLUGIN_HEADER #include "Plugins.h" @@ -64,42 +63,36 @@ namespace facebook::react { NativeDOM::NativeDOM(std::shared_ptr jsInvoker) : NativeDOMCxxSpec(std::move(jsInvoker)) {} -std::optional NativeDOM::getParentNode( +jsi::Value NativeDOM::getParentNode( jsi::Runtime& rt, jsi::Value shadowNodeValue) { auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); auto currentRevision = getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - return std::nullopt; + return jsi::Value::undefined(); } auto parentShadowNode = dom::getParentNode(currentRevision, *shadowNode); if (parentShadowNode == nullptr) { - return std::nullopt; + return jsi::Value::undefined(); } return parentShadowNode->getInstanceHandle(rt); } -std::optional> NativeDOM::getChildNodes( +std::vector NativeDOM::getChildNodes( jsi::Runtime& rt, jsi::Value shadowNodeValue) { auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); auto currentRevision = getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - return std::nullopt; + return std::vector{}; } auto childNodes = dom::getChildNodes(currentRevision, *shadowNode); - - // There's no version of this node in the current shadow tree - if (!childNodes) { - return std::nullopt; - } - - return getArrayOfInstanceHandlesFromShadowNodes(childNodes.value(), rt); + return getArrayOfInstanceHandlesFromShadowNodes(childNodes, rt); } bool NativeDOM::isConnected(jsi::Runtime& rt, jsi::Value shadowNodeValue) { @@ -142,11 +135,11 @@ std::string NativeDOM::getTextContent( return dom::getTextContent(currentRevision, *shadowNode); } -std::optional> + /* height: */ double> NativeDOM::getBoundingClientRect( jsi::Runtime& rt, jsi::Value shadowNodeValue, @@ -155,89 +148,93 @@ NativeDOM::getBoundingClientRect( auto currentRevision = getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - return std::nullopt; + return {0, 0, 0, 0}; } - return dom::getBoundingClientRect( + auto domRect = dom::getBoundingClientRect( currentRevision, *shadowNode, includeTransform); + + return std::tuple{domRect.x, domRect.y, domRect.width, domRect.height}; } -std::optional> + /* left: */ double> NativeDOM::getOffset(jsi::Runtime& rt, jsi::Value shadowNodeValue) { auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); auto currentRevision = getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - return std::nullopt; + return {jsi::Value::undefined(), 0, 0}; } - auto offset = dom::getOffset(currentRevision, *shadowNode); - - if (!offset) { - return std::nullopt; - } - - auto& offsetValue = offset.value(); + auto domOffset = dom::getOffset(currentRevision, *shadowNode); return std::tuple{ - std::get<0>(offsetValue)->getInstanceHandle(rt), - std::get<1>(offsetValue), - std::get<2>(offsetValue)}; + domOffset.offsetParent == nullptr + ? jsi::Value::undefined() + : domOffset.offsetParent->getInstanceHandle(rt), + domOffset.top, + domOffset.left}; } -std::optional> +std::tuple NativeDOM::getScrollPosition(jsi::Runtime& rt, jsi::Value shadowNodeValue) { auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); auto currentRevision = getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - return std::nullopt; + return {0, 0}; } - return dom::getScrollPosition(currentRevision, *shadowNode); + auto domPoint = dom::getScrollPosition(currentRevision, *shadowNode); + return std::tuple{domPoint.x, domPoint.y}; } -std::optional> +std::tuple NativeDOM::getScrollSize(jsi::Runtime& rt, jsi::Value shadowNodeValue) { auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); auto currentRevision = getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - return std::nullopt; + return {0, 0}; } - return dom::getScrollSize(currentRevision, *shadowNode); + auto scrollSize = dom::getScrollSize(currentRevision, *shadowNode); + return std::tuple{scrollSize.width, scrollSize.height}; } -std::optional> -NativeDOM::getInnerSize(jsi::Runtime& rt, jsi::Value shadowNodeValue) { +std::tuple NativeDOM::getInnerSize( + jsi::Runtime& rt, + jsi::Value shadowNodeValue) { auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); auto currentRevision = getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - return std::nullopt; + return {0, 0}; } - return dom::getInnerSize(currentRevision, *shadowNode); + auto innerSize = dom::getInnerSize(currentRevision, *shadowNode); + return std::tuple{innerSize.width, innerSize.height}; } -std::optional> -NativeDOM::getBorderSize(jsi::Runtime& rt, jsi::Value shadowNodeValue) { + /* leftWidth: */ int> +NativeDOM::getBorderWidth(jsi::Runtime& rt, jsi::Value shadowNodeValue) { auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); auto currentRevision = getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - return std::nullopt; + return {0, 0, 0, 0}; } - return dom::getBorderSize(currentRevision, *shadowNode); + auto borderWidth = dom::getBorderWidth(currentRevision, *shadowNode); + return std::tuple{ + borderWidth.top, borderWidth.right, borderWidth.bottom, borderWidth.left}; } std::string NativeDOM::getTagName( diff --git a/packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.h b/packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.h index 31de8d7c07c..07c30d2e1a2 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.h +++ b/packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.h @@ -23,11 +23,9 @@ class NativeDOM : public NativeDOMCxxSpec { public: NativeDOM(std::shared_ptr jsInvoker); - std::optional getParentNode( - jsi::Runtime& rt, - jsi::Value shadowNodeValue); + jsi::Value getParentNode(jsi::Runtime& rt, jsi::Value shadowNodeValue); - std::optional> getChildNodes( + std::vector getChildNodes( jsi::Runtime& rt, jsi::Value shadowNodeValue); @@ -40,38 +38,39 @@ class NativeDOM : public NativeDOMCxxSpec { std::string getTextContent(jsi::Runtime& rt, jsi::Value shadowNodeValue); - std::optional> + /* height: */ double> getBoundingClientRect( jsi::Runtime& rt, jsi::Value shadowNodeValue, bool includeTransform); - std::optional> + /* left: */ double> getOffset(jsi::Runtime& rt, jsi::Value shadowNodeValue); - std::optional> + std::tuple getScrollPosition(jsi::Runtime& rt, jsi::Value shadowNodeValue); - std::optional> - getScrollSize(jsi::Runtime& rt, jsi::Value shadowNodeValue); - - std::optional> getInnerSize( + std::tuple getScrollSize( jsi::Runtime& rt, jsi::Value shadowNodeValue); - std::optional getInnerSize( + jsi::Runtime& rt, + jsi::Value shadowNodeValue); + + std::tuple< /* topWidth: */ int, /* rightWidth: */ int, /* bottomWidth: */ int, - /* leftWidth: */ int>> - getBorderSize(jsi::Runtime& rt, jsi::Value shadowNodeValue); + /* leftWidth: */ int> + getBorderWidth(jsi::Runtime& rt, jsi::Value shadowNodeValue); std::string getTagName(jsi::Runtime& rt, jsi::Value shadowNodeValue); diff --git a/packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp b/packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp index 89405542e1e..f97bceb6e8c 100644 --- a/packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp +++ b/packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace { @@ -170,13 +171,13 @@ ShadowNode::Shared getParentNode( return getParentShadowNodeInRevision(currentRevision, shadowNode); } -std::optional> getChildNodes( +std::vector getChildNodes( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode) { auto shadowNodeInCurrentRevision = getShadowNodeInRevision(currentRevision, shadowNode); if (shadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return {}; } return shadowNodeInCurrentRevision->getChildren(); @@ -251,20 +252,14 @@ std::string getTextContent( return result; } -std::optional> -getBoundingClientRect( +DOMRect getBoundingClientRect( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode, bool includeTransform) { auto shadowNodeInCurrentRevision = getShadowNodeInRevision(currentRevision, shadowNode); if (shadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return DOMRect{}; } auto layoutMetrics = getRelativeLayoutMetrics( @@ -273,20 +268,18 @@ getBoundingClientRect( {.includeTransform = includeTransform, .includeViewportOffset = true}); if (layoutMetrics == EmptyLayoutMetrics) { - return std::nullopt; + return DOMRect{}; } auto frame = layoutMetrics.frame; - return std::tuple{ - frame.origin.x, frame.origin.y, frame.size.width, frame.size.height}; + return DOMRect{ + .x = frame.origin.x, + .y = frame.origin.y, + .width = frame.size.width, + .height = frame.size.height}; } -std::optional> -getOffset( +DOMOffset getOffset( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode) { auto shadowNodeInCurrentRevision = @@ -298,7 +291,7 @@ getOffset( // root node if (shadowNodeInCurrentRevision == nullptr || positionedAncestorOfShadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return DOMOffset{}; } // If the node is not displayed (itself or any of its ancestors has @@ -306,7 +299,7 @@ getOffset( auto shadowNodeLayoutMetricsRelativeToRoot = getRelativeLayoutMetrics( *currentRevision, shadowNode, {.includeTransform = false}); if (shadowNodeLayoutMetricsRelativeToRoot == EmptyLayoutMetrics) { - return std::nullopt; + return DOMOffset{}; } auto positionedAncestorLayoutMetricsRelativeToRoot = getRelativeLayoutMetrics( @@ -314,7 +307,7 @@ getOffset( *positionedAncestorOfShadowNodeInCurrentRevision, {.includeTransform = false}); if (positionedAncestorLayoutMetricsRelativeToRoot == EmptyLayoutMetrics) { - return std::nullopt; + return DOMOffset{}; } auto shadowNodeOriginRelativeToRoot = @@ -331,18 +324,19 @@ getOffset( positionedAncestorOriginRelativeToRoot.x - positionedAncestorLayoutMetricsRelativeToRoot.borderWidth.left; - return std::tuple{ - positionedAncestorOfShadowNodeInCurrentRevision, offsetTop, offsetLeft}; + return DOMOffset{ + .offsetParent = positionedAncestorOfShadowNodeInCurrentRevision, + .top = offsetTop, + .left = offsetLeft}; } -std::optional> -getScrollPosition( +DOMPoint getScrollPosition( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode) { auto shadowNodeInCurrentRevision = getShadowNodeInRevision(currentRevision, shadowNode); if (shadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return DOMPoint{}; } // If the node is not displayed (itself or any of its ancestors has @@ -353,31 +347,30 @@ getScrollPosition( {.includeTransform = true}); if (layoutMetrics == EmptyLayoutMetrics) { - return std::nullopt; + return DOMPoint{}; } auto layoutableShadowNode = dynamic_cast( shadowNodeInCurrentRevision.get()); // This should never happen if (layoutableShadowNode == nullptr) { - return std::nullopt; + return DOMPoint{}; } auto scrollPosition = layoutableShadowNode->getContentOriginOffset(); - return std::tuple{ - scrollPosition.x == 0 ? 0 : -scrollPosition.x, - scrollPosition.y == 0 ? 0 : -scrollPosition.y}; + return DOMPoint{ + .x = scrollPosition.x == 0 ? 0 : -scrollPosition.x, + .y = scrollPosition.y == 0 ? 0 : -scrollPosition.y}; } -std::optional> -getScrollSize( +DOMSizeRounded getScrollSize( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode) { auto shadowNodeInCurrentRevision = getShadowNodeInRevision(currentRevision, shadowNode); if (shadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return DOMSizeRounded{}; } // If the node is not displayed (itself or any of its ancestors has @@ -389,31 +382,32 @@ getScrollSize( if (layoutMetrics == EmptyLayoutMetrics || layoutMetrics.displayType == DisplayType::Inline) { - return std::nullopt; + return DOMSizeRounded{}; } auto layoutableShadowNode = dynamic_cast( shadowNodeInCurrentRevision.get()); // This should never happen if (layoutableShadowNode == nullptr) { - return std::nullopt; + return DOMSizeRounded{}; } Size scrollSize = getScrollableContentBounds( layoutableShadowNode->getContentBounds(), layoutMetrics) .size; - return std::tuple{ - std::round(scrollSize.width), std::round(scrollSize.height)}; + return DOMSizeRounded{ + .width = static_cast(std::round(scrollSize.width)), + .height = static_cast(std::round(scrollSize.height))}; } -std::optional> getInnerSize( +DOMSizeRounded getInnerSize( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode) { auto shadowNodeInCurrentRevision = getShadowNodeInRevision(currentRevision, shadowNode); if (shadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return DOMSizeRounded{}; } // If the node is not displayed (itself or any of its ancestors has @@ -425,29 +419,23 @@ std::optional> getInnerSize( if (layoutMetrics == EmptyLayoutMetrics || layoutMetrics.displayType == DisplayType::Inline) { - return std::nullopt; + return DOMSizeRounded{}; } auto paddingFrame = layoutMetrics.getPaddingFrame(); - return std::tuple{ - std::round(paddingFrame.size.width), - std::round(paddingFrame.size.height)}; + return DOMSizeRounded{ + .width = static_cast(std::round(paddingFrame.size.width)), + .height = static_cast(std::round(paddingFrame.size.height))}; } -std::optional> -getBorderSize( +DOMBorderWidthRounded getBorderWidth( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode) { auto shadowNodeInCurrentRevision = getShadowNodeInRevision(currentRevision, shadowNode); if (shadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return DOMBorderWidthRounded{}; } // If the node is not displayed (itself or any of its ancestors has @@ -459,14 +447,14 @@ getBorderSize( if (layoutMetrics == EmptyLayoutMetrics || layoutMetrics.displayType == DisplayType::Inline) { - return std::nullopt; + return DOMBorderWidthRounded{}; } - return std::tuple{ - std::round(layoutMetrics.borderWidth.top), - std::round(layoutMetrics.borderWidth.right), - std::round(layoutMetrics.borderWidth.bottom), - std::round(layoutMetrics.borderWidth.left)}; + return DOMBorderWidthRounded{ + .top = static_cast(std::round(layoutMetrics.borderWidth.top)), + .right = static_cast(std::round(layoutMetrics.borderWidth.right)), + .bottom = static_cast(std::round(layoutMetrics.borderWidth.bottom)), + .left = static_cast(std::round(layoutMetrics.borderWidth.left))}; } std::string getTagName(const ShadowNode& shadowNode) { @@ -486,20 +474,13 @@ std::string getTagName(const ShadowNode& shadowNode) { return canonicalComponentName; } -std::optional> -measure( +RNMeasureRect measure( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode) { auto shadowNodeInCurrentRevision = getShadowNodeInRevision(currentRevision, shadowNode); if (shadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return RNMeasureRect{}; } auto layoutMetrics = getRelativeLayoutMetrics( @@ -508,7 +489,7 @@ measure( {.includeTransform = true, .includeViewportOffset = false}); if (layoutMetrics == EmptyLayoutMetrics) { - return std::nullopt; + return RNMeasureRect{}; } auto layoutableShadowNode = dynamic_cast( @@ -519,27 +500,22 @@ measure( auto frame = layoutMetrics.frame; - return std::tuple{ - (double)originRelativeToParent.x, - (double)originRelativeToParent.y, - (double)frame.size.width, - (double)frame.size.height, - (double)frame.origin.x, - (double)frame.origin.y}; + return RNMeasureRect{ + .x = originRelativeToParent.x, + .y = originRelativeToParent.y, + .width = frame.size.width, + .height = frame.size.height, + .pageX = frame.origin.x, + .pageY = frame.origin.y}; } -std::optional> -measureInWindow( +DOMRect measureInWindow( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode) { auto shadowNodeInCurrentRevision = getShadowNodeInRevision(currentRevision, shadowNode); if (shadowNodeInCurrentRevision == nullptr) { - return std::nullopt; + return DOMRect{}; } auto layoutMetrics = getRelativeLayoutMetrics( @@ -548,24 +524,19 @@ measureInWindow( {.includeTransform = true, .includeViewportOffset = true}); if (layoutMetrics == EmptyLayoutMetrics) { - return std::nullopt; + return DOMRect{}; } auto frame = layoutMetrics.frame; - return std::tuple{ - (double)frame.origin.x, - (double)frame.origin.y, - (double)frame.size.width, - (double)frame.size.height, + return DOMRect{ + .x = frame.origin.x, + .y = frame.origin.y, + .width = frame.size.width, + .height = frame.size.height, }; } -std::optional> -measureLayout( +std::optional measureLayout( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode, const ShadowNode& relativeToShadowNode) { @@ -592,11 +563,11 @@ measureLayout( auto frame = layoutMetrics.frame; - return std::tuple{ - (double)frame.origin.x, - (double)frame.origin.y, - (double)frame.size.width, - (double)frame.size.height, + return DOMRect{ + .x = frame.origin.x, + .y = frame.origin.y, + .width = frame.size.width, + .height = frame.size.height, }; } diff --git a/packages/react-native/ReactCommon/react/renderer/dom/DOM.h b/packages/react-native/ReactCommon/react/renderer/dom/DOM.h index 9952d6d5b19..bd793096082 100644 --- a/packages/react-native/ReactCommon/react/renderer/dom/DOM.h +++ b/packages/react-native/ReactCommon/react/renderer/dom/DOM.h @@ -10,18 +10,56 @@ #include #include #include -#include #include #include #include namespace facebook::react::dom { +struct DOMRect { + double x = 0; + double y = 0; + double width = 0; + double height = 0; +}; + +struct RNMeasureRect { + double x = 0; + double y = 0; + double width = 0; + double height = 0; + double pageX = 0; + double pageY = 0; +}; + +struct DOMOffset { + ShadowNode::Shared offsetParent = nullptr; + double top = 0; + double left = 0; +}; + +struct DOMPoint { + double x = 0; + double y = 0; +}; + +struct DOMSizeRounded { + int width = 0; + int height = 0; +}; + +struct DOMBorderWidthRounded { + int top = 0; + int right = 0; + int bottom = 0; + int left = 0; +}; + ShadowNode::Shared getParentNode( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); -std::optional> getChildNodes( +std::vector getChildNodes( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); @@ -38,47 +76,28 @@ std::string getTextContent( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); -std::optional> -getBoundingClientRect( +DOMRect getBoundingClientRect( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode, bool includeTransform); -std::optional> -getOffset( +DOMOffset getOffset( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); -std::optional> -getScrollPosition( +DOMPoint getScrollPosition( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); -std::optional> -getScrollSize( +DOMSizeRounded getScrollSize( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); -std::optional> getInnerSize( +DOMSizeRounded getInnerSize( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); -std::optional> -getBorderSize( +DOMBorderWidthRounded getBorderWidth( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); @@ -86,32 +105,17 @@ std::string getTagName(const ShadowNode& shadowNode); // Non-standard methods from React Native -std::optional> -measure( +RNMeasureRect measure( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); -std::optional> -measureInWindow( +DOMRect measureInWindow( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode); -std::optional> -measureLayout( +// This method returns an optional to signal to go through the error callback +// instead of going through the success callback with an empty DOMRect. +std::optional measureLayout( const RootShadowNode::Shared& currentRevision, const ShadowNode& shadowNode, const ShadowNode& relativeToShadowNode); diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 64a271011cf..6a618691d13 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -670,22 +670,22 @@ jsi::Value UIManagerBinding::get( return jsi::Value::undefined(); } - auto result = dom::measureLayout( + auto maybeRect = dom::measureLayout( currentRevision, *shadowNode, *relativeToShadowNode); - if (!result) { + if (!maybeRect) { onFailFunction.call(runtime); return jsi::Value::undefined(); } - auto [x, y, width, height] = result.value(); + auto rect = maybeRect.value(); onSuccessFunction.call( runtime, - {jsi::Value{runtime, x}, - jsi::Value{runtime, y}, - jsi::Value{runtime, width}, - jsi::Value{runtime, height}}); + {jsi::Value{runtime, rect.x}, + jsi::Value{runtime, rect.y}, + jsi::Value{runtime, rect.width}, + jsi::Value{runtime, rect.height}}); return jsi::Value::undefined(); }); } @@ -715,23 +715,16 @@ jsi::Value UIManagerBinding::get( return jsi::Value::undefined(); } - auto result = dom::measure(currentRevision, *shadowNode); - - if (!result) { - callbackFunction.call(runtime, {0, 0, 0, 0, 0, 0}); - return jsi::Value::undefined(); - } - - auto [x, y, width, height, pageX, pageY] = result.value(); + auto measureRect = dom::measure(currentRevision, *shadowNode); callbackFunction.call( runtime, - {jsi::Value{runtime, x}, - jsi::Value{runtime, y}, - jsi::Value{runtime, width}, - jsi::Value{runtime, height}, - jsi::Value{runtime, pageX}, - jsi::Value{runtime, pageY}}); + {jsi::Value{runtime, measureRect.x}, + jsi::Value{runtime, measureRect.y}, + jsi::Value{runtime, measureRect.width}, + jsi::Value{runtime, measureRect.height}, + jsi::Value{runtime, measureRect.pageX}, + jsi::Value{runtime, measureRect.pageY}}); return jsi::Value::undefined(); }); } @@ -758,24 +751,17 @@ jsi::Value UIManagerBinding::get( shadowNode->getSurfaceId()); if (currentRevision == nullptr) { - callbackFunction.call(runtime, {0, 0, 0, 0, 0, 0}); + callbackFunction.call(runtime, {0, 0, 0, 0}); return jsi::Value::undefined(); } - auto result = dom::measureInWindow(currentRevision, *shadowNode); - if (!result) { - callbackFunction.call(runtime, {0, 0, 0, 0, 0, 0}); - return jsi::Value::undefined(); - } - - auto [x, y, width, height] = result.value(); - + auto rect = dom::measureInWindow(currentRevision, *shadowNode); callbackFunction.call( runtime, - {jsi::Value{runtime, x}, - jsi::Value{runtime, y}, - jsi::Value{runtime, width}, - jsi::Value{runtime, height}}); + {jsi::Value{runtime, rect.x}, + jsi::Value{runtime, rect.y}, + jsi::Value{runtime, rect.width}, + jsi::Value{runtime, rect.height}}); return jsi::Value::undefined(); }); } @@ -897,21 +883,15 @@ jsi::Value UIManagerBinding::get( return jsi::Value::undefined(); } - auto result = dom::getBoundingClientRect( + auto domRect = dom::getBoundingClientRect( currentRevision, *shadowNode, includeTransform); - if (!result) { - return jsi::Value::undefined(); - } - - auto [x, y, width, height] = result.value(); - return jsi::Array::createWithElements( runtime, - jsi::Value{runtime, x}, - jsi::Value{runtime, y}, - jsi::Value{runtime, width}, - jsi::Value{runtime, height}); + jsi::Value{runtime, domRect.x}, + jsi::Value{runtime, domRect.y}, + jsi::Value{runtime, domRect.width}, + jsi::Value{runtime, domRect.height}); }); } diff --git a/packages/react-native/src/private/webapis/dom/nodes/ReactNativeElement.js b/packages/react-native/src/private/webapis/dom/nodes/ReactNativeElement.js index de582ddb5cd..91affdae817 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/ReactNativeElement.js +++ b/packages/react-native/src/private/webapis/dom/nodes/ReactNativeElement.js @@ -69,9 +69,7 @@ export default class ReactNativeElement if (node != null) { const offset = NativeDOM.getOffset(node); - if (offset != null) { - return Math.round(offset[2]); - } + return Math.round(offset[2]); } return 0; @@ -85,7 +83,7 @@ export default class ReactNativeElement // For children of the root node we currently return offset data // but a `null` parent because the root node is not accessible // in JavaScript yet. - if (offset != null && offset[0] != null) { + if (offset[0] != null) { const offsetParentInstanceHandle = offset[0]; const offsetParent = getPublicInstanceFromInternalInstanceHandle( offsetParentInstanceHandle, @@ -104,9 +102,7 @@ export default class ReactNativeElement if (node != null) { const offset = NativeDOM.getOffset(node); - if (offset != null) { - return Math.round(offset[1]); - } + return Math.round(offset[1]); } return 0; diff --git a/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js b/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js index 9db3d7a3735..7ec84af850a 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js +++ b/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js @@ -36,9 +36,7 @@ export default class ReadOnlyElement extends ReadOnlyNode { if (node != null) { const innerSize = NativeDOM.getInnerSize(node); - if (innerSize != null) { - return innerSize[1]; - } + return innerSize[1]; } return 0; @@ -48,10 +46,8 @@ export default class ReadOnlyElement extends ReadOnlyNode { const node = getShadowNode(this); if (node != null) { - const borderSize = NativeDOM.getBorderSize(node); - if (borderSize != null) { - return borderSize[3]; - } + const borderSize = NativeDOM.getBorderWidth(node); + return borderSize[3]; } return 0; @@ -61,10 +57,8 @@ export default class ReadOnlyElement extends ReadOnlyNode { const node = getShadowNode(this); if (node != null) { - const borderSize = NativeDOM.getBorderSize(node); - if (borderSize != null) { - return borderSize[0]; - } + const borderSize = NativeDOM.getBorderWidth(node); + return borderSize[0]; } return 0; @@ -75,9 +69,7 @@ export default class ReadOnlyElement extends ReadOnlyNode { if (node != null) { const innerSize = NativeDOM.getInnerSize(node); - if (innerSize != null) { - return innerSize[0]; - } + return innerSize[0]; } return 0; @@ -138,9 +130,7 @@ export default class ReadOnlyElement extends ReadOnlyNode { if (node != null) { const scrollSize = NativeDOM.getScrollSize(node); - if (scrollSize != null) { - return scrollSize[1]; - } + return scrollSize[1]; } return 0; @@ -151,9 +141,7 @@ export default class ReadOnlyElement extends ReadOnlyNode { if (node != null) { const scrollPosition = NativeDOM.getScrollPosition(node); - if (scrollPosition != null) { - return scrollPosition[0]; - } + return scrollPosition[0]; } return 0; @@ -164,9 +152,7 @@ export default class ReadOnlyElement extends ReadOnlyNode { if (node != null) { const scrollPosition = NativeDOM.getScrollPosition(node); - if (scrollPosition != null) { - return scrollPosition[1]; - } + return scrollPosition[1]; } return 0; @@ -177,9 +163,7 @@ export default class ReadOnlyElement extends ReadOnlyNode { if (node != null) { const scrollSize = NativeDOM.getScrollSize(node); - if (scrollSize != null) { - return scrollSize[0]; - } + return scrollSize[0]; } return 0; @@ -255,10 +239,7 @@ export function getBoundingClientRect( if (shadowNode != null) { const rect = NativeDOM.getBoundingClientRect(shadowNode, includeTransform); - - if (rect) { - return new DOMRect(rect[0], rect[1], rect[2], rect[3]); - } + return new DOMRect(rect[0], rect[1], rect[2], rect[3]); } // Empty rect if any of the above failed diff --git a/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js b/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js index 45ec0ab7f6f..e86862d6c6b 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js +++ b/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js @@ -318,13 +318,6 @@ export function getChildNodes( } const childNodeInstanceHandles = NativeDOM.getChildNodes(shadowNode); - if ( - childNodeInstanceHandles == null || - childNodeInstanceHandles.length === 0 - ) { - return []; - } - return childNodeInstanceHandles .map(instanceHandle => getPublicInstanceFromInternalInstanceHandle(instanceHandle), diff --git a/packages/react-native/src/private/webapis/dom/nodes/specs/NativeDOM.js b/packages/react-native/src/private/webapis/dom/nodes/specs/NativeDOM.js index a6aa62ceada..c1ca2aeef84 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/specs/NativeDOM.js +++ b/packages/react-native/src/private/webapis/dom/nodes/specs/NativeDOM.js @@ -20,11 +20,11 @@ import nullthrows from 'nullthrows'; export interface Spec extends TurboModule { +getParentNode: ( shadowNode: mixed /* ShadowNode */, - ) => ?mixed /* ?InstanceHandle */; + ) => mixed /* ?InstanceHandle */; +getChildNodes: ( shadowNode: mixed /* ShadowNode */, - ) => ?$ReadOnlyArray /* ?$ReadOnlyArray */; + ) => $ReadOnlyArray /* $ReadOnlyArray */; +isConnected: (shadowNode: mixed /* ShadowNode */) => boolean; @@ -38,27 +38,27 @@ export interface Spec extends TurboModule { +getBoundingClientRect: ( shadowNode: mixed /* ShadowNode */, includeTransform: boolean, - ) => ?$ReadOnlyArray /* ?[x: number, y: number, width: number, height: number] */; + ) => $ReadOnlyArray /* [x: number, y: number, width: number, height: number] */; +getOffset: ( shadowNode: mixed /* ShadowNode */, - ) => ?$ReadOnlyArray /* ?[offsetParent: InstanceHandle, top: number, left: number] */; + ) => $ReadOnlyArray /* [offsetParent: ?InstanceHandle, top: number, left: number] */; +getScrollPosition: ( shadowNode: mixed /* ShadowNode */, - ) => ?$ReadOnlyArray /* ?[scrollLeft: number, scrollTop: number] */; + ) => $ReadOnlyArray /* [scrollLeft: number, scrollTop: number] */; +getScrollSize: ( shadowNode: mixed /* ShadowNode */, - ) => ?$ReadOnlyArray /* ?[scrollWidth: number, scrollHeight: number] */; + ) => $ReadOnlyArray /* [scrollWidth: number, scrollHeight: number] */; +getInnerSize: ( shadowNode: mixed /* ShadowNode */, - ) => ?$ReadOnlyArray /* ?[width: number, height: number] */; + ) => $ReadOnlyArray /* [width: number, height: number] */; - +getBorderSize: ( + +getBorderWidth: ( shadowNode: mixed /* ShadowNode */, - ) => ?$ReadOnlyArray /* ?[topWidth: number, rightWidth: number, bottomWidth: number, leftWidth: number] */; + ) => $ReadOnlyArray /* [topWidth: number, rightWidth: number, bottomWidth: number, leftWidth: number] */; +getTagName: (shadowNode: mixed /* ShadowNode */) => string; @@ -101,7 +101,7 @@ export interface RefinedSpec { * of an active shadow tree, it returns an array of instance handles of its * children. Otherwise, it returns an empty array. */ - +getChildNodes: (shadowNode: ShadowNode) => ?$ReadOnlyArray; + +getChildNodes: (shadowNode: ShadowNode) => $ReadOnlyArray; /** * This is a React Native implementation of `Node.prototype.isConnected` @@ -153,7 +153,7 @@ export interface RefinedSpec { +getBoundingClientRect: ( shadowNode: ShadowNode, includeTransform: boolean, - ) => ?$ReadOnly< + ) => $ReadOnly< [ /* x: */ number, /* y: */ number, @@ -178,8 +178,12 @@ export interface RefinedSpec { */ +getOffset: ( shadowNode: ShadowNode, - ) => ?$ReadOnly< - [/* offsetParent: */ InstanceHandle, /* top: */ number, /* left: */ number], + ) => $ReadOnly< + [ + /* offsetParent: */ ?InstanceHandle, + /* top: */ number, + /* left: */ number, + ], >; /** @@ -195,7 +199,7 @@ export interface RefinedSpec { */ +getScrollPosition: ( shadowNode: ShadowNode, - ) => ?$ReadOnly<[/* scrollLeft: */ number, /* scrollTop: */ number]>; + ) => $ReadOnly<[/* scrollLeft: */ number, /* scrollTop: */ number]>; /** * @@ -211,7 +215,7 @@ export interface RefinedSpec { */ +getScrollSize: ( shadowNode: ShadowNode, - ) => ?$ReadOnly<[/* scrollWidth: */ number, /* scrollHeight: */ number]>; + ) => $ReadOnly<[/* scrollWidth: */ number, /* scrollHeight: */ number]>; /** * This is a method to access the inner size of a shadow node, to implement @@ -227,7 +231,7 @@ export interface RefinedSpec { */ +getInnerSize: ( shadowNode: ShadowNode, - ) => ?$ReadOnly<[/* width: */ number, /* height: */ number]>; + ) => $ReadOnly<[/* width: */ number, /* height: */ number]>; /** * This is a method to access the border size of a shadow node, to implement @@ -241,9 +245,9 @@ export interface RefinedSpec { * it has an inline display, it returns `undefined`. Otherwise, it returns its * border size. */ - +getBorderSize: ( + +getBorderWidth: ( shadowNode: ShadowNode, - ) => ?$ReadOnly< + ) => $ReadOnly< [ /* topWidth: */ number, /* rightWidth: */ number, @@ -281,7 +285,7 @@ const NativeDOM: RefinedSpec = { // $FlowExpectedError[incompatible-cast] return (nullthrows(RawNativeDOM).getChildNodes( shadowNode, - ): ?$ReadOnlyArray); + ): $ReadOnlyArray); }, isConnected(shadowNode) { @@ -304,7 +308,7 @@ const NativeDOM: RefinedSpec = { return (nullthrows(RawNativeDOM).getBoundingClientRect( shadowNode, includeTransform, - ): ?$ReadOnly< + ): $ReadOnly< [ /* x: */ number, /* y: */ number, @@ -316,9 +320,9 @@ const NativeDOM: RefinedSpec = { getOffset(shadowNode) { // $FlowExpectedError[incompatible-cast] - return (nullthrows(RawNativeDOM).getOffset(shadowNode): ?$ReadOnly< + return (nullthrows(RawNativeDOM).getOffset(shadowNode): $ReadOnly< [ - /* offsetParent: */ InstanceHandle, + /* offsetParent: */ ?InstanceHandle, /* top: */ number, /* left: */ number, ], @@ -327,28 +331,28 @@ const NativeDOM: RefinedSpec = { getScrollPosition(shadowNode) { // $FlowExpectedError[incompatible-cast] - return (nullthrows(RawNativeDOM).getScrollPosition(shadowNode): ?$ReadOnly< + return (nullthrows(RawNativeDOM).getScrollPosition(shadowNode): $ReadOnly< [/* scrollLeft: */ number, /* scrollTop: */ number], >); }, getScrollSize(shadowNode) { // $FlowExpectedError[incompatible-cast] - return (nullthrows(RawNativeDOM).getScrollSize(shadowNode): ?$ReadOnly< + return (nullthrows(RawNativeDOM).getScrollSize(shadowNode): $ReadOnly< [/* scrollWidth: */ number, /* scrollHeight: */ number], >); }, getInnerSize(shadowNode) { // $FlowExpectedError[incompatible-cast] - return (nullthrows(RawNativeDOM).getInnerSize(shadowNode): ?$ReadOnly< + return (nullthrows(RawNativeDOM).getInnerSize(shadowNode): $ReadOnly< [/* width: */ number, /* height: */ number], >); }, - getBorderSize(shadowNode) { + getBorderWidth(shadowNode) { // $FlowExpectedError[incompatible-cast] - return (nullthrows(RawNativeDOM).getBorderSize(shadowNode): ?$ReadOnly< + return (nullthrows(RawNativeDOM).getBorderWidth(shadowNode): $ReadOnly< [ /* topWidth: */ number, /* rightWidth: */ number, diff --git a/packages/react-native/src/private/webapis/dom/nodes/specs/__mocks__/NativeDOMMock.js b/packages/react-native/src/private/webapis/dom/nodes/specs/__mocks__/NativeDOMMock.js index 8f6c64f4ee4..106d4d26ac5 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/specs/__mocks__/NativeDOMMock.js +++ b/packages/react-native/src/private/webapis/dom/nodes/specs/__mocks__/NativeDOMMock.js @@ -46,7 +46,7 @@ const NativeDOMMock: NativeDOM = { ( node: Node, includeTransform: boolean, - ): ?[ + ): [ /* x:*/ number, /* y:*/ number, /* width:*/ number, @@ -58,7 +58,7 @@ const NativeDOMMock: NativeDOM = { const currentProps = nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null; if (currentProps == null) { - return null; + return [0, 0, 0, 0]; } const boundingClientRectForTests: ?{ @@ -71,7 +71,7 @@ const NativeDOMMock: NativeDOM = { currentProps.__boundingClientRectForTests; if (boundingClientRectForTests == null) { - return null; + return [0, 0, 0, 0]; } const {x, y, width, height} = boundingClientRectForTests; @@ -193,14 +193,14 @@ const NativeDOMMock: NativeDOM = { getOffset: jest.fn( ( node: Node, - ): ?[ - /* offsetParent: */ InternalInstanceHandle, + ): [ + /* offsetParent: */ ?InternalInstanceHandle, /* offsetTop: */ number, /* offsetLeft: */ number, ] => { const ancestors = getAncestorsInCurrentTree(node); if (ancestors == null) { - return null; + return [null, 0, 0]; } const [parent, position] = ancestors[ancestors.length - 1]; @@ -209,7 +209,7 @@ const NativeDOMMock: NativeDOM = { const currentProps = nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null; if (currentProps == null || hasDisplayNone(nodeInCurrentTree)) { - return null; + return [null, 0, 0]; } const offsetForTests: ?{ @@ -220,7 +220,7 @@ const NativeDOMMock: NativeDOM = { currentProps.__offsetForTests; if (offsetForTests == null) { - return null; + return [null, 0, 0]; } let currentIndex = ancestors.length - 1; @@ -230,7 +230,7 @@ const NativeDOMMock: NativeDOM = { if (currentIndex >= 0) { // The node or one of its ancestors have display: none - return null; + return [null, 0, 0]; } return [ @@ -242,14 +242,14 @@ const NativeDOMMock: NativeDOM = { ), getScrollPosition: jest.fn( - (node: Node): ?[/* scrollLeft: */ number, /* scrollTop: */ number] => { + (node: Node): [/* scrollLeft: */ number, /* scrollTop: */ number] => { ensureHostNode(node); const nodeInCurrentTree = getNodeInCurrentTree(node); const currentProps = nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null; if (currentProps == null) { - return null; + return [0, 0]; } const scrollForTests: ?{ @@ -261,7 +261,7 @@ const NativeDOMMock: NativeDOM = { currentProps.__scrollForTests; if (scrollForTests == null) { - return null; + return [0, 0]; } const {scrollLeft, scrollTop} = scrollForTests; @@ -270,14 +270,14 @@ const NativeDOMMock: NativeDOM = { ), getScrollSize: jest.fn( - (node: Node): ?[/* scrollLeft: */ number, /* scrollTop: */ number] => { + (node: Node): [/* scrollLeft: */ number, /* scrollTop: */ number] => { ensureHostNode(node); const nodeInCurrentTree = getNodeInCurrentTree(node); const currentProps = nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null; if (currentProps == null) { - return null; + return [0, 0]; } const scrollForTests: ?{ @@ -289,7 +289,7 @@ const NativeDOMMock: NativeDOM = { currentProps.__scrollForTests; if (scrollForTests == null) { - return null; + return [0, 0]; } const {scrollWidth, scrollHeight} = scrollForTests; @@ -298,14 +298,14 @@ const NativeDOMMock: NativeDOM = { ), getInnerSize: jest.fn( - (node: Node): ?[/* width: */ number, /* height: */ number] => { + (node: Node): [/* width: */ number, /* height: */ number] => { ensureHostNode(node); const nodeInCurrentTree = getNodeInCurrentTree(node); const currentProps = nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null; if (currentProps == null) { - return null; + return [0, 0]; } const innerSizeForTests: ?{ @@ -317,7 +317,7 @@ const NativeDOMMock: NativeDOM = { currentProps.__innerSizeForTests; if (innerSizeForTests == null) { - return null; + return [0, 0]; } const {width, height} = innerSizeForTests; @@ -325,10 +325,10 @@ const NativeDOMMock: NativeDOM = { }, ), - getBorderSize: jest.fn( + getBorderWidth: jest.fn( ( node: Node, - ): ?[ + ): [ /* topWidth: */ number, /* rightWidth: */ number, /* bottomWidth: */ number, @@ -340,7 +340,7 @@ const NativeDOMMock: NativeDOM = { const currentProps = nodeInCurrentTree != null ? fromNode(nodeInCurrentTree).props : null; if (currentProps == null) { - return null; + return [0, 0, 0, 0]; } const borderSizeForTests: ?{ @@ -354,7 +354,7 @@ const NativeDOMMock: NativeDOM = { currentProps.__borderSizeForTests; if (borderSizeForTests == null) { - return null; + return [0, 0, 0, 0]; } const {