Skip to content

Commit 78f5c50

Browse files
authored
Notify FragmentInstance of added/removed text (#35637)
Follow up to #35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
1 parent e49335e commit 78f5c50

4 files changed

Lines changed: 51 additions & 17 deletions

File tree

‎packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,40 +3544,48 @@ export function updateFragmentInstanceFiber(
35443544
}
35453545

35463546
exportfunctioncommitNewChildToFragmentInstance(
3547-
childInstance: InstanceWithFragmentHandles,
3547+
childInstance: InstanceWithFragmentHandles|Text,
35483548
fragmentInstance: FragmentInstanceType,
35493549
): void{
3550+
if(childInstance.nodeType===TEXT_NODE){
3551+
return;
3552+
}
3553+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35503554
consteventListeners=fragmentInstance._eventListeners;
35513555
if(eventListeners!==null){
35523556
for(leti=0;i<eventListeners.length;i++){
35533557
const{type, listener, optionsOrUseCapture}=eventListeners[i];
3554-
childInstance.addEventListener(type,listener,optionsOrUseCapture);
3558+
instance.addEventListener(type,listener,optionsOrUseCapture);
35553559
}
35563560
}
35573561
if(fragmentInstance._observers!==null){
35583562
fragmentInstance._observers.forEach(observer=>{
3559-
observer.observe(childInstance);
3563+
observer.observe(instance);
35603564
});
35613565
}
35623566
if(enableFragmentRefsInstanceHandles){
3563-
addFragmentHandleToInstance(childInstance,fragmentInstance);
3567+
addFragmentHandleToInstance(instance,fragmentInstance);
35643568
}
35653569
}
35663570

35673571
exportfunctiondeleteChildFromFragmentInstance(
3568-
childInstance: InstanceWithFragmentHandles,
3572+
childInstance: InstanceWithFragmentHandles|Text,
35693573
fragmentInstance: FragmentInstanceType,
35703574
): void{
3575+
if(childInstance.nodeType===TEXT_NODE){
3576+
return;
3577+
}
3578+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35713579
consteventListeners=fragmentInstance._eventListeners;
35723580
if(eventListeners!==null){
35733581
for(leti=0;i<eventListeners.length;i++){
35743582
const{type,listener,optionsOrUseCapture}=eventListeners[i];
3575-
childInstance.removeEventListener(type,listener,optionsOrUseCapture);
3583+
instance.removeEventListener(type,listener,optionsOrUseCapture);
35763584
}
35773585
}
35783586
if(enableFragmentRefsInstanceHandles){
3579-
if(childInstance.unstable_reactFragments!=null){
3580-
childInstance.unstable_reactFragments.delete(fragmentInstance);
3587+
if(instance.unstable_reactFragments!=null){
3588+
instance.unstable_reactFragments.delete(fragmentInstance);
35813589
}
35823590
}
35833591
}

‎packages/react-native-renderer/src/ReactFiberConfigFabric.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import {
4040
typePublicTextInstance,
4141
typePublicRootInstance,
4242
}from'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
43-
import{enableFragmentRefsInstanceHandles}from'shared/ReactFeatureFlags';
43+
import{
44+
enableFragmentRefsInstanceHandles,
45+
enableFragmentRefsTextNodes,
46+
}from'shared/ReactFeatureFlags';
4447

4548
const{
4649
createNode,
@@ -847,10 +850,15 @@ export function updateFragmentInstanceFiber(
847850
}
848851

849852
export function commitNewChildToFragmentInstance(
850-
childInstance: Instance,
853+
childInstance: Instance | TextInstance,
851854
fragmentInstance: FragmentInstanceType,
852855
): void {
853-
constpublicInstance=getPublicInstance(childInstance);
856+
// Text nodes are not observable
857+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
858+
return;
859+
}
860+
const instance: Instance = (childInstance: any);
861+
const publicInstance = getPublicInstance(instance);
854862
if (fragmentInstance._observers !== null) {
855863
if(publicInstance==null){
856864
thrownewError('Expected to find a host node. This is a bug in React.');
@@ -869,11 +877,16 @@ export function commitNewChildToFragmentInstance(
869877
}
870878

871879
exportfunctiondeleteChildFromFragmentInstance(
872-
childInstance: Instance,
880+
childInstance: Instance|TextInstance,
873881
fragmentInstance: FragmentInstanceType,
874882
): void{
883+
// Text nodes are not observable
884+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
885+
return;
886+
}
887+
const instance: Instance = (childInstance: any);
875888
const publicInstance = ((getPublicInstance(
876-
childInstance,
889+
instance,
877890
): any): PublicInstanceWithFragmentHandles);
878891
if (enableFragmentRefsInstanceHandles) {
879892
if(publicInstance.unstable_reactFragments!=null){

‎packages/react-reconciler/src/ReactFiberCommitHostEffects.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {captureCommitPhaseError} from './ReactFiberWorkLoop';
6464
import{trackHostMutation}from'./ReactFiberMutationTracking';
6565

6666
import{runWithFiberInDEV}from'./ReactCurrentFiber';
67-
import{enableFragmentRefs}from'shared/ReactFeatureFlags';
67+
import{
68+
enableFragmentRefs,
69+
enableFragmentRefsTextNodes,
70+
}from'shared/ReactFeatureFlags';
6871

6972
exportfunctioncommitHostMount(finishedWork: Fiber){
7073
consttype=finishedWork.type;
@@ -258,7 +261,8 @@ export function commitNewChildToFragmentInstances(
258261
parentFragmentInstances: null|Array<FragmentInstanceType>,
259262
): void{
260263
if(
261-
fiber.tag!==HostComponent||
264+
(fiber.tag!==HostComponent&&
265+
!(enableFragmentRefsTextNodes&&fiber.tag===HostText))||
262266
// Only run fragment insertion effects for initial insertions
263267
fiber.alternate!==null||
264268
parentFragmentInstances===null

‎packages/react-reconciler/src/ReactFiberCommitWork.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
enableFragmentRefs,
6363
enableEagerAlternateStateNodeCleanup,
6464
enableDefaultTransitionIndicator,
65+
enableFragmentRefsTextNodes,
6566
}from'shared/ReactFeatureFlags';
6667
import{
6768
FunctionComponent,
@@ -1533,7 +1534,11 @@ function commitDeletionEffectsOnFiber(
15331534
if(!offscreenSubtreeWasHidden){
15341535
safelyDetachRef(deletedFiber,nearestMountedAncestor);
15351536
}
1536-
if(enableFragmentRefs&&deletedFiber.tag===HostComponent){
1537+
if(
1538+
enableFragmentRefs&&
1539+
(deletedFiber.tag===HostComponent||
1540+
(enableFragmentRefsTextNodes&&deletedFiber.tag===HostText))
1541+
){
15371542
commitFragmentInstanceDeletionEffects(deletedFiber);
15381543
}
15391544
// Intentional fallthrough to next branch
@@ -3028,7 +3033,11 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
30283033
// TODO (Offscreen) Check: flags & RefStatic
30293034
safelyDetachRef(finishedWork,finishedWork.return);
30303035

3031-
if(enableFragmentRefs&&finishedWork.tag===HostComponent){
3036+
if(
3037+
enableFragmentRefs&&
3038+
(finishedWork.tag===HostComponent||
3039+
(enableFragmentRefsTextNodes&&finishedWork.tag===HostText))
3040+
){
30323041
commitFragmentInstanceDeletionEffects(finishedWork);
30333042
}
30343043

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Notify FragmentInstance of added/removed text (#35637) · react/react@78f5c50 · GitHub
Skip to content

Commit 78f5c50

Browse files
authored
Notify FragmentInstance of added/removed text (#35637)
Follow up to #35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
1 parent e49335e commit 78f5c50

4 files changed

Lines changed: 51 additions & 17 deletions

File tree

‎packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,40 +3544,48 @@ export function updateFragmentInstanceFiber(
35443544
}
35453545

35463546
exportfunctioncommitNewChildToFragmentInstance(
3547-
childInstance: InstanceWithFragmentHandles,
3547+
childInstance: InstanceWithFragmentHandles|Text,
35483548
fragmentInstance: FragmentInstanceType,
35493549
): void{
3550+
if(childInstance.nodeType===TEXT_NODE){
3551+
return;
3552+
}
3553+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35503554
consteventListeners=fragmentInstance._eventListeners;
35513555
if(eventListeners!==null){
35523556
for(leti=0;i<eventListeners.length;i++){
35533557
const{type, listener, optionsOrUseCapture}=eventListeners[i];
3554-
childInstance.addEventListener(type,listener,optionsOrUseCapture);
3558+
instance.addEventListener(type,listener,optionsOrUseCapture);
35553559
}
35563560
}
35573561
if(fragmentInstance._observers!==null){
35583562
fragmentInstance._observers.forEach(observer=>{
3559-
observer.observe(childInstance);
3563+
observer.observe(instance);
35603564
});
35613565
}
35623566
if(enableFragmentRefsInstanceHandles){
3563-
addFragmentHandleToInstance(childInstance,fragmentInstance);
3567+
addFragmentHandleToInstance(instance,fragmentInstance);
35643568
}
35653569
}
35663570

35673571
exportfunctiondeleteChildFromFragmentInstance(
3568-
childInstance: InstanceWithFragmentHandles,
3572+
childInstance: InstanceWithFragmentHandles|Text,
35693573
fragmentInstance: FragmentInstanceType,
35703574
): void{
3575+
if(childInstance.nodeType===TEXT_NODE){
3576+
return;
3577+
}
3578+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35713579
consteventListeners=fragmentInstance._eventListeners;
35723580
if(eventListeners!==null){
35733581
for(leti=0;i<eventListeners.length;i++){
35743582
const{type,listener,optionsOrUseCapture}=eventListeners[i];
3575-
childInstance.removeEventListener(type,listener,optionsOrUseCapture);
3583+
instance.removeEventListener(type,listener,optionsOrUseCapture);
35763584
}
35773585
}
35783586
if(enableFragmentRefsInstanceHandles){
3579-
if(childInstance.unstable_reactFragments!=null){
3580-
childInstance.unstable_reactFragments.delete(fragmentInstance);
3587+
if(instance.unstable_reactFragments!=null){
3588+
instance.unstable_reactFragments.delete(fragmentInstance);
35813589
}
35823590
}
35833591
}

‎packages/react-native-renderer/src/ReactFiberConfigFabric.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import {
4040
typePublicTextInstance,
4141
typePublicRootInstance,
4242
}from'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
43-
import{enableFragmentRefsInstanceHandles}from'shared/ReactFeatureFlags';
43+
import{
44+
enableFragmentRefsInstanceHandles,
45+
enableFragmentRefsTextNodes,
46+
}from'shared/ReactFeatureFlags';
4447

4548
const{
4649
createNode,
@@ -847,10 +850,15 @@ export function updateFragmentInstanceFiber(
847850
}
848851

849852
export function commitNewChildToFragmentInstance(
850-
childInstance: Instance,
853+
childInstance: Instance | TextInstance,
851854
fragmentInstance: FragmentInstanceType,
852855
): void {
853-
constpublicInstance=getPublicInstance(childInstance);
856+
// Text nodes are not observable
857+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
858+
return;
859+
}
860+
const instance: Instance = (childInstance: any);
861+
const publicInstance = getPublicInstance(instance);
854862
if (fragmentInstance._observers !== null) {
855863
if(publicInstance==null){
856864
thrownewError('Expected to find a host node. This is a bug in React.');
@@ -869,11 +877,16 @@ export function commitNewChildToFragmentInstance(
869877
}
870878

871879
exportfunctiondeleteChildFromFragmentInstance(
872-
childInstance: Instance,
880+
childInstance: Instance|TextInstance,
873881
fragmentInstance: FragmentInstanceType,
874882
): void{
883+
// Text nodes are not observable
884+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
885+
return;
886+
}
887+
const instance: Instance = (childInstance: any);
875888
const publicInstance = ((getPublicInstance(
876-
childInstance,
889+
instance,
877890
): any): PublicInstanceWithFragmentHandles);
878891
if (enableFragmentRefsInstanceHandles) {
879892
if(publicInstance.unstable_reactFragments!=null){

‎packages/react-reconciler/src/ReactFiberCommitHostEffects.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {captureCommitPhaseError} from './ReactFiberWorkLoop';
6464
import{trackHostMutation}from'./ReactFiberMutationTracking';
6565

6666
import{runWithFiberInDEV}from'./ReactCurrentFiber';
67-
import{enableFragmentRefs}from'shared/ReactFeatureFlags';
67+
import{
68+
enableFragmentRefs,
69+
enableFragmentRefsTextNodes,
70+
}from'shared/ReactFeatureFlags';
6871

6972
exportfunctioncommitHostMount(finishedWork: Fiber){
7073
consttype=finishedWork.type;
@@ -258,7 +261,8 @@ export function commitNewChildToFragmentInstances(
258261
parentFragmentInstances: null|Array<FragmentInstanceType>,
259262
): void{
260263
if(
261-
fiber.tag!==HostComponent||
264+
(fiber.tag!==HostComponent&&
265+
!(enableFragmentRefsTextNodes&&fiber.tag===HostText))||
262266
// Only run fragment insertion effects for initial insertions
263267
fiber.alternate!==null||
264268
parentFragmentInstances===null

‎packages/react-reconciler/src/ReactFiberCommitWork.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
enableFragmentRefs,
6363
enableEagerAlternateStateNodeCleanup,
6464
enableDefaultTransitionIndicator,
65+
enableFragmentRefsTextNodes,
6566
}from'shared/ReactFeatureFlags';
6667
import{
6768
FunctionComponent,
@@ -1533,7 +1534,11 @@ function commitDeletionEffectsOnFiber(
15331534
if(!offscreenSubtreeWasHidden){
15341535
safelyDetachRef(deletedFiber,nearestMountedAncestor);
15351536
}
1536-
if(enableFragmentRefs&&deletedFiber.tag===HostComponent){
1537+
if(
1538+
enableFragmentRefs&&
1539+
(deletedFiber.tag===HostComponent||
1540+
(enableFragmentRefsTextNodes&&deletedFiber.tag===HostText))
1541+
){
15371542
commitFragmentInstanceDeletionEffects(deletedFiber);
15381543
}
15391544
// Intentional fallthrough to next branch
@@ -3028,7 +3033,11 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
30283033
// TODO (Offscreen) Check: flags & RefStatic
30293034
safelyDetachRef(finishedWork,finishedWork.return);
30303035

3031-
if(enableFragmentRefs&&finishedWork.tag===HostComponent){
3036+
if(
3037+
enableFragmentRefs&&
3038+
(finishedWork.tag===HostComponent||
3039+
(enableFragmentRefsTextNodes&&finishedWork.tag===HostText))
3040+
){
30323041
commitFragmentInstanceDeletionEffects(finishedWork);
30333042
}
30343043

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Notify FragmentInstance of added/removed text (#35637) · react/react@78f5c50 · GitHub
Skip to content

Commit 78f5c50

Browse files
authored
Notify FragmentInstance of added/removed text (#35637)
Follow up to #35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
1 parent e49335e commit 78f5c50

4 files changed

Lines changed: 51 additions & 17 deletions

File tree

‎packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,40 +3544,48 @@ export function updateFragmentInstanceFiber(
35443544
}
35453545

35463546
exportfunctioncommitNewChildToFragmentInstance(
3547-
childInstance: InstanceWithFragmentHandles,
3547+
childInstance: InstanceWithFragmentHandles|Text,
35483548
fragmentInstance: FragmentInstanceType,
35493549
): void{
3550+
if(childInstance.nodeType===TEXT_NODE){
3551+
return;
3552+
}
3553+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35503554
consteventListeners=fragmentInstance._eventListeners;
35513555
if(eventListeners!==null){
35523556
for(leti=0;i<eventListeners.length;i++){
35533557
const{type, listener, optionsOrUseCapture}=eventListeners[i];
3554-
childInstance.addEventListener(type,listener,optionsOrUseCapture);
3558+
instance.addEventListener(type,listener,optionsOrUseCapture);
35553559
}
35563560
}
35573561
if(fragmentInstance._observers!==null){
35583562
fragmentInstance._observers.forEach(observer=>{
3559-
observer.observe(childInstance);
3563+
observer.observe(instance);
35603564
});
35613565
}
35623566
if(enableFragmentRefsInstanceHandles){
3563-
addFragmentHandleToInstance(childInstance,fragmentInstance);
3567+
addFragmentHandleToInstance(instance,fragmentInstance);
35643568
}
35653569
}
35663570

35673571
exportfunctiondeleteChildFromFragmentInstance(
3568-
childInstance: InstanceWithFragmentHandles,
3572+
childInstance: InstanceWithFragmentHandles|Text,
35693573
fragmentInstance: FragmentInstanceType,
35703574
): void{
3575+
if(childInstance.nodeType===TEXT_NODE){
3576+
return;
3577+
}
3578+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35713579
consteventListeners=fragmentInstance._eventListeners;
35723580
if(eventListeners!==null){
35733581
for(leti=0;i<eventListeners.length;i++){
35743582
const{type,listener,optionsOrUseCapture}=eventListeners[i];
3575-
childInstance.removeEventListener(type,listener,optionsOrUseCapture);
3583+
instance.removeEventListener(type,listener,optionsOrUseCapture);
35763584
}
35773585
}
35783586
if(enableFragmentRefsInstanceHandles){
3579-
if(childInstance.unstable_reactFragments!=null){
3580-
childInstance.unstable_reactFragments.delete(fragmentInstance);
3587+
if(instance.unstable_reactFragments!=null){
3588+
instance.unstable_reactFragments.delete(fragmentInstance);
35813589
}
35823590
}
35833591
}

‎packages/react-native-renderer/src/ReactFiberConfigFabric.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import {
4040
typePublicTextInstance,
4141
typePublicRootInstance,
4242
}from'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
43-
import{enableFragmentRefsInstanceHandles}from'shared/ReactFeatureFlags';
43+
import{
44+
enableFragmentRefsInstanceHandles,
45+
enableFragmentRefsTextNodes,
46+
}from'shared/ReactFeatureFlags';
4447

4548
const{
4649
createNode,
@@ -847,10 +850,15 @@ export function updateFragmentInstanceFiber(
847850
}
848851

849852
export function commitNewChildToFragmentInstance(
850-
childInstance: Instance,
853+
childInstance: Instance | TextInstance,
851854
fragmentInstance: FragmentInstanceType,
852855
): void {
853-
constpublicInstance=getPublicInstance(childInstance);
856+
// Text nodes are not observable
857+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
858+
return;
859+
}
860+
const instance: Instance = (childInstance: any);
861+
const publicInstance = getPublicInstance(instance);
854862
if (fragmentInstance._observers !== null) {
855863
if(publicInstance==null){
856864
thrownewError('Expected to find a host node. This is a bug in React.');
@@ -869,11 +877,16 @@ export function commitNewChildToFragmentInstance(
869877
}
870878

871879
exportfunctiondeleteChildFromFragmentInstance(
872-
childInstance: Instance,
880+
childInstance: Instance|TextInstance,
873881
fragmentInstance: FragmentInstanceType,
874882
): void{
883+
// Text nodes are not observable
884+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
885+
return;
886+
}
887+
const instance: Instance = (childInstance: any);
875888
const publicInstance = ((getPublicInstance(
876-
childInstance,
889+
instance,
877890
): any): PublicInstanceWithFragmentHandles);
878891
if (enableFragmentRefsInstanceHandles) {
879892
if(publicInstance.unstable_reactFragments!=null){

‎packages/react-reconciler/src/ReactFiberCommitHostEffects.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {captureCommitPhaseError} from './ReactFiberWorkLoop';
6464
import{trackHostMutation}from'./ReactFiberMutationTracking';
6565

6666
import{runWithFiberInDEV}from'./ReactCurrentFiber';
67-
import{enableFragmentRefs}from'shared/ReactFeatureFlags';
67+
import{
68+
enableFragmentRefs,
69+
enableFragmentRefsTextNodes,
70+
}from'shared/ReactFeatureFlags';
6871

6972
exportfunctioncommitHostMount(finishedWork: Fiber){
7073
consttype=finishedWork.type;
@@ -258,7 +261,8 @@ export function commitNewChildToFragmentInstances(
258261
parentFragmentInstances: null|Array<FragmentInstanceType>,
259262
): void{
260263
if(
261-
fiber.tag!==HostComponent||
264+
(fiber.tag!==HostComponent&&
265+
!(enableFragmentRefsTextNodes&&fiber.tag===HostText))||
262266
// Only run fragment insertion effects for initial insertions
263267
fiber.alternate!==null||
264268
parentFragmentInstances===null

‎packages/react-reconciler/src/ReactFiberCommitWork.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
enableFragmentRefs,
6363
enableEagerAlternateStateNodeCleanup,
6464
enableDefaultTransitionIndicator,
65+
enableFragmentRefsTextNodes,
6566
}from'shared/ReactFeatureFlags';
6667
import{
6768
FunctionComponent,
@@ -1533,7 +1534,11 @@ function commitDeletionEffectsOnFiber(
15331534
if(!offscreenSubtreeWasHidden){
15341535
safelyDetachRef(deletedFiber,nearestMountedAncestor);
15351536
}
1536-
if(enableFragmentRefs&&deletedFiber.tag===HostComponent){
1537+
if(
1538+
enableFragmentRefs&&
1539+
(deletedFiber.tag===HostComponent||
1540+
(enableFragmentRefsTextNodes&&deletedFiber.tag===HostText))
1541+
){
15371542
commitFragmentInstanceDeletionEffects(deletedFiber);
15381543
}
15391544
// Intentional fallthrough to next branch
@@ -3028,7 +3033,11 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
30283033
// TODO (Offscreen) Check: flags & RefStatic
30293034
safelyDetachRef(finishedWork,finishedWork.return);
30303035

3031-
if(enableFragmentRefs&&finishedWork.tag===HostComponent){
3036+
if(
3037+
enableFragmentRefs&&
3038+
(finishedWork.tag===HostComponent||
3039+
(enableFragmentRefsTextNodes&&finishedWork.tag===HostText))
3040+
){
30323041
commitFragmentInstanceDeletionEffects(finishedWork);
30333042
}
30343043

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Notify FragmentInstance of added/removed text (#35637) · react/react@78f5c50 · GitHub
Skip to content

Commit 78f5c50

Browse files
authored
Notify FragmentInstance of added/removed text (#35637)
Follow up to #35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
1 parent e49335e commit 78f5c50

4 files changed

Lines changed: 51 additions & 17 deletions

File tree

‎packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,40 +3544,48 @@ export function updateFragmentInstanceFiber(
35443544
}
35453545

35463546
exportfunctioncommitNewChildToFragmentInstance(
3547-
childInstance: InstanceWithFragmentHandles,
3547+
childInstance: InstanceWithFragmentHandles|Text,
35483548
fragmentInstance: FragmentInstanceType,
35493549
): void{
3550+
if(childInstance.nodeType===TEXT_NODE){
3551+
return;
3552+
}
3553+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35503554
consteventListeners=fragmentInstance._eventListeners;
35513555
if(eventListeners!==null){
35523556
for(leti=0;i<eventListeners.length;i++){
35533557
const{type, listener, optionsOrUseCapture}=eventListeners[i];
3554-
childInstance.addEventListener(type,listener,optionsOrUseCapture);
3558+
instance.addEventListener(type,listener,optionsOrUseCapture);
35553559
}
35563560
}
35573561
if(fragmentInstance._observers!==null){
35583562
fragmentInstance._observers.forEach(observer=>{
3559-
observer.observe(childInstance);
3563+
observer.observe(instance);
35603564
});
35613565
}
35623566
if(enableFragmentRefsInstanceHandles){
3563-
addFragmentHandleToInstance(childInstance,fragmentInstance);
3567+
addFragmentHandleToInstance(instance,fragmentInstance);
35643568
}
35653569
}
35663570

35673571
exportfunctiondeleteChildFromFragmentInstance(
3568-
childInstance: InstanceWithFragmentHandles,
3572+
childInstance: InstanceWithFragmentHandles|Text,
35693573
fragmentInstance: FragmentInstanceType,
35703574
): void{
3575+
if(childInstance.nodeType===TEXT_NODE){
3576+
return;
3577+
}
3578+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35713579
consteventListeners=fragmentInstance._eventListeners;
35723580
if(eventListeners!==null){
35733581
for(leti=0;i<eventListeners.length;i++){
35743582
const{type,listener,optionsOrUseCapture}=eventListeners[i];
3575-
childInstance.removeEventListener(type,listener,optionsOrUseCapture);
3583+
instance.removeEventListener(type,listener,optionsOrUseCapture);
35763584
}
35773585
}
35783586
if(enableFragmentRefsInstanceHandles){
3579-
if(childInstance.unstable_reactFragments!=null){
3580-
childInstance.unstable_reactFragments.delete(fragmentInstance);
3587+
if(instance.unstable_reactFragments!=null){
3588+
instance.unstable_reactFragments.delete(fragmentInstance);
35813589
}
35823590
}
35833591
}

‎packages/react-native-renderer/src/ReactFiberConfigFabric.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import {
4040
typePublicTextInstance,
4141
typePublicRootInstance,
4242
}from'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
43-
import{enableFragmentRefsInstanceHandles}from'shared/ReactFeatureFlags';
43+
import{
44+
enableFragmentRefsInstanceHandles,
45+
enableFragmentRefsTextNodes,
46+
}from'shared/ReactFeatureFlags';
4447

4548
const{
4649
createNode,
@@ -847,10 +850,15 @@ export function updateFragmentInstanceFiber(
847850
}
848851

849852
export function commitNewChildToFragmentInstance(
850-
childInstance: Instance,
853+
childInstance: Instance | TextInstance,
851854
fragmentInstance: FragmentInstanceType,
852855
): void {
853-
constpublicInstance=getPublicInstance(childInstance);
856+
// Text nodes are not observable
857+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
858+
return;
859+
}
860+
const instance: Instance = (childInstance: any);
861+
const publicInstance = getPublicInstance(instance);
854862
if (fragmentInstance._observers !== null) {
855863
if(publicInstance==null){
856864
thrownewError('Expected to find a host node. This is a bug in React.');
@@ -869,11 +877,16 @@ export function commitNewChildToFragmentInstance(
869877
}
870878

871879
exportfunctiondeleteChildFromFragmentInstance(
872-
childInstance: Instance,
880+
childInstance: Instance|TextInstance,
873881
fragmentInstance: FragmentInstanceType,
874882
): void{
883+
// Text nodes are not observable
884+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
885+
return;
886+
}
887+
const instance: Instance = (childInstance: any);
875888
const publicInstance = ((getPublicInstance(
876-
childInstance,
889+
instance,
877890
): any): PublicInstanceWithFragmentHandles);
878891
if (enableFragmentRefsInstanceHandles) {
879892
if(publicInstance.unstable_reactFragments!=null){

‎packages/react-reconciler/src/ReactFiberCommitHostEffects.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {captureCommitPhaseError} from './ReactFiberWorkLoop';
6464
import{trackHostMutation}from'./ReactFiberMutationTracking';
6565

6666
import{runWithFiberInDEV}from'./ReactCurrentFiber';
67-
import{enableFragmentRefs}from'shared/ReactFeatureFlags';
67+
import{
68+
enableFragmentRefs,
69+
enableFragmentRefsTextNodes,
70+
}from'shared/ReactFeatureFlags';
6871

6972
exportfunctioncommitHostMount(finishedWork: Fiber){
7073
consttype=finishedWork.type;
@@ -258,7 +261,8 @@ export function commitNewChildToFragmentInstances(
258261
parentFragmentInstances: null|Array<FragmentInstanceType>,
259262
): void{
260263
if(
261-
fiber.tag!==HostComponent||
264+
(fiber.tag!==HostComponent&&
265+
!(enableFragmentRefsTextNodes&&fiber.tag===HostText))||
262266
// Only run fragment insertion effects for initial insertions
263267
fiber.alternate!==null||
264268
parentFragmentInstances===null

‎packages/react-reconciler/src/ReactFiberCommitWork.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
enableFragmentRefs,
6363
enableEagerAlternateStateNodeCleanup,
6464
enableDefaultTransitionIndicator,
65+
enableFragmentRefsTextNodes,
6566
}from'shared/ReactFeatureFlags';
6667
import{
6768
FunctionComponent,
@@ -1533,7 +1534,11 @@ function commitDeletionEffectsOnFiber(
15331534
if(!offscreenSubtreeWasHidden){
15341535
safelyDetachRef(deletedFiber,nearestMountedAncestor);
15351536
}
1536-
if(enableFragmentRefs&&deletedFiber.tag===HostComponent){
1537+
if(
1538+
enableFragmentRefs&&
1539+
(deletedFiber.tag===HostComponent||
1540+
(enableFragmentRefsTextNodes&&deletedFiber.tag===HostText))
1541+
){
15371542
commitFragmentInstanceDeletionEffects(deletedFiber);
15381543
}
15391544
// Intentional fallthrough to next branch
@@ -3028,7 +3033,11 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
30283033
// TODO (Offscreen) Check: flags & RefStatic
30293034
safelyDetachRef(finishedWork,finishedWork.return);
30303035

3031-
if(enableFragmentRefs&&finishedWork.tag===HostComponent){
3036+
if(
3037+
enableFragmentRefs&&
3038+
(finishedWork.tag===HostComponent||
3039+
(enableFragmentRefsTextNodes&&finishedWork.tag===HostText))
3040+
){
30323041
commitFragmentInstanceDeletionEffects(finishedWork);
30333042
}
30343043

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Notify FragmentInstance of added/removed text (#35637) · react/react@78f5c50 · GitHub
Skip to content

Commit 78f5c50

Browse files
authored
Notify FragmentInstance of added/removed text (#35637)
Follow up to #35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
1 parent e49335e commit 78f5c50

4 files changed

Lines changed: 51 additions & 17 deletions

File tree

‎packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,40 +3544,48 @@ export function updateFragmentInstanceFiber(
35443544
}
35453545

35463546
exportfunctioncommitNewChildToFragmentInstance(
3547-
childInstance: InstanceWithFragmentHandles,
3547+
childInstance: InstanceWithFragmentHandles|Text,
35483548
fragmentInstance: FragmentInstanceType,
35493549
): void{
3550+
if(childInstance.nodeType===TEXT_NODE){
3551+
return;
3552+
}
3553+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35503554
consteventListeners=fragmentInstance._eventListeners;
35513555
if(eventListeners!==null){
35523556
for(leti=0;i<eventListeners.length;i++){
35533557
const{type, listener, optionsOrUseCapture}=eventListeners[i];
3554-
childInstance.addEventListener(type,listener,optionsOrUseCapture);
3558+
instance.addEventListener(type,listener,optionsOrUseCapture);
35553559
}
35563560
}
35573561
if(fragmentInstance._observers!==null){
35583562
fragmentInstance._observers.forEach(observer=>{
3559-
observer.observe(childInstance);
3563+
observer.observe(instance);
35603564
});
35613565
}
35623566
if(enableFragmentRefsInstanceHandles){
3563-
addFragmentHandleToInstance(childInstance,fragmentInstance);
3567+
addFragmentHandleToInstance(instance,fragmentInstance);
35643568
}
35653569
}
35663570

35673571
exportfunctiondeleteChildFromFragmentInstance(
3568-
childInstance: InstanceWithFragmentHandles,
3572+
childInstance: InstanceWithFragmentHandles|Text,
35693573
fragmentInstance: FragmentInstanceType,
35703574
): void{
3575+
if(childInstance.nodeType===TEXT_NODE){
3576+
return;
3577+
}
3578+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35713579
consteventListeners=fragmentInstance._eventListeners;
35723580
if(eventListeners!==null){
35733581
for(leti=0;i<eventListeners.length;i++){
35743582
const{type,listener,optionsOrUseCapture}=eventListeners[i];
3575-
childInstance.removeEventListener(type,listener,optionsOrUseCapture);
3583+
instance.removeEventListener(type,listener,optionsOrUseCapture);
35763584
}
35773585
}
35783586
if(enableFragmentRefsInstanceHandles){
3579-
if(childInstance.unstable_reactFragments!=null){
3580-
childInstance.unstable_reactFragments.delete(fragmentInstance);
3587+
if(instance.unstable_reactFragments!=null){
3588+
instance.unstable_reactFragments.delete(fragmentInstance);
35813589
}
35823590
}
35833591
}

‎packages/react-native-renderer/src/ReactFiberConfigFabric.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import {
4040
typePublicTextInstance,
4141
typePublicRootInstance,
4242
}from'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
43-
import{enableFragmentRefsInstanceHandles}from'shared/ReactFeatureFlags';
43+
import{
44+
enableFragmentRefsInstanceHandles,
45+
enableFragmentRefsTextNodes,
46+
}from'shared/ReactFeatureFlags';
4447

4548
const{
4649
createNode,
@@ -847,10 +850,15 @@ export function updateFragmentInstanceFiber(
847850
}
848851

849852
export function commitNewChildToFragmentInstance(
850-
childInstance: Instance,
853+
childInstance: Instance | TextInstance,
851854
fragmentInstance: FragmentInstanceType,
852855
): void {
853-
constpublicInstance=getPublicInstance(childInstance);
856+
// Text nodes are not observable
857+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
858+
return;
859+
}
860+
const instance: Instance = (childInstance: any);
861+
const publicInstance = getPublicInstance(instance);
854862
if (fragmentInstance._observers !== null) {
855863
if(publicInstance==null){
856864
thrownewError('Expected to find a host node. This is a bug in React.');
@@ -869,11 +877,16 @@ export function commitNewChildToFragmentInstance(
869877
}
870878

871879
exportfunctiondeleteChildFromFragmentInstance(
872-
childInstance: Instance,
880+
childInstance: Instance|TextInstance,
873881
fragmentInstance: FragmentInstanceType,
874882
): void{
883+
// Text nodes are not observable
884+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
885+
return;
886+
}
887+
const instance: Instance = (childInstance: any);
875888
const publicInstance = ((getPublicInstance(
876-
childInstance,
889+
instance,
877890
): any): PublicInstanceWithFragmentHandles);
878891
if (enableFragmentRefsInstanceHandles) {
879892
if(publicInstance.unstable_reactFragments!=null){

‎packages/react-reconciler/src/ReactFiberCommitHostEffects.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {captureCommitPhaseError} from './ReactFiberWorkLoop';
6464
import{trackHostMutation}from'./ReactFiberMutationTracking';
6565

6666
import{runWithFiberInDEV}from'./ReactCurrentFiber';
67-
import{enableFragmentRefs}from'shared/ReactFeatureFlags';
67+
import{
68+
enableFragmentRefs,
69+
enableFragmentRefsTextNodes,
70+
}from'shared/ReactFeatureFlags';
6871

6972
exportfunctioncommitHostMount(finishedWork: Fiber){
7073
consttype=finishedWork.type;
@@ -258,7 +261,8 @@ export function commitNewChildToFragmentInstances(
258261
parentFragmentInstances: null|Array<FragmentInstanceType>,
259262
): void{
260263
if(
261-
fiber.tag!==HostComponent||
264+
(fiber.tag!==HostComponent&&
265+
!(enableFragmentRefsTextNodes&&fiber.tag===HostText))||
262266
// Only run fragment insertion effects for initial insertions
263267
fiber.alternate!==null||
264268
parentFragmentInstances===null

‎packages/react-reconciler/src/ReactFiberCommitWork.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
enableFragmentRefs,
6363
enableEagerAlternateStateNodeCleanup,
6464
enableDefaultTransitionIndicator,
65+
enableFragmentRefsTextNodes,
6566
}from'shared/ReactFeatureFlags';
6667
import{
6768
FunctionComponent,
@@ -1533,7 +1534,11 @@ function commitDeletionEffectsOnFiber(
15331534
if(!offscreenSubtreeWasHidden){
15341535
safelyDetachRef(deletedFiber,nearestMountedAncestor);
15351536
}
1536-
if(enableFragmentRefs&&deletedFiber.tag===HostComponent){
1537+
if(
1538+
enableFragmentRefs&&
1539+
(deletedFiber.tag===HostComponent||
1540+
(enableFragmentRefsTextNodes&&deletedFiber.tag===HostText))
1541+
){
15371542
commitFragmentInstanceDeletionEffects(deletedFiber);
15381543
}
15391544
// Intentional fallthrough to next branch
@@ -3028,7 +3033,11 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
30283033
// TODO (Offscreen) Check: flags & RefStatic
30293034
safelyDetachRef(finishedWork,finishedWork.return);
30303035

3031-
if(enableFragmentRefs&&finishedWork.tag===HostComponent){
3036+
if(
3037+
enableFragmentRefs&&
3038+
(finishedWork.tag===HostComponent||
3039+
(enableFragmentRefsTextNodes&&finishedWork.tag===HostText))
3040+
){
30323041
commitFragmentInstanceDeletionEffects(finishedWork);
30333042
}
30343043

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Notify FragmentInstance of added/removed text (#35637) · react/react@78f5c50 · GitHub
Skip to content

Commit 78f5c50

Browse files
authored
Notify FragmentInstance of added/removed text (#35637)
Follow up to #35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
1 parent e49335e commit 78f5c50

4 files changed

Lines changed: 51 additions & 17 deletions

File tree

‎packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,40 +3544,48 @@ export function updateFragmentInstanceFiber(
35443544
}
35453545

35463546
exportfunctioncommitNewChildToFragmentInstance(
3547-
childInstance: InstanceWithFragmentHandles,
3547+
childInstance: InstanceWithFragmentHandles|Text,
35483548
fragmentInstance: FragmentInstanceType,
35493549
): void{
3550+
if(childInstance.nodeType===TEXT_NODE){
3551+
return;
3552+
}
3553+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35503554
consteventListeners=fragmentInstance._eventListeners;
35513555
if(eventListeners!==null){
35523556
for(leti=0;i<eventListeners.length;i++){
35533557
const{type, listener, optionsOrUseCapture}=eventListeners[i];
3554-
childInstance.addEventListener(type,listener,optionsOrUseCapture);
3558+
instance.addEventListener(type,listener,optionsOrUseCapture);
35553559
}
35563560
}
35573561
if(fragmentInstance._observers!==null){
35583562
fragmentInstance._observers.forEach(observer=>{
3559-
observer.observe(childInstance);
3563+
observer.observe(instance);
35603564
});
35613565
}
35623566
if(enableFragmentRefsInstanceHandles){
3563-
addFragmentHandleToInstance(childInstance,fragmentInstance);
3567+
addFragmentHandleToInstance(instance,fragmentInstance);
35643568
}
35653569
}
35663570

35673571
exportfunctiondeleteChildFromFragmentInstance(
3568-
childInstance: InstanceWithFragmentHandles,
3572+
childInstance: InstanceWithFragmentHandles|Text,
35693573
fragmentInstance: FragmentInstanceType,
35703574
): void{
3575+
if(childInstance.nodeType===TEXT_NODE){
3576+
return;
3577+
}
3578+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35713579
consteventListeners=fragmentInstance._eventListeners;
35723580
if(eventListeners!==null){
35733581
for(leti=0;i<eventListeners.length;i++){
35743582
const{type,listener,optionsOrUseCapture}=eventListeners[i];
3575-
childInstance.removeEventListener(type,listener,optionsOrUseCapture);
3583+
instance.removeEventListener(type,listener,optionsOrUseCapture);
35763584
}
35773585
}
35783586
if(enableFragmentRefsInstanceHandles){
3579-
if(childInstance.unstable_reactFragments!=null){
3580-
childInstance.unstable_reactFragments.delete(fragmentInstance);
3587+
if(instance.unstable_reactFragments!=null){
3588+
instance.unstable_reactFragments.delete(fragmentInstance);
35813589
}
35823590
}
35833591
}

‎packages/react-native-renderer/src/ReactFiberConfigFabric.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import {
4040
typePublicTextInstance,
4141
typePublicRootInstance,
4242
}from'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
43-
import{enableFragmentRefsInstanceHandles}from'shared/ReactFeatureFlags';
43+
import{
44+
enableFragmentRefsInstanceHandles,
45+
enableFragmentRefsTextNodes,
46+
}from'shared/ReactFeatureFlags';
4447

4548
const{
4649
createNode,
@@ -847,10 +850,15 @@ export function updateFragmentInstanceFiber(
847850
}
848851

849852
export function commitNewChildToFragmentInstance(
850-
childInstance: Instance,
853+
childInstance: Instance | TextInstance,
851854
fragmentInstance: FragmentInstanceType,
852855
): void {
853-
constpublicInstance=getPublicInstance(childInstance);
856+
// Text nodes are not observable
857+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
858+
return;
859+
}
860+
const instance: Instance = (childInstance: any);
861+
const publicInstance = getPublicInstance(instance);
854862
if (fragmentInstance._observers !== null) {
855863
if(publicInstance==null){
856864
thrownewError('Expected to find a host node. This is a bug in React.');
@@ -869,11 +877,16 @@ export function commitNewChildToFragmentInstance(
869877
}
870878

871879
exportfunctiondeleteChildFromFragmentInstance(
872-
childInstance: Instance,
880+
childInstance: Instance|TextInstance,
873881
fragmentInstance: FragmentInstanceType,
874882
): void{
883+
// Text nodes are not observable
884+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
885+
return;
886+
}
887+
const instance: Instance = (childInstance: any);
875888
const publicInstance = ((getPublicInstance(
876-
childInstance,
889+
instance,
877890
): any): PublicInstanceWithFragmentHandles);
878891
if (enableFragmentRefsInstanceHandles) {
879892
if(publicInstance.unstable_reactFragments!=null){

‎packages/react-reconciler/src/ReactFiberCommitHostEffects.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {captureCommitPhaseError} from './ReactFiberWorkLoop';
6464
import{trackHostMutation}from'./ReactFiberMutationTracking';
6565

6666
import{runWithFiberInDEV}from'./ReactCurrentFiber';
67-
import{enableFragmentRefs}from'shared/ReactFeatureFlags';
67+
import{
68+
enableFragmentRefs,
69+
enableFragmentRefsTextNodes,
70+
}from'shared/ReactFeatureFlags';
6871

6972
exportfunctioncommitHostMount(finishedWork: Fiber){
7073
consttype=finishedWork.type;
@@ -258,7 +261,8 @@ export function commitNewChildToFragmentInstances(
258261
parentFragmentInstances: null|Array<FragmentInstanceType>,
259262
): void{
260263
if(
261-
fiber.tag!==HostComponent||
264+
(fiber.tag!==HostComponent&&
265+
!(enableFragmentRefsTextNodes&&fiber.tag===HostText))||
262266
// Only run fragment insertion effects for initial insertions
263267
fiber.alternate!==null||
264268
parentFragmentInstances===null

‎packages/react-reconciler/src/ReactFiberCommitWork.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
enableFragmentRefs,
6363
enableEagerAlternateStateNodeCleanup,
6464
enableDefaultTransitionIndicator,
65+
enableFragmentRefsTextNodes,
6566
}from'shared/ReactFeatureFlags';
6667
import{
6768
FunctionComponent,
@@ -1533,7 +1534,11 @@ function commitDeletionEffectsOnFiber(
15331534
if(!offscreenSubtreeWasHidden){
15341535
safelyDetachRef(deletedFiber,nearestMountedAncestor);
15351536
}
1536-
if(enableFragmentRefs&&deletedFiber.tag===HostComponent){
1537+
if(
1538+
enableFragmentRefs&&
1539+
(deletedFiber.tag===HostComponent||
1540+
(enableFragmentRefsTextNodes&&deletedFiber.tag===HostText))
1541+
){
15371542
commitFragmentInstanceDeletionEffects(deletedFiber);
15381543
}
15391544
// Intentional fallthrough to next branch
@@ -3028,7 +3033,11 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
30283033
// TODO (Offscreen) Check: flags & RefStatic
30293034
safelyDetachRef(finishedWork,finishedWork.return);
30303035

3031-
if(enableFragmentRefs&&finishedWork.tag===HostComponent){
3036+
if(
3037+
enableFragmentRefs&&
3038+
(finishedWork.tag===HostComponent||
3039+
(enableFragmentRefsTextNodes&&finishedWork.tag===HostText))
3040+
){
30323041
commitFragmentInstanceDeletionEffects(finishedWork);
30333042
}
30343043

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Notify FragmentInstance of added/removed text (#35637) · react/react@78f5c50 · GitHub
Skip to content

Commit 78f5c50

Browse files
authored
Notify FragmentInstance of added/removed text (#35637)
Follow up to #35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
1 parent e49335e commit 78f5c50

4 files changed

Lines changed: 51 additions & 17 deletions

File tree

‎packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,40 +3544,48 @@ export function updateFragmentInstanceFiber(
35443544
}
35453545

35463546
exportfunctioncommitNewChildToFragmentInstance(
3547-
childInstance: InstanceWithFragmentHandles,
3547+
childInstance: InstanceWithFragmentHandles|Text,
35483548
fragmentInstance: FragmentInstanceType,
35493549
): void{
3550+
if(childInstance.nodeType===TEXT_NODE){
3551+
return;
3552+
}
3553+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35503554
consteventListeners=fragmentInstance._eventListeners;
35513555
if(eventListeners!==null){
35523556
for(leti=0;i<eventListeners.length;i++){
35533557
const{type, listener, optionsOrUseCapture}=eventListeners[i];
3554-
childInstance.addEventListener(type,listener,optionsOrUseCapture);
3558+
instance.addEventListener(type,listener,optionsOrUseCapture);
35553559
}
35563560
}
35573561
if(fragmentInstance._observers!==null){
35583562
fragmentInstance._observers.forEach(observer=>{
3559-
observer.observe(childInstance);
3563+
observer.observe(instance);
35603564
});
35613565
}
35623566
if(enableFragmentRefsInstanceHandles){
3563-
addFragmentHandleToInstance(childInstance,fragmentInstance);
3567+
addFragmentHandleToInstance(instance,fragmentInstance);
35643568
}
35653569
}
35663570

35673571
exportfunctiondeleteChildFromFragmentInstance(
3568-
childInstance: InstanceWithFragmentHandles,
3572+
childInstance: InstanceWithFragmentHandles|Text,
35693573
fragmentInstance: FragmentInstanceType,
35703574
): void{
3575+
if(childInstance.nodeType===TEXT_NODE){
3576+
return;
3577+
}
3578+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35713579
consteventListeners=fragmentInstance._eventListeners;
35723580
if(eventListeners!==null){
35733581
for(leti=0;i<eventListeners.length;i++){
35743582
const{type,listener,optionsOrUseCapture}=eventListeners[i];
3575-
childInstance.removeEventListener(type,listener,optionsOrUseCapture);
3583+
instance.removeEventListener(type,listener,optionsOrUseCapture);
35763584
}
35773585
}
35783586
if(enableFragmentRefsInstanceHandles){
3579-
if(childInstance.unstable_reactFragments!=null){
3580-
childInstance.unstable_reactFragments.delete(fragmentInstance);
3587+
if(instance.unstable_reactFragments!=null){
3588+
instance.unstable_reactFragments.delete(fragmentInstance);
35813589
}
35823590
}
35833591
}

‎packages/react-native-renderer/src/ReactFiberConfigFabric.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import {
4040
typePublicTextInstance,
4141
typePublicRootInstance,
4242
}from'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
43-
import{enableFragmentRefsInstanceHandles}from'shared/ReactFeatureFlags';
43+
import{
44+
enableFragmentRefsInstanceHandles,
45+
enableFragmentRefsTextNodes,
46+
}from'shared/ReactFeatureFlags';
4447

4548
const{
4649
createNode,
@@ -847,10 +850,15 @@ export function updateFragmentInstanceFiber(
847850
}
848851

849852
export function commitNewChildToFragmentInstance(
850-
childInstance: Instance,
853+
childInstance: Instance | TextInstance,
851854
fragmentInstance: FragmentInstanceType,
852855
): void {
853-
constpublicInstance=getPublicInstance(childInstance);
856+
// Text nodes are not observable
857+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
858+
return;
859+
}
860+
const instance: Instance = (childInstance: any);
861+
const publicInstance = getPublicInstance(instance);
854862
if (fragmentInstance._observers !== null) {
855863
if(publicInstance==null){
856864
thrownewError('Expected to find a host node. This is a bug in React.');
@@ -869,11 +877,16 @@ export function commitNewChildToFragmentInstance(
869877
}
870878

871879
exportfunctiondeleteChildFromFragmentInstance(
872-
childInstance: Instance,
880+
childInstance: Instance|TextInstance,
873881
fragmentInstance: FragmentInstanceType,
874882
): void{
883+
// Text nodes are not observable
884+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
885+
return;
886+
}
887+
const instance: Instance = (childInstance: any);
875888
const publicInstance = ((getPublicInstance(
876-
childInstance,
889+
instance,
877890
): any): PublicInstanceWithFragmentHandles);
878891
if (enableFragmentRefsInstanceHandles) {
879892
if(publicInstance.unstable_reactFragments!=null){

‎packages/react-reconciler/src/ReactFiberCommitHostEffects.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {captureCommitPhaseError} from './ReactFiberWorkLoop';
6464
import{trackHostMutation}from'./ReactFiberMutationTracking';
6565

6666
import{runWithFiberInDEV}from'./ReactCurrentFiber';
67-
import{enableFragmentRefs}from'shared/ReactFeatureFlags';
67+
import{
68+
enableFragmentRefs,
69+
enableFragmentRefsTextNodes,
70+
}from'shared/ReactFeatureFlags';
6871

6972
exportfunctioncommitHostMount(finishedWork: Fiber){
7073
consttype=finishedWork.type;
@@ -258,7 +261,8 @@ export function commitNewChildToFragmentInstances(
258261
parentFragmentInstances: null|Array<FragmentInstanceType>,
259262
): void{
260263
if(
261-
fiber.tag!==HostComponent||
264+
(fiber.tag!==HostComponent&&
265+
!(enableFragmentRefsTextNodes&&fiber.tag===HostText))||
262266
// Only run fragment insertion effects for initial insertions
263267
fiber.alternate!==null||
264268
parentFragmentInstances===null

‎packages/react-reconciler/src/ReactFiberCommitWork.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
enableFragmentRefs,
6363
enableEagerAlternateStateNodeCleanup,
6464
enableDefaultTransitionIndicator,
65+
enableFragmentRefsTextNodes,
6566
}from'shared/ReactFeatureFlags';
6667
import{
6768
FunctionComponent,
@@ -1533,7 +1534,11 @@ function commitDeletionEffectsOnFiber(
15331534
if(!offscreenSubtreeWasHidden){
15341535
safelyDetachRef(deletedFiber,nearestMountedAncestor);
15351536
}
1536-
if(enableFragmentRefs&&deletedFiber.tag===HostComponent){
1537+
if(
1538+
enableFragmentRefs&&
1539+
(deletedFiber.tag===HostComponent||
1540+
(enableFragmentRefsTextNodes&&deletedFiber.tag===HostText))
1541+
){
15371542
commitFragmentInstanceDeletionEffects(deletedFiber);
15381543
}
15391544
// Intentional fallthrough to next branch
@@ -3028,7 +3033,11 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
30283033
// TODO (Offscreen) Check: flags & RefStatic
30293034
safelyDetachRef(finishedWork,finishedWork.return);
30303035

3031-
if(enableFragmentRefs&&finishedWork.tag===HostComponent){
3036+
if(
3037+
enableFragmentRefs&&
3038+
(finishedWork.tag===HostComponent||
3039+
(enableFragmentRefsTextNodes&&finishedWork.tag===HostText))
3040+
){
30323041
commitFragmentInstanceDeletionEffects(finishedWork);
30333042
}
30343043

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Notify FragmentInstance of added/removed text (#35637) · react/react@78f5c50 · GitHub
Skip to content

Commit 78f5c50

Browse files
authored
Notify FragmentInstance of added/removed text (#35637)
Follow up to #35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
1 parent e49335e commit 78f5c50

4 files changed

Lines changed: 51 additions & 17 deletions

File tree

‎packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,40 +3544,48 @@ export function updateFragmentInstanceFiber(
35443544
}
35453545

35463546
exportfunctioncommitNewChildToFragmentInstance(
3547-
childInstance: InstanceWithFragmentHandles,
3547+
childInstance: InstanceWithFragmentHandles|Text,
35483548
fragmentInstance: FragmentInstanceType,
35493549
): void{
3550+
if(childInstance.nodeType===TEXT_NODE){
3551+
return;
3552+
}
3553+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35503554
consteventListeners=fragmentInstance._eventListeners;
35513555
if(eventListeners!==null){
35523556
for(leti=0;i<eventListeners.length;i++){
35533557
const{type, listener, optionsOrUseCapture}=eventListeners[i];
3554-
childInstance.addEventListener(type,listener,optionsOrUseCapture);
3558+
instance.addEventListener(type,listener,optionsOrUseCapture);
35553559
}
35563560
}
35573561
if(fragmentInstance._observers!==null){
35583562
fragmentInstance._observers.forEach(observer=>{
3559-
observer.observe(childInstance);
3563+
observer.observe(instance);
35603564
});
35613565
}
35623566
if(enableFragmentRefsInstanceHandles){
3563-
addFragmentHandleToInstance(childInstance,fragmentInstance);
3567+
addFragmentHandleToInstance(instance,fragmentInstance);
35643568
}
35653569
}
35663570

35673571
exportfunctiondeleteChildFromFragmentInstance(
3568-
childInstance: InstanceWithFragmentHandles,
3572+
childInstance: InstanceWithFragmentHandles|Text,
35693573
fragmentInstance: FragmentInstanceType,
35703574
): void{
3575+
if(childInstance.nodeType===TEXT_NODE){
3576+
return;
3577+
}
3578+
constinstance: InstanceWithFragmentHandles=(childInstance: any);
35713579
consteventListeners=fragmentInstance._eventListeners;
35723580
if(eventListeners!==null){
35733581
for(leti=0;i<eventListeners.length;i++){
35743582
const{type,listener,optionsOrUseCapture}=eventListeners[i];
3575-
childInstance.removeEventListener(type,listener,optionsOrUseCapture);
3583+
instance.removeEventListener(type,listener,optionsOrUseCapture);
35763584
}
35773585
}
35783586
if(enableFragmentRefsInstanceHandles){
3579-
if(childInstance.unstable_reactFragments!=null){
3580-
childInstance.unstable_reactFragments.delete(fragmentInstance);
3587+
if(instance.unstable_reactFragments!=null){
3588+
instance.unstable_reactFragments.delete(fragmentInstance);
35813589
}
35823590
}
35833591
}

‎packages/react-native-renderer/src/ReactFiberConfigFabric.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ import {
4040
typePublicTextInstance,
4141
typePublicRootInstance,
4242
}from'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
43-
import{enableFragmentRefsInstanceHandles}from'shared/ReactFeatureFlags';
43+
import{
44+
enableFragmentRefsInstanceHandles,
45+
enableFragmentRefsTextNodes,
46+
}from'shared/ReactFeatureFlags';
4447

4548
const{
4649
createNode,
@@ -847,10 +850,15 @@ export function updateFragmentInstanceFiber(
847850
}
848851

849852
export function commitNewChildToFragmentInstance(
850-
childInstance: Instance,
853+
childInstance: Instance | TextInstance,
851854
fragmentInstance: FragmentInstanceType,
852855
): void {
853-
constpublicInstance=getPublicInstance(childInstance);
856+
// Text nodes are not observable
857+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
858+
return;
859+
}
860+
const instance: Instance = (childInstance: any);
861+
const publicInstance = getPublicInstance(instance);
854862
if (fragmentInstance._observers !== null) {
855863
if(publicInstance==null){
856864
thrownewError('Expected to find a host node. This is a bug in React.');
@@ -869,11 +877,16 @@ export function commitNewChildToFragmentInstance(
869877
}
870878

871879
exportfunctiondeleteChildFromFragmentInstance(
872-
childInstance: Instance,
880+
childInstance: Instance|TextInstance,
873881
fragmentInstance: FragmentInstanceType,
874882
): void{
883+
// Text nodes are not observable
884+
if(enableFragmentRefsTextNodes&&childInstance.canonical==null){
885+
return;
886+
}
887+
const instance: Instance = (childInstance: any);
875888
const publicInstance = ((getPublicInstance(
876-
childInstance,
889+
instance,
877890
): any): PublicInstanceWithFragmentHandles);
878891
if (enableFragmentRefsInstanceHandles) {
879892
if(publicInstance.unstable_reactFragments!=null){

‎packages/react-reconciler/src/ReactFiberCommitHostEffects.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {captureCommitPhaseError} from './ReactFiberWorkLoop';
6464
import{trackHostMutation}from'./ReactFiberMutationTracking';
6565

6666
import{runWithFiberInDEV}from'./ReactCurrentFiber';
67-
import{enableFragmentRefs}from'shared/ReactFeatureFlags';
67+
import{
68+
enableFragmentRefs,
69+
enableFragmentRefsTextNodes,
70+
}from'shared/ReactFeatureFlags';
6871

6972
exportfunctioncommitHostMount(finishedWork: Fiber){
7073
consttype=finishedWork.type;
@@ -258,7 +261,8 @@ export function commitNewChildToFragmentInstances(
258261
parentFragmentInstances: null|Array<FragmentInstanceType>,
259262
): void{
260263
if(
261-
fiber.tag!==HostComponent||
264+
(fiber.tag!==HostComponent&&
265+
!(enableFragmentRefsTextNodes&&fiber.tag===HostText))||
262266
// Only run fragment insertion effects for initial insertions
263267
fiber.alternate!==null||
264268
parentFragmentInstances===null

‎packages/react-reconciler/src/ReactFiberCommitWork.js‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
enableFragmentRefs,
6363
enableEagerAlternateStateNodeCleanup,
6464
enableDefaultTransitionIndicator,
65+
enableFragmentRefsTextNodes,
6566
}from'shared/ReactFeatureFlags';
6667
import{
6768
FunctionComponent,
@@ -1533,7 +1534,11 @@ function commitDeletionEffectsOnFiber(
15331534
if(!offscreenSubtreeWasHidden){
15341535
safelyDetachRef(deletedFiber,nearestMountedAncestor);
15351536
}
1536-
if(enableFragmentRefs&&deletedFiber.tag===HostComponent){
1537+
if(
1538+
enableFragmentRefs&&
1539+
(deletedFiber.tag===HostComponent||
1540+
(enableFragmentRefsTextNodes&&deletedFiber.tag===HostText))
1541+
){
15371542
commitFragmentInstanceDeletionEffects(deletedFiber);
15381543
}
15391544
// Intentional fallthrough to next branch
@@ -3028,7 +3033,11 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
30283033
// TODO (Offscreen) Check: flags & RefStatic
30293034
safelyDetachRef(finishedWork,finishedWork.return);
30303035

3031-
if(enableFragmentRefs&&finishedWork.tag===HostComponent){
3036+
if(
3037+
enableFragmentRefs&&
3038+
(finishedWork.tag===HostComponent||
3039+
(enableFragmentRefsTextNodes&&finishedWork.tag===HostText))
3040+
){
30323041
commitFragmentInstanceDeletionEffects(finishedWork);
30333042
}
30343043

0 commit comments

Comments
 (0)