From 5957d0af6944d64513cead28186dfbcc74bbfea0 Mon Sep 17 00:00:00 2001 From: Jon Thysell Date: Wed, 8 Jan 2025 14:00:40 -0800 Subject: [PATCH] Stop disabling warning 4244 because BinSkim fails if it sees one (#14258) ## Description This PR removes all instances where we ignore warning 4244 (loss of data when casting double to int) because BinSkim won't let us pass compliance when that happens. ### Type of Change - Bug fix (non-breaking change which fixes an issue) ### Why Compliance, fix publish, see above. Closes #14251 ### What See above. ## Screenshots N/A ## Testing N/A ## Changelog Should this change be included in the release notes: _yes_ Stop disabling warning 4244 because BinSkim fails if it sees one --- ...-30444064-215c-45d3-aaa7-9c10ae68e203.json | 7 + .../Composition/ContentIslandComponentView.h | 2 +- .../Fabric/Composition/ImageComponentView.h | 2 +- .../react/nativemodule/dom/NativeDOM.cpp | 358 ++++++++++++++++++ vnext/Shared/Shared.vcxitems | 2 +- vnext/overrides.json | 7 + 6 files changed, 375 insertions(+), 3 deletions(-) create mode 100644 change/react-native-windows-30444064-215c-45d3-aaa7-9c10ae68e203.json create mode 100644 vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/dom/NativeDOM.cpp diff --git a/change/react-native-windows-30444064-215c-45d3-aaa7-9c10ae68e203.json b/change/react-native-windows-30444064-215c-45d3-aaa7-9c10ae68e203.json new file mode 100644 index 00000000000..39c9d7dc261 --- /dev/null +++ b/change/react-native-windows-30444064-215c-45d3-aaa7-9c10ae68e203.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Stop disabling warning 4244 because BinSkim fails if it sees one", + "packageName": "react-native-windows", + "email": "jthysell@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h index ae252c9bb61..fce95ffb076 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h @@ -13,7 +13,7 @@ #include "CompositionViewComponentView.h" #pragma warning(push) -#pragma warning(disable : 4244 4305) +#pragma warning(disable : 4305) #include #pragma warning(pop) #include "Composition.ContentIslandComponentView.g.h" diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h index 829aca4f383..cb450f5aa4e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h @@ -17,7 +17,7 @@ #include "ImageResponseImage.h" #pragma warning(push) -#pragma warning(disable : 4244 4305) +#pragma warning(disable : 4305) #include #pragma warning(pop) #include "Composition.ImageComponentView.g.h" diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/dom/NativeDOM.cpp b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/dom/NativeDOM.cpp new file mode 100644 index 00000000000..7fbf8b52ebf --- /dev/null +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/dom/NativeDOM.cpp @@ -0,0 +1,358 @@ +/* + * 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. + */ + +#include "NativeDOM.h" +#include +#include +#include +#include + +#ifdef RN_DISABLE_OSS_PLUGIN_HEADER +#include "Plugins.h" +#endif + +std::shared_ptr NativeDOMModuleProvider( + std::shared_ptr jsInvoker) { + return std::make_shared(std::move(jsInvoker)); +} + +namespace facebook::react { + +#pragma mark - Private helpers + +static RootShadowNode::Shared getCurrentShadowTreeRevision( + facebook::jsi::Runtime& runtime, + SurfaceId surfaceId) { + auto& uiManager = + facebook::react::UIManagerBinding::getBinding(runtime)->getUIManager(); + auto shadowTreeRevisionProvider = uiManager.getShadowTreeRevisionProvider(); + return shadowTreeRevisionProvider->getCurrentRevision(surfaceId); +} + +static facebook::react::PointerEventsProcessor& +getPointerEventsProcessorFromRuntime(facebook::jsi::Runtime& runtime) { + return facebook::react::UIManagerBinding::getBinding(runtime) + ->getPointerEventsProcessor(); +} + +static std::vector +getArrayOfInstanceHandlesFromShadowNodes( + const ShadowNode::ListOfShared& nodes, + facebook::jsi::Runtime& runtime) { + // JSI doesn't support adding elements to an array after creation, + // so we need to accumulate the values in a vector and then create + // the array when we know the size. + std::vector nonNullInstanceHandles; + nonNullInstanceHandles.reserve(nodes.size()); + for (const auto& shadowNode : nodes) { + auto instanceHandle = (*shadowNode).getInstanceHandle(runtime); + if (!instanceHandle.isNull()) { + nonNullInstanceHandles.push_back(std::move(instanceHandle)); + } + } + + return nonNullInstanceHandles; +} + +#pragma mark - NativeDOM + +NativeDOM::NativeDOM(std::shared_ptr jsInvoker) + : NativeDOMCxxSpec(std::move(jsInvoker)) {} + +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 jsi::Value::undefined(); + } + + auto parentShadowNode = dom::getParentNode(currentRevision, *shadowNode); + if (parentShadowNode == nullptr) { + return jsi::Value::undefined(); + } + + return parentShadowNode->getInstanceHandle(rt); +} + +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::vector{}; + } + + auto childNodes = dom::getChildNodes(currentRevision, *shadowNode); + return getArrayOfInstanceHandlesFromShadowNodes(childNodes, rt); +} + +bool NativeDOM::isConnected(jsi::Runtime& rt, jsi::Value shadowNodeValue) { + auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); + auto currentRevision = + getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); + if (currentRevision == nullptr) { + return false; + } + + return dom::isConnected(currentRevision, *shadowNode); +} + +double NativeDOM::compareDocumentPosition( + jsi::Runtime& rt, + jsi::Value shadowNodeValue, + jsi::Value otherShadowNodeValue) { + auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); + auto otherShadowNode = shadowNodeFromValue(rt, otherShadowNodeValue); + auto currentRevision = + getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); + if (otherShadowNode == nullptr || currentRevision == nullptr) { + return 0; + } + + return dom::compareDocumentPosition( + currentRevision, *shadowNode, *otherShadowNode); +} + +std::string NativeDOM::getTextContent( + jsi::Runtime& rt, + jsi::Value shadowNodeValue) { + auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); + auto currentRevision = + getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); + if (currentRevision == nullptr) { + return ""; + } + + return dom::getTextContent(currentRevision, *shadowNode); +} + +std::tuple< + /* x: */ double, + /* y: */ double, + /* width: */ double, + /* height: */ double> +NativeDOM::getBoundingClientRect( + jsi::Runtime& rt, + jsi::Value shadowNodeValue, + bool includeTransform) { + auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); + auto currentRevision = + getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); + if (currentRevision == nullptr) { + return {0, 0, 0, 0}; + } + + auto domRect = dom::getBoundingClientRect( + currentRevision, *shadowNode, includeTransform); + + return std::tuple{domRect.x, domRect.y, domRect.width, domRect.height}; +} + +std::tuple< + /* offsetParent: */ jsi::Value, + /* top: */ double, + /* 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 {jsi::Value::undefined(), 0, 0}; + } + + auto domOffset = dom::getOffset(currentRevision, *shadowNode); + + return std::tuple{ + domOffset.offsetParent == nullptr + ? jsi::Value::undefined() + : domOffset.offsetParent->getInstanceHandle(rt), + domOffset.top, + domOffset.left}; +} + +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 {0, 0}; + } + + auto domPoint = dom::getScrollPosition(currentRevision, *shadowNode); + return std::tuple{domPoint.x, domPoint.y}; +} + +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 {0, 0}; + } + + auto scrollSize = dom::getScrollSize(currentRevision, *shadowNode); + return std::tuple{scrollSize.width, scrollSize.height}; +} + +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 {0, 0}; + } + + auto innerSize = dom::getInnerSize(currentRevision, *shadowNode); + return std::tuple{innerSize.width, innerSize.height}; +} + +std::tuple< + /* topWidth: */ int, + /* rightWidth: */ int, + /* bottomWidth: */ int, + /* 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 {0, 0, 0, 0}; + } + + auto borderWidth = dom::getBorderWidth(currentRevision, *shadowNode); + return std::tuple{ + borderWidth.top, borderWidth.right, borderWidth.bottom, borderWidth.left}; +} + +std::string NativeDOM::getTagName( + jsi::Runtime& rt, + jsi::Value shadowNodeValue) { + auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); + return dom::getTagName(*shadowNode); +} + +#pragma mark - Pointer events + +bool NativeDOM::hasPointerCapture( + jsi::Runtime& rt, + jsi::Value shadowNodeValue, + double pointerId) { + bool isCapturing = getPointerEventsProcessorFromRuntime(rt).hasPointerCapture( + // [Windows] Cast to fix https://github.com/microsoft/react-native-windows/issues/14251 + static_cast(pointerId), shadowNodeFromValue(rt, shadowNodeValue).get()); + return isCapturing; +} + +void NativeDOM::setPointerCapture( + jsi::Runtime& rt, + jsi::Value shadowNodeValue, + double pointerId) { + getPointerEventsProcessorFromRuntime(rt).setPointerCapture( + // [Windows] Cast to fix https://github.com/microsoft/react-native-windows/issues/14251 + static_cast(pointerId), shadowNodeFromValue(rt, shadowNodeValue)); +} + +void NativeDOM::releasePointerCapture( + jsi::Runtime& rt, + jsi::Value shadowNodeValue, + double pointerId) { + getPointerEventsProcessorFromRuntime(rt).releasePointerCapture( + // [Windows] Cast to fix https://github.com/microsoft/react-native-windows/issues/14251 + static_cast(pointerId), shadowNodeFromValue(rt, shadowNodeValue).get()); +} + +#pragma mark - Legacy RN layout APIs + +void NativeDOM::measure( + jsi::Runtime& rt, + jsi::Value shadowNodeValue, + jsi::Function callback) { + auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); + auto currentRevision = + getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); + if (currentRevision == nullptr) { + callback.call(rt, {0, 0, 0, 0, 0, 0}); + return; + } + + auto measureRect = dom::measure(currentRevision, *shadowNode); + + callback.call( + rt, + {jsi::Value{rt, measureRect.x}, + jsi::Value{rt, measureRect.y}, + jsi::Value{rt, measureRect.width}, + jsi::Value{rt, measureRect.height}, + jsi::Value{rt, measureRect.pageX}, + jsi::Value{rt, measureRect.pageY}}); +} + +void NativeDOM::measureInWindow( + jsi::Runtime& rt, + jsi::Value shadowNodeValue, + jsi::Function callback) { + auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); + auto currentRevision = + getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); + if (currentRevision == nullptr) { + callback.call(rt, {0, 0, 0, 0}); + return; + } + + auto rect = dom::measureInWindow(currentRevision, *shadowNode); + callback.call( + rt, + {jsi::Value{rt, rect.x}, + jsi::Value{rt, rect.y}, + jsi::Value{rt, rect.width}, + jsi::Value{rt, rect.height}}); +} + +void NativeDOM::measureLayout( + jsi::Runtime& rt, + jsi::Value shadowNodeValue, + jsi::Value relativeToShadowNodeValue, + jsi::Function onFail, + jsi::Function onSuccess) { + auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue); + auto relativeToShadowNode = + shadowNodeFromValue(rt, relativeToShadowNodeValue); + auto currentRevision = + getCurrentShadowTreeRevision(rt, shadowNode->getSurfaceId()); + if (currentRevision == nullptr) { + onFail.call(rt); + return; + } + + auto maybeRect = + dom::measureLayout(currentRevision, *shadowNode, *relativeToShadowNode); + + if (!maybeRect) { + onFail.call(rt); + return; + } + + auto rect = maybeRect.value(); + + onSuccess.call( + rt, + {jsi::Value{rt, rect.x}, + jsi::Value{rt, rect.y}, + jsi::Value{rt, rect.width}, + jsi::Value{rt, rect.height}}); +} + +} // namespace facebook::react diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems index 2695bd12fbc..8a8712c1e31 100644 --- a/vnext/Shared/Shared.vcxitems +++ b/vnext/Shared/Shared.vcxitems @@ -555,7 +555,7 @@ - + diff --git a/vnext/overrides.json b/vnext/overrides.json index 69d7b39814c..fced4102734 100644 --- a/vnext/overrides.json +++ b/vnext/overrides.json @@ -128,6 +128,13 @@ "baseHash": "e82eb139eab8a6e122421416fb724811bfadd6fb", "issue": 14128 }, + { + "type": "patch", + "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/dom/NativeDOM.cpp", + "baseFile": "packages/react-native/ReactCommon/react/nativemodule/dom/NativeDOM.cpp", + "baseHash": "d1424b3fbb7b7edd73c7a3e3ceb09b47c3953051", + "issue": 14257 + }, { "type": "derived", "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp",