mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add legacy layout methods from Fabric to DOM native module (#43659)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43659 Changelog: [internal] This adds an implementation for the legacy layout measurement methods in React Native (`measure`, `measureInWindow` and `measureLayout`) in the DOM native module, so we can clean up the API from the `nativeFabricUIManager` binding. Reviewed By: javache Differential Revision: D55368141 fbshipit-source-id: 196d4d29be3b78ffc22fdc136be6e0cf5ab9dd26
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ff392b0156
commit
2af1da42ff
@@ -21,10 +21,11 @@ std::shared_ptr<facebook::react::TurboModule> NativeDOMModuleProvider(
|
||||
return std::make_shared<facebook::react::NativeDOM>(std::move(jsInvoker));
|
||||
}
|
||||
|
||||
namespace {
|
||||
using namespace facebook::react;
|
||||
namespace facebook::react {
|
||||
|
||||
RootShadowNode::Shared getCurrentShadowTreeRevision(
|
||||
#pragma mark - Private helpers
|
||||
|
||||
static RootShadowNode::Shared getCurrentShadowTreeRevision(
|
||||
facebook::jsi::Runtime& runtime,
|
||||
SurfaceId surfaceId) {
|
||||
auto& uiManager =
|
||||
@@ -33,13 +34,14 @@ RootShadowNode::Shared getCurrentShadowTreeRevision(
|
||||
return shadowTreeRevisionProvider->getCurrentRevision(surfaceId);
|
||||
}
|
||||
|
||||
facebook::react::PointerEventsProcessor& getPointerEventsProcessorFromRuntime(
|
||||
facebook::jsi::Runtime& runtime) {
|
||||
static facebook::react::PointerEventsProcessor&
|
||||
getPointerEventsProcessorFromRuntime(facebook::jsi::Runtime& runtime) {
|
||||
return facebook::react::UIManagerBinding::getBinding(runtime)
|
||||
->getPointerEventsProcessor();
|
||||
}
|
||||
|
||||
std::vector<facebook::jsi::Value> getArrayOfInstanceHandlesFromShadowNodes(
|
||||
static std::vector<facebook::jsi::Value>
|
||||
getArrayOfInstanceHandlesFromShadowNodes(
|
||||
const ShadowNode::ListOfShared& nodes,
|
||||
facebook::jsi::Runtime& runtime) {
|
||||
// JSI doesn't support adding elements to an array after creation,
|
||||
@@ -56,9 +58,8 @@ std::vector<facebook::jsi::Value> getArrayOfInstanceHandlesFromShadowNodes(
|
||||
|
||||
return nonNullInstanceHandles;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace facebook::react {
|
||||
#pragma mark - NativeDOM
|
||||
|
||||
NativeDOM::NativeDOM(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: NativeDOMCxxSpec(std::move(jsInvoker)) {}
|
||||
@@ -244,6 +245,8 @@ std::string NativeDOM::getTagName(
|
||||
return dom::getTagName(*shadowNode);
|
||||
}
|
||||
|
||||
#pragma mark - Pointer events
|
||||
|
||||
bool NativeDOM::hasPointerCapture(
|
||||
jsi::Runtime& rt,
|
||||
jsi::Value shadowNodeValue,
|
||||
@@ -269,4 +272,85 @@ void NativeDOM::releasePointerCapture(
|
||||
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
|
||||
|
||||
@@ -88,6 +88,23 @@ class NativeDOM : public NativeDOMCxxSpec<NativeDOM> {
|
||||
jsi::Runtime& rt,
|
||||
jsi::Value shadowNodeValue,
|
||||
double pointerId);
|
||||
|
||||
// Legacy layout APIs
|
||||
|
||||
void
|
||||
measure(jsi::Runtime& rt, jsi::Value shadowNodeValue, jsi::Function callback);
|
||||
|
||||
void measureInWindow(
|
||||
jsi::Runtime& rt,
|
||||
jsi::Value shadowNodeValue,
|
||||
jsi::Function callback);
|
||||
|
||||
void measureLayout(
|
||||
jsi::Runtime& rt,
|
||||
jsi::Value shadowNodeValue,
|
||||
jsi::Value relativeToShadowNodeValue,
|
||||
jsi::Function onFail,
|
||||
jsi::Function onSuccess);
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
@@ -17,6 +17,29 @@ import type {TurboModule} from '../../../../../../Libraries/TurboModule/RCTExpor
|
||||
import * as TurboModuleRegistry from '../../../../../../Libraries/TurboModule/TurboModuleRegistry';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
export type MeasureInWindowOnSuccessCallback = (
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
) => void;
|
||||
|
||||
export type MeasureOnSuccessCallback = (
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
pageX: number,
|
||||
pageY: number,
|
||||
) => void;
|
||||
|
||||
export type MeasureLayoutOnSuccessCallback = (
|
||||
left: number,
|
||||
top: number,
|
||||
width: number,
|
||||
height: number,
|
||||
) => void;
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+getParentNode: (
|
||||
shadowNode: mixed /* ShadowNode */,
|
||||
@@ -76,6 +99,24 @@ export interface Spec extends TurboModule {
|
||||
shadowNode: mixed /* ShadowNode */,
|
||||
pointerId: number,
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Legacy layout APIs
|
||||
*/
|
||||
|
||||
+measure: (shadowNode: mixed, callback: MeasureOnSuccessCallback) => void;
|
||||
|
||||
+measureInWindow: (
|
||||
shadowNode: mixed,
|
||||
callback: MeasureInWindowOnSuccessCallback,
|
||||
) => void;
|
||||
|
||||
+measureLayout: (
|
||||
shadowNode: mixed,
|
||||
relativeNode: mixed,
|
||||
onFail: () => void,
|
||||
onSuccess: MeasureLayoutOnSuccessCallback,
|
||||
) => void;
|
||||
}
|
||||
|
||||
const RawNativeDOM = (TurboModuleRegistry.get<Spec>('NativeDOMCxx'): ?Spec);
|
||||
@@ -271,6 +312,27 @@ export interface RefinedSpec {
|
||||
+setPointerCapture: (shadowNode: ShadowNode, pointerId: number) => void;
|
||||
|
||||
+releasePointerCapture: (shadowNode: ShadowNode, pointerId: number) => void;
|
||||
|
||||
/**
|
||||
* Legacy layout APIs
|
||||
*/
|
||||
|
||||
+measure: (
|
||||
shadowNode: ShadowNode,
|
||||
callback: MeasureOnSuccessCallback,
|
||||
) => void;
|
||||
|
||||
+measureInWindow: (
|
||||
shadowNode: ShadowNode,
|
||||
callback: MeasureInWindowOnSuccessCallback,
|
||||
) => void;
|
||||
|
||||
+measureLayout: (
|
||||
shadowNode: ShadowNode,
|
||||
relativeNode: ShadowNode,
|
||||
onFail: () => void,
|
||||
onSuccess: MeasureLayoutOnSuccessCallback,
|
||||
) => void;
|
||||
}
|
||||
|
||||
const NativeDOM: RefinedSpec = {
|
||||
@@ -380,6 +442,27 @@ const NativeDOM: RefinedSpec = {
|
||||
pointerId,
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Legacy layout APIs
|
||||
*/
|
||||
|
||||
measure(shadowNode, callback) {
|
||||
return nullthrows(RawNativeDOM).measure(shadowNode, callback);
|
||||
},
|
||||
|
||||
measureInWindow(shadowNode, callback) {
|
||||
return nullthrows(RawNativeDOM).measureInWindow(shadowNode, callback);
|
||||
},
|
||||
|
||||
measureLayout(shadowNode, relativeNode, onFail, onSuccess) {
|
||||
return nullthrows(RawNativeDOM).measureLayout(
|
||||
shadowNode,
|
||||
relativeNode,
|
||||
onFail,
|
||||
onSuccess,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default NativeDOM;
|
||||
|
||||
+37
@@ -13,6 +13,11 @@ import type {
|
||||
InternalInstanceHandle,
|
||||
Node,
|
||||
} from '../../../../../../../Libraries/Renderer/shims/ReactNativeTypes';
|
||||
import type {
|
||||
MeasureInWindowOnSuccessCallback,
|
||||
MeasureLayoutOnSuccessCallback,
|
||||
MeasureOnSuccessCallback,
|
||||
} from '../NativeDOM';
|
||||
import typeof NativeDOM from '../NativeDOM';
|
||||
|
||||
import {
|
||||
@@ -371,6 +376,38 @@ const NativeDOMMock: NativeDOM = {
|
||||
ensureHostNode(node);
|
||||
return 'RN:' + fromNode(node).viewName;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Legacy layout APIs
|
||||
*/
|
||||
|
||||
measure: jest.fn((node: Node, callback: MeasureOnSuccessCallback): void => {
|
||||
ensureHostNode(node);
|
||||
|
||||
callback(10, 10, 100, 100, 0, 0);
|
||||
}),
|
||||
|
||||
measureInWindow: jest.fn(
|
||||
(node: Node, callback: MeasureInWindowOnSuccessCallback): void => {
|
||||
ensureHostNode(node);
|
||||
|
||||
callback(10, 10, 100, 100);
|
||||
},
|
||||
),
|
||||
|
||||
measureLayout: jest.fn(
|
||||
(
|
||||
node: Node,
|
||||
relativeNode: Node,
|
||||
onFail: () => void,
|
||||
onSuccess: MeasureLayoutOnSuccessCallback,
|
||||
): void => {
|
||||
ensureHostNode(node);
|
||||
ensureHostNode(relativeNode);
|
||||
|
||||
onSuccess(1, 1, 100, 100);
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
export default NativeDOMMock;
|
||||
|
||||
Reference in New Issue
Block a user