Skip to content
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

Remove dependance on global window and document #2897

Merged
merged 4 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions render/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ var df = require("../render/domFor")
var delayedRemoval = df.delayedRemoval
var domFor = df.domFor

module.exports = function($window) {
var $doc = $window && $window.document

module.exports = function() {
var nameSpace = {
svg: "http://www.w3.org/2000/svg",
math: "http://www.w3.org/1998/Math/MathML"
Expand All @@ -16,6 +14,10 @@ module.exports = function($window) {
var currentRedraw
var currentRender

function getDocument(dom) {
return dom.ownerDocument;
}

function getNameSpace(vnode) {
return vnode.attrs && vnode.attrs.xmlns || nameSpace[vnode.tag]
}
Expand All @@ -40,9 +42,9 @@ module.exports = function($window) {

// IE11 (at least) throws an UnspecifiedError when accessing document.activeElement when
// inside an iframe. Catch and swallow this error, and heavy-handidly return null.
function activeElement() {
function activeElement(document) {
try {
return $doc.activeElement
return document.activeElement
} catch (e) {
return null
}
Expand Down Expand Up @@ -71,7 +73,7 @@ module.exports = function($window) {
else createComponent(parent, vnode, hooks, ns, nextSibling)
}
function createText(parent, vnode, nextSibling) {
vnode.dom = $doc.createTextNode(vnode.children)
vnode.dom = getDocument(parent).createTextNode(vnode.children)
insertDOM(parent, vnode.dom, nextSibling)
}
var possibleParents = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}
Expand All @@ -82,7 +84,7 @@ module.exports = function($window) {
// div.innerHTML = "<td>i</td><td>j</td>"
// console.log(div.innerHTML)
// --> "ij", no <td> in sight.
var temp = $doc.createElement(possibleParents[match[1]] || "div")
var temp = getDocument(parent).createElement(possibleParents[match[1]] || "div")
if (ns === "http://www.w3.org/2000/svg") {
temp.innerHTML = "<svg xmlns=\"http://www.w3.org/2000/svg\">" + vnode.children + "</svg>"
temp = temp.firstChild
Expand All @@ -92,15 +94,15 @@ module.exports = function($window) {
vnode.dom = temp.firstChild
vnode.domSize = temp.childNodes.length
// Capture nodes to remove, so we don't confuse them.
var fragment = $doc.createDocumentFragment()
var fragment = getDocument(parent).createDocumentFragment()
var child
while (child = temp.firstChild) {
fragment.appendChild(child)
}
insertDOM(parent, fragment, nextSibling)
}
function createFragment(parent, vnode, hooks, ns, nextSibling) {
var fragment = $doc.createDocumentFragment()
var fragment = getDocument(parent).createDocumentFragment()
if (vnode.children != null) {
var children = vnode.children
createNodes(fragment, children, 0, children.length, hooks, null, ns)
Expand All @@ -117,8 +119,8 @@ module.exports = function($window) {
ns = getNameSpace(vnode) || ns

var element = ns ?
is ? $doc.createElementNS(ns, tag, {is: is}) : $doc.createElementNS(ns, tag) :
is ? $doc.createElement(tag, {is: is}) : $doc.createElement(tag)
is ? getDocument(parent).createElementNS(ns, tag, {is: is}) : getDocument(parent).createElementNS(ns, tag) :
is ? getDocument(parent).createElement(tag, {is: is}) : getDocument(parent).createElement(tag)
vnode.dom = element

if (attrs != null) {
Expand Down Expand Up @@ -553,7 +555,7 @@ module.exports = function($window) {
// don't allocate for the common case
target = vnode.dom
} else {
target = $doc.createDocumentFragment()
target = getDocument(parent).createDocumentFragment()
for (var dom of domFor(vnode)) target.appendChild(dom)
}
insertDOM(parent, target, nextSibling)
Expand Down Expand Up @@ -693,7 +695,7 @@ module.exports = function($window) {
/* eslint-disable no-implicit-coercion */
//setting input[value] to same value by typing on focused element moves cursor to end in Chrome
//setting input[type=file][value] to same value causes an error to be generated if it's non-empty
if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === "" + value && (isFileInput || vnode.dom === activeElement())) return
if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === "" + value && (isFileInput || vnode.dom === activeElement(getDocument(vnode.dom)))) return
//setting select[value] to same value while having select open blinks select dropdown in Chrome
if (vnode.tag === "select" && old !== null && vnode.dom.value === "" + value) return
//setting option[value] to same value while having select open blinks select dropdown in Chrome
Expand Down Expand Up @@ -722,7 +724,7 @@ module.exports = function($window) {
&& key !== "title" // creates "null" as title
&& !(key === "value" && (
vnode.tag === "option"
|| vnode.tag === "select" && vnode.dom.selectedIndex === -1 && vnode.dom === activeElement()
|| vnode.tag === "select" && vnode.dom.selectedIndex === -1 && vnode.dom === activeElement(getDocument(vnode.dom))
))
&& !(vnode.tag === "input" && key === "type")
) {
Expand Down Expand Up @@ -771,7 +773,7 @@ module.exports = function($window) {
}
}
function isFormAttribute(vnode, attr) {
return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === activeElement() || vnode.tag === "option" && vnode.dom.parentNode === $doc.activeElement
return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === activeElement(getDocument(vnode.dom)) || vnode.tag === "option" && vnode.dom.parentNode === activeElement(getDocument(vnode.dom))
}
function isLifecycleMethod(attr) {
return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate"
Expand Down Expand Up @@ -923,7 +925,7 @@ module.exports = function($window) {
var prevRedraw = currentRedraw
var prevDOM = currentDOM
var hooks = []
var active = activeElement()
var active = activeElement(getDocument(dom))
var namespace = dom.namespaceURI

currentDOM = dom
Expand All @@ -936,7 +938,7 @@ module.exports = function($window) {
updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace)
dom.vnodes = vnodes
// `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement
if (active != null && activeElement() !== active && typeof active.focus === "function") active.focus()
if (active != null && activeElement(getDocument(dom)) !== active && typeof active.focus === "function") active.focus()
for (var i = 0; i < hooks.length; i++) hooks[i]()
} finally {
currentRedraw = prevRedraw
Expand Down
3 changes: 3 additions & 0 deletions test-utils/domMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ module.exports = function(options) {
parentNode: null,
childNodes: [],
attributes: {},
ownerDocument: $window.document,
contains: function(child) {
while (child != null) {
if (child === this) return true
Expand Down Expand Up @@ -717,6 +718,7 @@ module.exports = function(options) {
},
createDocumentFragment: function() {
return {
ownerDocument: $window.document,
nodeType: 11,
nodeName: "#document-fragment",
appendChild: appendChild,
Expand All @@ -738,6 +740,7 @@ module.exports = function(options) {
get activeElement() {return activeElement},
},
}
$window.document.defaultView = $window
$window.document.documentElement = $window.document.createElement("html")
appendChild.call($window.document.documentElement, $window.document.createElement("head"))
$window.document.body = $window.document.createElement("body")
Expand Down