Skip to content

Commit 673c761

Browse files
rubennortefacebook-github-bot
authored andcommitted
Implement DOMRect and DOMRectReadOnly matching Web
Summary: This adds the `DOMRect` and `DOMRectReadOnly` classes to React Native, mostly following the Web spec. This is a requirement for `node.getBoundingClientRect()`, which we'll implement in React (in https://github.com/facebook/react/blob/main/packages/react-native-renderer/src/ReactFabricHostConfig.js#L134-L323). Changelog: [General][Added] - Added Web-compatible `DOMRect` and `DOMRectReadOnly` classes to the global scope. Reviewed By: ryancat Differential Revision: D42963222 fbshipit-source-id: bf2ed15bfbfd71822cb6f969f8cc0a67c7834333
1 parent 3337553 commit 673c761

File tree

5 files changed

+293
-0
lines changed

5 files changed

+293
-0
lines changed

Libraries/Core/InitializeCore.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
const start = Date.now();
2828

2929
require('./setUpGlobals');
30+
require('./setUpDOM');
3031
require('./setUpPerformance');
3132
require('./setUpErrorHandling');
3233
require('./polyfillPromise');

Libraries/Core/setUpDOM.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
* @flow strict
8+
* @format
9+
*/
10+
11+
import DOMRect from '../DOM/Geometry/DOMRect';
12+
import DOMRectReadOnly from '../DOM/Geometry/DOMRectReadOnly';
13+
14+
// $FlowExpectedError[cannot-write] The global isn't writable anywhere but here, where we define it
15+
global.DOMRect = DOMRect;
16+
17+
// $FlowExpectedError[cannot-write] The global isn't writable anywhere but here, where we define it
18+
global.DOMRectReadOnly = DOMRectReadOnly;

Libraries/DOM/Geometry/DOMRect.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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+
* @flow strict
8+
* @format
9+
*/
10+
11+
/**
12+
* The JSDoc comments in this file have been extracted from [DOMRect](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect).
13+
* Content by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect/contributors.txt),
14+
* licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/).
15+
*/
16+
17+
import DOMRectReadOnly, {type DOMRectLike} from './DOMRectReadOnly';
18+
19+
// flowlint unsafe-getters-setters:off
20+
21+
/**
22+
* A `DOMRect` describes the size and position of a rectangle.
23+
* The type of box represented by the `DOMRect` is specified by the method or property that returned it.
24+
*
25+
* This is a (mostly) spec-compliant version of `DOMRect` (https://developer.mozilla.org/en-US/docs/Web/API/DOMRect).
26+
*/
27+
export default class DOMRect extends DOMRectReadOnly {
28+
/**
29+
* The x coordinate of the `DOMRect`'s origin.
30+
*/
31+
get x(): number {
32+
return this.__getInternalX();
33+
}
34+
35+
set x(x: ?number) {
36+
this.__setInternalX(x);
37+
}
38+
39+
/**
40+
* The y coordinate of the `DOMRect`'s origin.
41+
*/
42+
get y(): number {
43+
return this.__getInternalY();
44+
}
45+
46+
set y(y: ?number) {
47+
this.__setInternalY(y);
48+
}
49+
50+
/**
51+
* The width of the `DOMRect`.
52+
*/
53+
get width(): number {
54+
return this.__getInternalWidth();
55+
}
56+
57+
set width(width: ?number) {
58+
this.__setInternalWidth(width);
59+
}
60+
61+
/**
62+
* The height of the `DOMRect`.
63+
*/
64+
get height(): number {
65+
return this.__getInternalHeight();
66+
}
67+
68+
set height(height: ?number) {
69+
this.__setInternalHeight(height);
70+
}
71+
72+
/**
73+
* Creates a new `DOMRect` object with a given location and dimensions.
74+
*/
75+
static fromRect(rect?: ?DOMRectLike): DOMRect {
76+
if (!rect) {
77+
return new DOMRect();
78+
}
79+
80+
return new DOMRect(rect.x, rect.y, rect.width, rect.height);
81+
}
82+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
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+
* @flow strict
8+
* @format
9+
*/
10+
11+
/**
12+
* The JSDoc comments in this file have been extracted from [DOMRectReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly).
13+
* Content by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/contributors.txt),
14+
* licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/).
15+
*/
16+
17+
// flowlint sketchy-null:off, unsafe-getters-setters:off
18+
19+
export interface DOMRectLike {
20+
x?: ?number;
21+
y?: ?number;
22+
width?: ?number;
23+
height?: ?number;
24+
}
25+
26+
function castToNumber(value: mixed): number {
27+
return value ? Number(value) : 0;
28+
}
29+
30+
/**
31+
* The `DOMRectReadOnly` interface specifies the standard properties used by `DOMRect` to define a rectangle whose properties are immutable.
32+
*
33+
* This is a (mostly) spec-compliant version of `DOMRectReadOnly` (https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly).
34+
*/
35+
export default class DOMRectReadOnly {
36+
_x: number;
37+
_y: number;
38+
_width: number;
39+
_height: number;
40+
41+
constructor(x: ?number, y: ?number, width: ?number, height: ?number) {
42+
this.__setInternalX(x);
43+
this.__setInternalY(y);
44+
this.__setInternalWidth(width);
45+
this.__setInternalHeight(height);
46+
}
47+
48+
/**
49+
* The x coordinate of the `DOMRectReadOnly`'s origin.
50+
*/
51+
get x(): number {
52+
return this._x;
53+
}
54+
55+
/**
56+
* The y coordinate of the `DOMRectReadOnly`'s origin.
57+
*/
58+
get y(): number {
59+
return this._y;
60+
}
61+
62+
/**
63+
* The width of the `DOMRectReadOnly`.
64+
*/
65+
get width(): number {
66+
return this._width;
67+
}
68+
69+
/**
70+
* The height of the `DOMRectReadOnly`.
71+
*/
72+
get height(): number {
73+
return this._height;
74+
}
75+
76+
/**
77+
* Returns the top coordinate value of the `DOMRect` (has the same value as `y`, or `y + height` if `height` is negative).
78+
*/
79+
get top(): number {
80+
const height = this._height;
81+
const y = this._y;
82+
83+
if (height < 0) {
84+
return y + height;
85+
}
86+
87+
return y;
88+
}
89+
90+
/**
91+
* Returns the right coordinate value of the `DOMRect` (has the same value as ``x + width`, or `x` if `width` is negative).
92+
*/
93+
get right(): number {
94+
const width = this._width;
95+
const x = this._x;
96+
97+
if (width < 0) {
98+
return x;
99+
}
100+
101+
return x + width;
102+
}
103+
104+
/**
105+
* Returns the bottom coordinate value of the `DOMRect` (has the same value as `y + height`, or `y` if `height` is negative).
106+
*/
107+
get bottom(): number {
108+
const height = this._height;
109+
const y = this._y;
110+
111+
if (height < 0) {
112+
return y;
113+
}
114+
115+
return y + height;
116+
}
117+
118+
/**
119+
* Returns the left coordinate value of the `DOMRect` (has the same value as `x`, or `x + width` if `width` is negative).
120+
*/
121+
get left(): number {
122+
const width = this._width;
123+
const x = this._x;
124+
125+
if (width < 0) {
126+
return x + width;
127+
}
128+
129+
return x;
130+
}
131+
132+
toJSON(): {
133+
x: number,
134+
y: number,
135+
width: number,
136+
height: number,
137+
top: number,
138+
left: number,
139+
bottom: number,
140+
right: number,
141+
} {
142+
const {x, y, width, height, top, left, bottom, right} = this;
143+
return {x, y, width, height, top, left, bottom, right};
144+
}
145+
146+
/**
147+
* Creates a new `DOMRectReadOnly` object with a given location and dimensions.
148+
*/
149+
static fromRect(rect?: ?DOMRectLike): DOMRectReadOnly {
150+
if (!rect) {
151+
return new DOMRectReadOnly();
152+
}
153+
154+
return new DOMRectReadOnly(rect.x, rect.y, rect.width, rect.height);
155+
}
156+
157+
__getInternalX(): number {
158+
return this._x;
159+
}
160+
161+
__getInternalY(): number {
162+
return this._y;
163+
}
164+
165+
__getInternalWidth(): number {
166+
return this._width;
167+
}
168+
169+
__getInternalHeight(): number {
170+
return this._height;
171+
}
172+
173+
__setInternalX(x: ?number) {
174+
this._x = castToNumber(x);
175+
}
176+
177+
__setInternalY(y: ?number) {
178+
this._y = castToNumber(y);
179+
}
180+
181+
__setInternalWidth(width: ?number) {
182+
this._width = castToNumber(width);
183+
}
184+
185+
__setInternalHeight(height: ?number) {
186+
this._height = castToNumber(height);
187+
}
188+
}

flow/global.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ declare var global: {
8080
+__DEV__?: boolean,
8181
+RN$Bridgeless?: boolean,
8282

83+
// setupDOM
84+
+DOMRect: typeof DOMRect,
85+
+DOMRectReadOnly: typeof DOMRectReadOnly,
86+
8387
// Undeclared properties are implicitly `any`.
8488
[string | symbol]: any,
8589
};

0 commit comments

Comments
 (0)