From 348bed0a7e1ba0376281792f2081bd1c057aa607 Mon Sep 17 00:00:00 2001 From: Isiah Meadows Date: Sun, 1 Oct 2017 19:26:43 -0400 Subject: [PATCH] Allow `xlink:href` to get removed, fix `option.value` in mock --- docs/change-log.md | 1 + render/render.js | 2 +- render/tests/test-attributes.js | 10 +++++----- render/tests/test-createElement.js | 22 ++++++++++++++++++++-- test-utils/domMock.js | 2 +- test-utils/tests/test-domMock.js | 4 ++-- 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/docs/change-log.md b/docs/change-log.md index 722d5975..3873c6b8 100644 --- a/docs/change-log.md +++ b/docs/change-log.md @@ -38,6 +38,7 @@ - core: Event listeners allocate less memory, swap at low cost, and are properly diffed now when rendered via `m.mount()`/`m.redraw()`. - core: `Object.prototype` properties can no longer interfere with event listener calls. - API: Event handlers, when set to literally `undefined` (or any non-function), are now correctly removed. +- core: `xlink:href` attributes are now correctly removed --- diff --git a/render/render.js b/render/render.js index d8de6e0d..121083ca 100644 --- a/render/render.js +++ b/render/render.js @@ -476,7 +476,7 @@ module.exports = function($window) { if (key[0] === "o" && key[1] === "n") return updateEvent(vnode, key, value) if ((old === value && !isFormAttribute(vnode, key)) && typeof value !== "object" || value === undefined) return var element = vnode.dom - if (key.slice(0, 6) === "xlink:") element.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(6), value) + if (key.slice(0, 6) === "xlink:") element.setAttributeNS("http://www.w3.org/1999/xlink", key, value) else if (key === "style") updateStyle(element, old, value) else if (key in element && !isAttribute(key) && ns === undefined && !isCustomElement(vnode)) { if (key === "value") { diff --git a/render/tests/test-attributes.js b/render/tests/test-attributes.js index fcc7f150..d54ed9d4 100644 --- a/render/tests/test-attributes.js +++ b/render/tests/test-attributes.js @@ -376,15 +376,15 @@ o.spec("attributes", function() { o(a.dom.value).equals("1") }) - o("null becomes the empty string", function() { + o("null becomes 'null'", function() { var a = {tag: "option", attrs: {value: null}} var b = {tag: "option", attrs: {value: "test"}} var c = {tag: "option", attrs: {value: null}} render(root, [a]); - o(a.dom.value).equals("") - o(a.dom.getAttribute("value")).equals("") + o(a.dom.value).equals("null") + o(a.dom.getAttribute("value")).equals("null") render(root, [b]); @@ -393,8 +393,8 @@ o.spec("attributes", function() { render(root, [c]); - o(c.dom.value).equals("") - o(c.dom.getAttribute("value")).equals("") + o(c.dom.value).equals("null") + o(c.dom.getAttribute("value")).equals("null") }) o("'' and 0 are different values", function() { var a = {tag: "option", attrs: {value: 0}, children:[{tag:"#", children:""}]} diff --git a/render/tests/test-createElement.js b/render/tests/test-createElement.js index 6e3dcdd7..c2dc1d90 100644 --- a/render/tests/test-createElement.js +++ b/render/tests/test-createElement.js @@ -65,8 +65,8 @@ o.spec("createElement", function() { o(vnode.dom.namespaceURI).equals("http://www.w3.org/2000/svg") o(vnode.dom.firstChild.nodeName).equals("a") o(vnode.dom.firstChild.namespaceURI).equals("http://www.w3.org/2000/svg") - o(vnode.dom.firstChild.attributes["href"].value).equals("javascript:;") - o(vnode.dom.firstChild.attributes["href"].namespaceURI).equals("http://www.w3.org/1999/xlink") + o(vnode.dom.firstChild.attributes["xlink:href"].value).equals("javascript:;") + o(vnode.dom.firstChild.attributes["xlink:href"].namespaceURI).equals("http://www.w3.org/1999/xlink") o(vnode.dom.childNodes[1].nodeName).equals("foreignObject") o(vnode.dom.childNodes[1].firstChild.nodeName).equals("body") o(vnode.dom.childNodes[1].firstChild.namespaceURI).equals("http://www.w3.org/1999/xhtml") @@ -77,6 +77,24 @@ o.spec("createElement", function() { o(vnode.dom.attributes["viewBox"].value).equals("0 0 100 100") }) + o("removes xlink:href", function() { + var vnode = {tag: "svg", ns: "http://www.w3.org/2000/svg", children: [ + {tag: "a", ns: "http://www.w3.org/2000/svg", attrs: {"xlink:href": "javascript:;"}} + ]} + render(root, [vnode]) + + o(vnode.dom.nodeName).equals("svg") + o(vnode.dom.firstChild.attributes["xlink:href"].value).equals("javascript:;") + o(vnode.dom.firstChild.attributes["xlink:href"].namespaceURI).equals("http://www.w3.org/1999/xlink") + + vnode = {tag: "svg", ns: "http://www.w3.org/2000/svg", children: [ + {tag: "a", ns: "http://www.w3.org/2000/svg", attrs: {}} + ]} + render(root, [vnode]) + + o(vnode.dom.nodeName).equals("svg") + o(vnode.dom.firstChild.attributes["xlink:href"]).equals(undefined) + }) o("creates mathml", function() { var vnode = {tag: "math", ns: "http://www.w3.org/1998/Math/MathML", children: [{tag: "mrow", ns: "http://www.w3.org/1998/Math/MathML"}]} render(root, [vnode]) diff --git a/test-utils/domMock.js b/test-utils/domMock.js index d99dce47..b8f5d1a3 100644 --- a/test-utils/domMock.js +++ b/test-utils/domMock.js @@ -445,7 +445,7 @@ module.exports = function(options) { if (element.nodeName === "OPTION") { var valueSetter = spy(function(value) { /*eslint-disable no-implicit-coercion*/ - this.setAttribute("value", value === null ? "" : "" + value) + this.setAttribute("value", "" + value) /*eslint-enable no-implicit-coercion*/ }) Object.defineProperty(element, "value", { diff --git a/test-utils/tests/test-domMock.js b/test-utils/tests/test-domMock.js index a5829458..3e4a9567 100644 --- a/test-utils/tests/test-domMock.js +++ b/test-utils/tests/test-domMock.js @@ -954,11 +954,11 @@ o.spec("domMock", function() { o(select.selectedIndex).equals(1) } }) - o("option.value = null is converted to the empty string", function() { + o("option.value = null is converted to 'null'", function() { var option = $document.createElement("option") option.value = null - o(option.value).equals("") + o(option.value).equals("null") }) o("setting valid value works with optgroup", function() { var select = $document.createElement("select")