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 8941185 commit 91689ec
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 18 deletions.
3 changes: 2 additions & 1 deletion compat/src/portals.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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 @@ -39,6 +39,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 @@ -51,7 +52,8 @@ export function diffChildren(
commitQueue,
oldDom,
isHydrating,
refQueue
refQueue,
doc
) {
let i,
/** @type {VNode} */
Expand Down Expand Up @@ -104,7 +106,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 @@ -45,6 +45,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 @@ -56,7 +57,8 @@ export function diff(
commitQueue,
oldDom,
isHydrating,
refQueue
refQueue,
doc
) {
/** @type {any} */
let tmp,
Expand Down Expand Up @@ -275,7 +277,8 @@ export function diff(
commitQueue,
oldDom,
isHydrating,
refQueue
refQueue,
doc
);

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

Expand Down Expand Up @@ -381,6 +385,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 @@ -392,7 +397,8 @@ function diffElementNodes(
excessDomChildren,
commitQueue,
isHydrating,
refQueue
refQueue,
doc
) {
let oldProps = oldVNode.props;
let newProps = newVNode.props;
Expand Down Expand Up @@ -435,14 +441,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 @@ -543,7 +545,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
4 changes: 2 additions & 2 deletions src/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ export type ComponentChild =
| undefined;
export type ComponentChildren = ComponentChild[] | ComponentChild;

export interface FunctionComponent<P = {}>
extends preact.FunctionComponent<P> {
export interface FunctionComponent<P = {}> extends preact.FunctionComponent<P> {
// Internally, createContext uses `contextType` on a Function component to
// implement the Consumer component
contextType?: PreactContext;
Expand Down Expand Up @@ -123,6 +122,7 @@ export interface PreactElement extends preact.ContainerNode {
_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 @@ -61,7 +61,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('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 91689ec

Please sign in to comment.