Commit 78ba6bd
Adopt React Native 0.82 DOM Node APIs (#475)
* Adopt React Native 0.82 DOM Node APIs
Bump the react-native peer dependency to >=0.82.0 and rewrite
useStrictDOMElement to wrap the underlying RN host node in a thin
Proxy instead of cloning it via Object.create / Object.defineProperties.
React Native 0.82 shipped the stable DOM Node APIs that strict-dom
helped drive into RN (DOM traversal, ownerDocument, getRootNode,
children/childNodes, pointer-capture methods, etc.), so the native
ref polyfill becomes a lightweight overlay rather than a parallel
implementation. The Proxy traps only the keys strict-dom still needs
to control:
- nodeName: uppercase DOM name (RN exposes tagName as 'RN:View')
- getBoundingClientRect and length getters: divided by the active
viewportScale
- <img>.complete: fallback to false when the underlying RN Image
node does not expose it
- <input>/<textarea> selection trio (setSelectionRange,
selectionStart, selectionEnd): polyfilled on top of setSelection
while RN's TextInput lacks the W3C selection API
Everything else (ownerDocument, getRootNode, parentNode, children,
childNodes, sibling navigation, pointer-capture, legacy measure*)
forwards directly to the underlying RN node via Reflect.get. Function
values are bound to the target so internal `this`-references inside
RN's implementations resolve correctly.
Identity caching via a WeakMap<Node, Proxy> is preserved so the same
underlying RN node always yields the same wrapped ref.
The selection polyfill is gated on the underlying property being
absent, so the day RN exposes the W3C selection API on TextInput the
polyfill self-disables.
RN 0.83 also tightened the Flow types around Animated.createAnimatedComponent
(now a single-type-arg generic) and made ImageProps / TextInputProps
exact. The Animated factory call sites are updated to the new
signature; the wide-spread of strict-dom's ReactNativeProps onto the
exact host components is suppressed with targeted $FlowFixMe
annotations (real follow-up tracked separately).
Adds 10 ref tests in tests/html/html-refs-test.native.js documenting
the contract: uppercase nodeName, getBoundingClientRect pass-through
at scale=1, getBoundingClientRect scaled when viewportScale != 1, the
DOM Node API pass-through (ownerDocument / getRootNode / childNodes /
children), identity stability of the strict ref across renders, and
the <img>.complete fallback (both when omitted and when provided).
Bundle size: native/index.js drops ~363 minified / ~69 brotli bytes.
Web build is byte-identical.
* Bump example apps to Expo SDK 55 / React Native 0.83
Bring apps/expo-app and apps/platform-tests onto a real RN >=0.82.0
runtime so they exercise the new useStrictDOMElement Proxy path
against the DOM Node APIs from the previous commit.
Note: there is no Expo SDK that pairs exactly with RN 0.82 (SDK 53 =
RN 0.79, SDK 54 ~= RN 0.81, SDK 55 = RN 0.83). SDK 55 / RN 0.83.6
still satisfies the library's >=0.82.0 peer dep and ships the same
DOM Node API surface, so it is the closest landing zone.
Co-traveling dependency versions (@expo/metro-runtime,
expo-build-properties, expo-status-bar, react-native-web, etc.) come
from `npx expo install --check` for SDK 55; no hand-rolled versions.
Also pin react / react-dom / react-test-renderer to ~19.2.0 across
the workspace root and the two library packages' devDependencies.
RN 0.82+ requires React >=19.1.1, and aligning the workspace devDeps
avoids a multiple-React-instances error in the jest suite that would
otherwise surface once the apps hoist React 19.2.x at the root.
* Update CHANGELOG for React Native 0.82 adoption
* Use prototype delegation in useStrictDOMElement
RN 0.82 settled the DOM Node prototype hierarchy, so we can stop
cloning the host node. Object.create(node) makes the raw node the
wrapper's prototype; strict-dom defines its overrides on top;
everything else falls through. Symbol-keyed internals like
INSTANCE_HANDLE_KEY stay reachable through the chain, so RN's
prototype methods work when called on the wrapper.
Changes vs the previous clone:
* No descriptor snapshot. Reads stay in sync with the node.
* No try/catch fallback. defineProperty on a fresh object can't
fail in normal use.
* getBoundingClientRect and the length getters only install when
viewportScale isn't 1. Scale 1 skips them.
* nodeName is a value descriptor now, since tagName.toUpperCase()
doesn't change for a given wrapper.
* writable: true removed from the value descriptors. DOM spec is
read-only for nodeName, getBoundingClientRect and
setSelectionRange, so strict-mode assignments throw now.
* configurable: true on every override.
instanceof still works: the chain is one link longer (wrapper to
node to ReactNativeElement.prototype) but the class prototype is
still on it. Ten tests in html-refs-test.native.js pass.
* Aligned RN & React versions across packages & updated changelog
---------
Co-authored-by: Yamin Yassin <Yamin.Yassin+CAG@cagtechhub.com>1 parent bbe0ece commit 78ba6bd
13 files changed
Lines changed: 1905 additions & 2078 deletions
File tree
- apps
- expo-app
- platform-tests
- packages
- react-strict-animated
- react-strict-dom
- src/native/modules
- tests/html
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
| |||
25 | 27 | | |
26 | 28 | | |
27 | 29 | | |
28 | | - | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
29 | 34 | | |
30 | 35 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
14 | 14 | | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| |||
0 commit comments