Skip to content

Commit

Permalink
Get document from parentNode.ownerDocument
Browse files Browse the repository at this point in the history
Co-authored-by: Hydrophobefireman <hi@hpfm.dev>
  • Loading branch information
alshdavid and Hydrophobefireman committed Feb 19, 2025
1 parent 1807173 commit 5f33510
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 16 deletions.
3 changes: 2 additions & 1 deletion compat/src/portals.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ function Portal(props) {
removeChild(child) {
this.childNodes.splice(this.childNodes.indexOf(child) >>> 1, 1);
_this._container.removeChild(child);
}
},
ownerDocument: container.ownerDocument
};
}

Expand Down
3 changes: 2 additions & 1 deletion src/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ function renderComponent(component) {
commitQueue,
oldDom == null ? getDomSibling(oldVNode) : oldDom,
!!(oldVNode._flags & MODE_HYDRATE),
refQueue
refQueue,
component._parentDom.ownerDocument
);

newVNode._original = oldVNode._original;
Expand Down
7 changes: 5 additions & 2 deletions src/diff/children.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { getDomSibling } from '../component';
* siblings. In most cases, it starts out as `oldChildren[0]._dom`.
* @param {boolean} isHydrating Whether or not we are in hydration
* @param {any[]} refQueue an array of elements needed to invoke refs
* @param {Document} doc The owner document of the parentNode
*/
export function diffChildren(
parentDom,
Expand All @@ -37,7 +38,8 @@ export function diffChildren(
commitQueue,
oldDom,
isHydrating,
refQueue
refQueue,
doc
) {
let i,
/** @type {VNode} */
Expand Down Expand Up @@ -86,7 +88,8 @@ export function diffChildren(
commitQueue,
oldDom,
isHydrating,
refQueue
refQueue,
doc
);

// Adjust DOM nodes
Expand Down
25 changes: 14 additions & 11 deletions src/diff/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import options from '../options';
* siblings. In most cases, it starts out as `oldChildren[0]._dom`.
* @param {boolean} isHydrating Whether or not we are in hydration
* @param {any[]} refQueue an array of elements needed to invoke refs
* @param {Document} doc The owner document of the parentNode
*/
export function diff(
parentDom,
Expand All @@ -39,7 +40,8 @@ export function diff(
commitQueue,
oldDom,
isHydrating,
refQueue
refQueue,
doc
) {
/** @type {any} */
let tmp,
Expand Down Expand Up @@ -254,7 +256,8 @@ export function diff(
commitQueue,
oldDom,
isHydrating,
refQueue
refQueue,
doc
);

c.base = newVNode._dom;
Expand Down Expand Up @@ -304,7 +307,8 @@ export function diff(
excessDomChildren,
commitQueue,
isHydrating,
refQueue
refQueue,
doc
);
}

Expand Down Expand Up @@ -353,6 +357,7 @@ export function commitRoot(commitQueue, root, refQueue) {
* to invoke in commitRoot
* @param {boolean} isHydrating Whether or not we are in hydration
* @param {any[]} refQueue an array of elements needed to invoke refs
* @param {Document} doc The owner document of the parentNode
* @returns {PreactElement}
*/
function diffElementNodes(
Expand All @@ -364,7 +369,8 @@ function diffElementNodes(
excessDomChildren,
commitQueue,
isHydrating,
refQueue
refQueue,
doc
) {
let oldProps = oldVNode.props;
let newProps = newVNode.props;
Expand Down Expand Up @@ -408,14 +414,10 @@ function diffElementNodes(

if (dom == null) {
if (nodeType === null) {
return document.createTextNode(newProps);
return doc.createTextNode(newProps);
}

dom = document.createElementNS(
namespace,
nodeType,
newProps.is && newProps
);
dom = doc.createElementNS(namespace, nodeType, newProps.is && newProps);

// we are creating a new node, so we can assume this is a new subtree (in
// case we are hydrating), this deopts the hydrate
Expand Down Expand Up @@ -517,7 +519,8 @@ function diffElementNodes(
? excessDomChildren[0]
: oldVNode._children && getDomSibling(oldVNode, 0),
isHydrating,
refQueue
refQueue,
doc
);

// Remove children that are not part of any vnode.
Expand Down
1 change: 1 addition & 0 deletions src/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ declare global {
_children?: VNode<any> | null;
/** Event listeners to support event delegation */
_listeners?: Record<string, (e: Event) => void>;
ownerDocument: Document;
}

export interface PreactEvent extends Event {
Expand Down
3 changes: 2 additions & 1 deletion src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export function render(vnode, parentDom, replaceNode) {
? oldVNode._dom
: parentDom.firstChild,
isHydrating,
refQueue
refQueue,
parentDom.ownerDocument
);

// Flush all queued effects
Expand Down
50 changes: 50 additions & 0 deletions test/browser/getOwnerDocument.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { createElement, render } from 'preact';
import { setupScratch, teardown } from '../_util/helpers';

/** @jsx createElement */

describe.only('parentDom.ownerDocument', () => {
/** @type {HTMLDivElement} */
let scratch;

before(() => {
scratch = setupScratch();
});

after(() => {
teardown(scratch);
});

it('should reference the correct document from the parent node', () => {
let iframe = document.createElement('iframe');

scratch.appendChild(iframe);

let iframeDoc = iframe.contentDocument;

iframeDoc.write(
'<!DOCTYPE html><html><head></head><body><div></div></body></html>'
);

iframeDoc.close();

let rootTextSpy = sinon.spy(document, 'createTextNode');
let rootElementSpy = sinon.spy(document, 'createElement');

let iframeTextSpy = sinon.spy(iframeDoc, 'createTextNode');
let iframeElementSpy = sinon.spy(iframeDoc, 'createElement');

let iframeRootNode = iframeDoc.querySelector('div');

render(<span>Hello</span>, iframeRootNode);

expect(rootTextSpy).not.to.be.called;
expect(rootElementSpy).not.to.be.called;
expect(iframeTextSpy).to.be.called;
expect(iframeElementSpy).to.be.called;

expect(iframeRootNode.textContent).to.be.equal('Hello');
expect(iframeRootNode.firstChild.ownerDocument).to.be.equal(iframeDoc);
expect(iframeRootNode.firstChild.ownerDocument).to.not.be.equal(document);
});
});

0 comments on commit 5f33510

Please sign in to comment.