diffDOM icon indicating copy to clipboard operation
diffDOM copied to clipboard

Content from iframes is still not fully supported

Open mflorea opened this issue 2 years ago • 5 comments

It seems the fix from #126 is not enough to properly support iframes. The root problem is that the realm of the JavaScript interface (e.g. Text) of a DOM node is not always synchronized with the node's owner document. For instance, for a given DOM text node the following is not always true:

textNode instanceof textNode.ownerDocument.defaultView.Text

One such case when this is not true is when a DOM node is adopted. Adopting a DOM node changes its owner document, but it seems it doesn't change its prototype in all browsers. See https://jsfiddle.net/f7pbmue6/2/

  • Firefox (119) updates the prototype
  • Chrome (119) doesn't update the prototype

Judging by https://bugzilla.mozilla.org/show_bug.cgi?id=1470017 my feeling is that Chrome's behavior is the standard one which means the prototype and the owner document doesn't have to be in sync. If that is the case then using instanceof for checking the type of a DOM node becomes very fragile, since the node's prototype can be from any realm (you can imagine having multiple iframes and adopting nodes between them). We would need a way to find the (original) realm in which the DOM node was created, but I'm not sure this is possible.

mflorea avatar Nov 22 '23 11:11 mflorea

@mflorea How about checking for element.__proto__.constructor.name ? Will that always work? I am just assuming that not checking for attributes or comparing string values is something done for performance reasons.

johanneswilm avatar Nov 22 '23 11:11 johanneswilm

Using something like element.__proto__.constructor.name feels very hackish to me. Can you remind me what is the issue with checking node.nodeType? Its value is a number and there are predefined constants for it, like Node.ELEMENT_NODE, which should make:

node.nodeType === Node.TEXT_NODE

super fast. I don't understand what's wrong with this.

mflorea avatar Nov 22 '23 12:11 mflorea

@mflorea The issue is that that will only let us distinguish between text nodes, comment nodes and regular elements. We even need to find things like HTMLTextAreaElement. Maybe, after all, the only option is to check for attributes if we are to support all the possible ways of using iframes. That also feels hackish.

johanneswilm avatar Nov 22 '23 12:11 johanneswilm

This seems relevant: https://groups.google.com/g/mozilla.dev.platform/c/bfwNKKiAxcw

This is more than a decade old. They seem to suggest comparing things from the prototype. Some of the other methods, like Components.utils.getGlobalForObject(el) seem to have been removed from Chrome since.

johanneswilm avatar Nov 22 '23 17:11 johanneswilm

If we don't want to access the prototype through __proto__, another way is Object.getPrototypeOf(el).constructor.name. To check whether an element is an Element at all, the answer seems to be something like typeof el === 'object' && el.constructor !== Object && !Object.prototype.hasOwnProperty.call(el, 'nodeType') && el.nodeType !== undefined

johanneswilm avatar Nov 22 '23 17:11 johanneswilm