Skip to content

Commit

Permalink
[Fiber] retain scripts on clearContainer and clearSingleton (#26871)
Browse files Browse the repository at this point in the history
clearContainer and clearSingleton both assumed scripts could be safely
removed from the DOM because normally once a script has been inserted
into the DOM it is executable and removing it, even synchronously, will
not prevent it from running. However There is an edge case in a couple
browsers (Chrome at least) where during HTML streaming if a script is
opened and not yet closed the script will be inserted into the document
but not yet executed. If the script is removed from the document before
the end tag is parsed then the script will not run. This change causes
clearContainer and clearSingleton to retain script elements. This is
generally thought to be safe because if we are calling these methods we
are no longer hydrating the container or the singleton and the scripts
execution will happen regardless.

DiffTrain build for [1cea384](1cea384)
  • Loading branch information
gnoff committed May 30, 2023
1 parent abcb33d commit 0b1cce0
Show file tree
Hide file tree
Showing 15 changed files with 100 additions and 28 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0210f0b082c95f5aec08f356d796c512eab44fc4
1cea384480a6dea80128e5e0ddb714df7bea1520
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ if (
}
"use strict";

var ReactVersion = "18.3.0-www-modern-c47d099f";
var ReactVersion = "18.3.0-www-modern-1948588f";

// ATTENTION
// When adding new symbols to this file,
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/ReactART-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function _assertThisInitialized(self) {
return self;
}

var ReactVersion = "18.3.0-www-classic-70819ba2";
var ReactVersion = "18.3.0-www-classic-ce251e44";

var LegacyRoot = 0;
var ConcurrentRoot = 1;
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/ReactART-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function _assertThisInitialized(self) {
return self;
}

var ReactVersion = "18.3.0-www-modern-c47d099f";
var ReactVersion = "18.3.0-www-modern-1948588f";

var LegacyRoot = 0;
var ConcurrentRoot = 1;
Expand Down
4 changes: 2 additions & 2 deletions compiled/facebook-www/ReactART-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -10193,7 +10193,7 @@ var slice = Array.prototype.slice,
return null;
},
bundleType: 0,
version: "18.3.0-www-classic-c0d8bc44",
version: "18.3.0-www-classic-8d78e420",
rendererPackageName: "react-art"
};
var internals$jscomp$inline_1323 = {
Expand Down Expand Up @@ -10224,7 +10224,7 @@ var internals$jscomp$inline_1323 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-classic-c0d8bc44"
reconcilerVersion: "18.3.0-www-classic-8d78e420"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1324 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
17 changes: 16 additions & 1 deletion compiled/facebook-www/ReactDOM-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -34196,7 +34196,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-classic-04ede6af";
var ReactVersion = "18.3.0-www-classic-b91cf5f1";

function createPortal$1(
children,
Expand Down Expand Up @@ -42932,10 +42932,24 @@ function clearContainerSparingly(container) {
detachDeletedInstance(element);
continue;
}
// Script tags are retained to avoid an edge case bug. Normally scripts will execute if they
// are ever inserted into the DOM. However when streaming if a script tag is opened but not
// yet closed some browsers create and insert the script DOM Node but the script cannot execute
// yet until the closing tag is parsed. If something causes React to call clearContainer while
// this DOM node is in the document but not yet executable the DOM node will be removed from the
// document and when the script closing tag comes in the script will not end up running. This seems
// to happen in Chrome/Firefox but not Safari at the moment though this is not necessarily specified
// behavior so it could change in future versions of browsers. While leaving all scripts is broader
// than strictly necessary this is the least amount of additional code to avoid this breaking
// edge case.
//
// Style tags are retained because they may likely come from 3rd party scripts and extensions

case "SCRIPT":
case "STYLE": {
continue;
}
// Stylesheet tags are retained because tehy may likely come from 3rd party scripts and extensions

case "LINK": {
if (node.rel.toLowerCase() === "stylesheet") {
Expand Down Expand Up @@ -43612,6 +43626,7 @@ function clearSingleton(instance) {
isMarkedHoistable(node) ||
nodeName === "HEAD" ||
nodeName === "BODY" ||
nodeName === "SCRIPT" ||
nodeName === "STYLE" ||
(nodeName === "LINK" && node.rel.toLowerCase() === "stylesheet")
);
Expand Down
17 changes: 16 additions & 1 deletion compiled/facebook-www/ReactDOM-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -34041,7 +34041,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-modern-27051227";
var ReactVersion = "18.3.0-www-modern-13e7cdbe";

function createPortal$1(
children,
Expand Down Expand Up @@ -43442,10 +43442,24 @@ function clearContainerSparingly(container) {
detachDeletedInstance(element);
continue;
}
// Script tags are retained to avoid an edge case bug. Normally scripts will execute if they
// are ever inserted into the DOM. However when streaming if a script tag is opened but not
// yet closed some browsers create and insert the script DOM Node but the script cannot execute
// yet until the closing tag is parsed. If something causes React to call clearContainer while
// this DOM node is in the document but not yet executable the DOM node will be removed from the
// document and when the script closing tag comes in the script will not end up running. This seems
// to happen in Chrome/Firefox but not Safari at the moment though this is not necessarily specified
// behavior so it could change in future versions of browsers. While leaving all scripts is broader
// than strictly necessary this is the least amount of additional code to avoid this breaking
// edge case.
//
// Style tags are retained because they may likely come from 3rd party scripts and extensions

case "SCRIPT":
case "STYLE": {
continue;
}
// Stylesheet tags are retained because tehy may likely come from 3rd party scripts and extensions

case "LINK": {
if (node.rel.toLowerCase() === "stylesheet") {
Expand Down Expand Up @@ -44122,6 +44136,7 @@ function clearSingleton(instance) {
isMarkedHoistable(node) ||
nodeName === "HEAD" ||
nodeName === "BODY" ||
nodeName === "SCRIPT" ||
nodeName === "STYLE" ||
(nodeName === "LINK" && node.rel.toLowerCase() === "stylesheet")
);
Expand Down
8 changes: 5 additions & 3 deletions compiled/facebook-www/ReactDOM-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -8673,6 +8673,7 @@ function commitMutationEffectsOnFiber(finishedWork, root) {
i[internalHoistableMarker] ||
"HEAD" === nodeName ||
"BODY" === nodeName ||
"SCRIPT" === nodeName ||
"STYLE" === nodeName ||
("LINK" === nodeName && "stylesheet" === i.rel.toLowerCase()) ||
hoistableRoot.removeChild(i);
Expand Down Expand Up @@ -15108,6 +15109,7 @@ function clearContainerSparingly(container) {
clearContainerSparingly(node);
detachDeletedInstance(node);
continue;
case "SCRIPT":
case "STYLE":
continue;
case "LINK":
Expand Down Expand Up @@ -16649,7 +16651,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1827 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-classic-70819ba2",
version: "18.3.0-www-classic-ce251e44",
rendererPackageName: "react-dom"
};
var internals$jscomp$inline_2201 = {
Expand Down Expand Up @@ -16679,7 +16681,7 @@ var internals$jscomp$inline_2201 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-classic-70819ba2"
reconcilerVersion: "18.3.0-www-classic-ce251e44"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_2202 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -16922,4 +16924,4 @@ exports.unstable_renderSubtreeIntoContainer = function (
);
};
exports.unstable_runWithPriority = runWithPriority;
exports.version = "18.3.0-www-classic-70819ba2";
exports.version = "18.3.0-www-classic-ce251e44";
8 changes: 5 additions & 3 deletions compiled/facebook-www/ReactDOM-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -8509,6 +8509,7 @@ function commitMutationEffectsOnFiber(finishedWork, root) {
i[internalHoistableMarker] ||
"HEAD" === nodeName ||
"BODY" === nodeName ||
"SCRIPT" === nodeName ||
"STYLE" === nodeName ||
("LINK" === nodeName && "stylesheet" === i.rel.toLowerCase()) ||
hoistableRoot.removeChild(i);
Expand Down Expand Up @@ -15336,6 +15337,7 @@ function clearContainerSparingly(container) {
clearContainerSparingly(node);
detachDeletedInstance(node);
continue;
case "SCRIPT":
case "STYLE":
continue;
case "LINK":
Expand Down Expand Up @@ -16176,7 +16178,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1786 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-modern-29fda94c",
version: "18.3.0-www-modern-de14310d",
rendererPackageName: "react-dom"
};
var internals$jscomp$inline_2165 = {
Expand Down Expand Up @@ -16207,7 +16209,7 @@ var internals$jscomp$inline_2165 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-modern-29fda94c"
reconcilerVersion: "18.3.0-www-modern-de14310d"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_2166 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -16378,4 +16380,4 @@ exports.unstable_createEventHandle = function (type, options) {
return eventHandle;
};
exports.unstable_runWithPriority = runWithPriority;
exports.version = "18.3.0-www-modern-29fda94c";
exports.version = "18.3.0-www-modern-de14310d";
8 changes: 5 additions & 3 deletions compiled/facebook-www/ReactDOM-profiling.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -9223,6 +9223,7 @@ function commitMutationEffectsOnFiber(finishedWork, root) {
i[internalHoistableMarker] ||
"HEAD" === nodeName ||
"BODY" === nodeName ||
"SCRIPT" === nodeName ||
"STYLE" === nodeName ||
("LINK" === nodeName && "stylesheet" === i.rel.toLowerCase()) ||
hoistableRoot.removeChild(i);
Expand Down Expand Up @@ -15883,6 +15884,7 @@ function clearContainerSparingly(container) {
clearContainerSparingly(node);
detachDeletedInstance(node);
continue;
case "SCRIPT":
case "STYLE":
continue;
case "LINK":
Expand Down Expand Up @@ -17424,7 +17426,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1912 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-classic-c0d8bc44",
version: "18.3.0-www-classic-8d78e420",
rendererPackageName: "react-dom"
};
(function (internals) {
Expand Down Expand Up @@ -17468,7 +17470,7 @@ var devToolsConfig$jscomp$inline_1912 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-classic-c0d8bc44"
reconcilerVersion: "18.3.0-www-classic-8d78e420"
});
assign(Internals, {
ReactBrowserEventEmitter: {
Expand Down Expand Up @@ -17698,7 +17700,7 @@ exports.unstable_renderSubtreeIntoContainer = function (
);
};
exports.unstable_runWithPriority = runWithPriority;
exports.version = "18.3.0-www-classic-c0d8bc44";
exports.version = "18.3.0-www-classic-8d78e420";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
8 changes: 5 additions & 3 deletions compiled/facebook-www/ReactDOM-profiling.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -9053,6 +9053,7 @@ function commitMutationEffectsOnFiber(finishedWork, root) {
i[internalHoistableMarker] ||
"HEAD" === nodeName ||
"BODY" === nodeName ||
"SCRIPT" === nodeName ||
"STYLE" === nodeName ||
("LINK" === nodeName && "stylesheet" === i.rel.toLowerCase()) ||
hoistableRoot.removeChild(i);
Expand Down Expand Up @@ -16105,6 +16106,7 @@ function clearContainerSparingly(container) {
clearContainerSparingly(node);
detachDeletedInstance(node);
continue;
case "SCRIPT":
case "STYLE":
continue;
case "LINK":
Expand Down Expand Up @@ -16945,7 +16947,7 @@ Internals.Events = [
var devToolsConfig$jscomp$inline_1871 = {
findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 0,
version: "18.3.0-www-modern-33083caa",
version: "18.3.0-www-modern-c632454d",
rendererPackageName: "react-dom"
};
(function (internals) {
Expand Down Expand Up @@ -16990,7 +16992,7 @@ var devToolsConfig$jscomp$inline_1871 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "18.3.0-www-modern-33083caa"
reconcilerVersion: "18.3.0-www-modern-c632454d"
});
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals;
exports.createPortal = function (children, container) {
Expand Down Expand Up @@ -17148,7 +17150,7 @@ exports.unstable_createEventHandle = function (type, options) {
return eventHandle;
};
exports.unstable_runWithPriority = runWithPriority;
exports.version = "18.3.0-www-modern-33083caa";
exports.version = "18.3.0-www-modern-c632454d";

/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
Expand Down
17 changes: 16 additions & 1 deletion compiled/facebook-www/ReactDOMTesting-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -34813,7 +34813,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-classic-482d05c5";
var ReactVersion = "18.3.0-www-classic-4a7abc07";

function createPortal$1(
children,
Expand Down Expand Up @@ -43549,10 +43549,24 @@ function clearContainerSparingly(container) {
detachDeletedInstance(element);
continue;
}
// Script tags are retained to avoid an edge case bug. Normally scripts will execute if they
// are ever inserted into the DOM. However when streaming if a script tag is opened but not
// yet closed some browsers create and insert the script DOM Node but the script cannot execute
// yet until the closing tag is parsed. If something causes React to call clearContainer while
// this DOM node is in the document but not yet executable the DOM node will be removed from the
// document and when the script closing tag comes in the script will not end up running. This seems
// to happen in Chrome/Firefox but not Safari at the moment though this is not necessarily specified
// behavior so it could change in future versions of browsers. While leaving all scripts is broader
// than strictly necessary this is the least amount of additional code to avoid this breaking
// edge case.
//
// Style tags are retained because they may likely come from 3rd party scripts and extensions

case "SCRIPT":
case "STYLE": {
continue;
}
// Stylesheet tags are retained because tehy may likely come from 3rd party scripts and extensions

case "LINK": {
if (node.rel.toLowerCase() === "stylesheet") {
Expand Down Expand Up @@ -44361,6 +44375,7 @@ function clearSingleton(instance) {
isMarkedHoistable(node) ||
nodeName === "HEAD" ||
nodeName === "BODY" ||
nodeName === "SCRIPT" ||
nodeName === "STYLE" ||
(nodeName === "LINK" && node.rel.toLowerCase() === "stylesheet")
);
Expand Down
17 changes: 16 additions & 1 deletion compiled/facebook-www/ReactDOMTesting-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -34658,7 +34658,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-modern-91eb192c";
var ReactVersion = "18.3.0-www-modern-02d14a38";

function createPortal$1(
children,
Expand Down Expand Up @@ -44059,10 +44059,24 @@ function clearContainerSparingly(container) {
detachDeletedInstance(element);
continue;
}
// Script tags are retained to avoid an edge case bug. Normally scripts will execute if they
// are ever inserted into the DOM. However when streaming if a script tag is opened but not
// yet closed some browsers create and insert the script DOM Node but the script cannot execute
// yet until the closing tag is parsed. If something causes React to call clearContainer while
// this DOM node is in the document but not yet executable the DOM node will be removed from the
// document and when the script closing tag comes in the script will not end up running. This seems
// to happen in Chrome/Firefox but not Safari at the moment though this is not necessarily specified
// behavior so it could change in future versions of browsers. While leaving all scripts is broader
// than strictly necessary this is the least amount of additional code to avoid this breaking
// edge case.
//
// Style tags are retained because they may likely come from 3rd party scripts and extensions

case "SCRIPT":
case "STYLE": {
continue;
}
// Stylesheet tags are retained because tehy may likely come from 3rd party scripts and extensions

case "LINK": {
if (node.rel.toLowerCase() === "stylesheet") {
Expand Down Expand Up @@ -44871,6 +44885,7 @@ function clearSingleton(instance) {
isMarkedHoistable(node) ||
nodeName === "HEAD" ||
nodeName === "BODY" ||
nodeName === "SCRIPT" ||
nodeName === "STYLE" ||
(nodeName === "LINK" && node.rel.toLowerCase() === "stylesheet")
);
Expand Down
Loading

0 comments on commit 0b1cce0

Please sign in to comment.