-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Float] handle resource Resource creation inside svg context #25599
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,6 +88,7 @@ import {ConcurrentMode, NoMode} from 'react-reconciler/src/ReactTypeOfMode'; | |
import { | ||
prepareToRenderResources, | ||
cleanupAfterRenderResources, | ||
clearRootResources, | ||
isHostResourceType, | ||
} from './ReactDOMFloatClient'; | ||
|
||
|
@@ -219,6 +220,16 @@ export function getPublicInstance(instance: Instance): Instance { | |
return instance; | ||
} | ||
|
||
export function getNamespace(hostContext: HostContext): string { | ||
if (__DEV__) { | ||
const hostContextDev: HostContextDev = (hostContext: any); | ||
return hostContextDev.namespace; | ||
} else { | ||
const hostContextProd: HostContextProd = (hostContext: any); | ||
return hostContextProd; | ||
} | ||
} | ||
|
||
gnoff marked this conversation as resolved.
Show resolved
Hide resolved
|
||
export function prepareForCommit(containerInfo: Container): Object | null { | ||
eventsEnabled = ReactBrowserEventEmitterIsEnabled(); | ||
selectionInformation = getSelectionInformation(); | ||
|
@@ -715,11 +726,18 @@ export function clearContainer(container: Container): void { | |
if (enableHostSingletons) { | ||
const nodeType = container.nodeType; | ||
if (nodeType === DOCUMENT_NODE) { | ||
clearRootResources(container); | ||
clearContainerSparingly(container); | ||
} else if (nodeType === ELEMENT_NODE) { | ||
switch (container.nodeName) { | ||
case 'HEAD': { | ||
// If we are clearing document.head as a container we are essentially clearing everything | ||
// that was hoisted to the head and should forget the instances that will no longer be in the DOM | ||
clearRootResources(container); | ||
// fall through to clear child contents | ||
} | ||
// eslint-disable-next-line-no-fallthrough | ||
case 'HTML': | ||
case 'HEAD': | ||
case 'BODY': | ||
clearContainerSparingly(container); | ||
return; | ||
|
@@ -910,6 +928,19 @@ function getNextHydratable(node) { | |
if (nodeType === ELEMENT_NODE) { | ||
const element: Element = (node: any); | ||
switch (element.tagName) { | ||
// This is subtle. in SVG scope the title tag is case sensitive. we don't want to skip | ||
// titles in svg but we do want to skip them outside of svg. there is an edge case where | ||
// you could do `React.createElement('TITLE', ...)` inside an svg scope but the SSR serializer | ||
// will still emit lowercase. Practically speaking the only time the DOM will have a non-uppercased | ||
// title tagName is if it is inside an svg. | ||
// Other Resource types like META, BASE, LINK, and SCRIPT should be treated as resources even inside | ||
// svg scope because they are invalid otherwise. We still don't need to handle the lowercase variant | ||
// because if they are present in the DOM already they would have been hoisted outside the SVG scope | ||
// as Resources. So while it would be correct to skip a <link> inside <svg> and this algorithm won't | ||
// skip that link because the tagName will not be uppercased it functionally is irrelevant. If one | ||
// tries to render incompatible types such as a non-resource stylesheet inside an svg the server will | ||
// emit that invalid html and hydration will fail. In Dev this will present warnings guiding the | ||
// developer on how to fix. | ||
Comment on lines
+931
to
+943
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please check my rationale here |
||
case 'TITLE': | ||
case 'META': | ||
case 'BASE': | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the other helpers that call out to external things in ReactDOMComponent read the namespace first and then pass it in as an argument to them.
I think we need to rip out getHostContext call and put those in the reconciler and then call the host config with the host context like we do for createInstance and others.
It's too fragile. I don't actually know if it's even correct to call it in the child reconciler. I think that might actually be wrong in some cases because I'm not sure that it's guaranteed to have the right context. Regardless, that code in the reconciler is what needs to provide that guarantee.
Once you pass it in to isHostResourceType, then you can get the namespace in isHostResourceType and pass it into ReactDOMFloatClient. It's free in prod since it's just the same value and hopefully the whole ReactDOMFloatClient gets inlined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unforutnately buried pretty deep in the reconciliation pass. I'd have to thread it through reconcileChildren. I can do this but before I go and make that happen I want to make sure that's actually viable.
An alternative is we let the reconciliation create HostComponents always and then we "upgrade" them to Resource when we beginWork and currrent === null similar to how Memo's can become SimpleMemos
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can start by just calling it right before calling isHostResourceType. At least then it's in the reconciler code instead of the bindings. It's a pretty cheap call too that could possibly even be reorganized by the compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or it could be cheap #25609