-
Notifications
You must be signed in to change notification settings - Fork 47.4k
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
Address issues where ID of nodeName causes internal errors in React #10076
Conversation
7a4ec79
to
ecca02b
Compare
var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); | ||
|
||
if (nodeName === 'input') { | ||
if (elem instanceof HTMLInputElement) { |
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 doesn't work when these nodes are rendered into another iframe. It's not a super common use case but a bigger discussion if we should stop supporting that.
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.
Woah:
iframe.contentWindow.window.HTMLInputElement instanceof HTMLInputElement // false
Today I learned....
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.
Seems like we could at least get some test coverage for this. I'll dig into that too. Though, if we don't have any coverage for it presently, I wonder if it's just a can of worms in JSDOM.
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.
How much slower would it be to do something like:
getInstanceForNode(elem)._tag === 'input'
That gets us around working with the DOM.
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.
Let's chat about the possibility of dropping multiple iframes support. I think the instanceof check can probably often be faster when available.
I'm not as concerned about that use case as I am about supporting React itself being in a different realm than the one being rendered into. That's still trivially supported even with instanceof
checks.
Cool, I'd be interested in knowing more about that use case. Time to dig into realms. For discussion's sake, another option might be to perform a check like: function elementIsType (element: HTMLElement, type: string): boolean {
return element instanceof element.ownerDocument.defaultView[type]
} Which is interesting, but it doesn't really get around the underling problem: the id attribute can arbitrarily screw up any specific DOM API access. This just recreates the same issue with I wonder if this is only isolated to forms and window. |
This only fixes the problem for I think in theory we could extract these methods from the prototype chain. Like this: var nodeNameGetter = Object.getOwnPropertyDescriptor(
Node.prototype,
'nodeName'
).get;
console.log(nodeNameGetter.call(element)); I'm not sure it's worth the performance overhead and file size to deal with this kind of defensive coding. |
- Add test coverage for nodeName fix - Add defaultValue to test to avoid log
Another proposal: Throw if any of the known names are used as a form name? Warning would be nice but I'm also concerned about the potential attack surface of dynamic values. |
I think the nodeName getter will work. Seems fast too: I've almost got this setup, I just hit a snag because the original test case doesn't hit the code path with the new ChangeEvent updates. Be back shortly :). |
53b5992
to
1810b5a
Compare
var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); | ||
if (elem === window) { | ||
return false; | ||
} |
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.
@sebmarkbage this is the only downside I see to calling the nodeName
getter. Occasionally this value is the window. That's because the target instance falls back to the window when it can't find a target instance:
I can't help but wonder if this could be document.body
instead of window.
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.
A good example of this is if you throw a breakpoint in this function and click anywhere on the page other than the target input.
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.
Sorry. To clarify: calling nodeNameGetter
on window
raises an exception.
The reason this is even an issue in the first place is because elements with IDs are registered as properties on Why don't we just type check the |
@aweary That might work. The only other element that exhibits this behavior, that I can find, is inputs within forms: https://codepen.io/nhunzaker/pen/qXjOGy?editors=1111 The Beyond that, if we access nodeName directly, are there any other edge cases that producing a |
Specifically, we need to know if there's any situation where this can occur on a |
Stale. |
This is a continuation of #6311. More or less, using
nodeName
as an ID on an input causes references to thenodeName
prototype property to be overriden.I've rebased @jimfb's original PR and added some test coverage. I've also browser tested this against IE11, Firefox, Safari, and Chrome.
I would like to test down to IE9, however it looks like I need the Set polyfill on our DOM fixtures. Is there a preferred method of adding the Set polyfill?