Merge pull request #522 from webcomponents/refix-import-node

Make sure IE11 importNode workaround for doc fragments is patch on importNode
This commit is contained in:
Kevin Schaaf
2016-04-15 10:59:01 -07:00
4 changed files with 75 additions and 49 deletions

View File

@@ -1,16 +1,15 @@
language: node_js
sudo: false
node_js: 4
sudo: required
dist: trusty
node_js: stable
addons:
sauce_connect: true
firefox: latest
apt:
sources:
- google-chrome
- ubuntu-toolchain-r-test
packages:
- google-chrome-stable
- g++-4.8
before_script:
- export PATH=$PWD/node_modules/.bin:$PATH
script:
@@ -20,4 +19,3 @@ env:
global:
- secure: c0kVrjNDtqd06Gyg4Xi3iopr0KCz1k0LbZeL+TCbnyCdmAE7m9FcJASWvM2Zr7d774hTiMSi0Z79SlV6XZhLN2pi4EsbdEpsnVeAXXH/GYzDKgpXbdfD/nQv4n1nMXL6XSaZkAX7WwgmrjzJ9cXQJYV9vNHIBRcGoVRRyCFx9v4=
- secure: Mo+AVRGUmlDENnZ2GioF5pU62WhyLUMnPlSqzeodZzJoAnwcNr9VnHiRCgQBLnHCZwjbMv6C0vhWopY7lN9w77vlS5vr8MDZKjYT/YRl9jk0+hStJ+diSS9MD+FnNNerXe+V+WA6NYVHno3vdWRqDDMYzCdH/pyLukkuKdMFaAU=
- CXX=g++-4.8

View File

@@ -350,27 +350,6 @@ function wrapDomMethodToForceUpgrade(obj, methodName) {
wrapDomMethodToForceUpgrade(Node.prototype, 'cloneNode');
wrapDomMethodToForceUpgrade(document, 'importNode');
// Patch document.importNode to work around IE11 bug that
// casues children of a document fragment imported while
// there is a mutation observer to not have a parentNode (!?!)
if (isIE) {
(function() {
var importNode = document.importNode;
document.importNode = function() {
var n = importNode.apply(document, arguments);
// Copy all children to a new document fragment since
// this one may be broken
if (n.nodeType == n.DOCUMENT_FRAGMENT_NODE) {
var f = document.createDocumentFragment();
f.appendChild(n);
return f;
} else {
return n;
}
};
})();
}
// exports
document.registerElement = register;
document.createElement = createElement; // override

View File

@@ -11,17 +11,38 @@
// minimal template polyfill
(function() {
var needsTemplate = (typeof HTMLTemplateElement === 'undefined');
// NOTE: Patch document.importNode to work around IE11 bug that
// casues children of a document fragment imported while
// there is a mutation observer to not have a parentNode (!?!)
// This needs to happen *after* patching importNode to fix template cloning
if (/Trident/.test(navigator.userAgent)) {
(function() {
var importNode = document.importNode;
document.importNode = function() {
var n = importNode.apply(document, arguments);
// Copy all children to a new document fragment since
// this one may be broken
if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
var f = document.createDocumentFragment();
f.appendChild(n);
return f;
} else {
return n;
}
};
})();
}
// returns true if nested templates can be cloned (they cannot be on
// returns true if nested templates cannot be cloned (they cannot be on
// some impl's like Safari 8)
var needsCloning = (function() {
if (!needsTemplate) {
var frag = document.createDocumentFragment();
var t = document.createElement('template');
frag.appendChild(t);
t.content.appendChild(document.createElement('div'));
var clone = frag.cloneNode(true);
return (clone.firstChild.content.childNodes.length === 0);
var t2 = document.createElement('template');
t2.content.appendChild(document.createElement('div'));
t.content.appendChild(t2);
var clone = t.cloneNode(true);
return (clone.content.childNodes.length === 0 || clone.content.firstChild.content.childNodes.length === 0);
}
})();
@@ -42,7 +63,6 @@
/**
Provides a minimal shim for the <template> element.
*/
TemplateImpl.prototype = Object.create(HTMLElement.prototype);
/**
@@ -59,6 +79,11 @@
while (child = template.firstChild) {
template.content.appendChild(child);
}
template.cloneNode = function(deep) {
return TemplateImpl.cloneNode(this, deep);
};
// add innerHTML to template, if possible
// Note: this throws on Safari 7
if (canDecorate) {
@@ -84,10 +109,6 @@
configurable: true
});
template.cloneNode = function(deep) {
return TemplateImpl.cloneNode(this, deep);
};
} catch (err) {
canDecorate = false;
}
@@ -117,7 +138,7 @@
document.createElement = function() {
'use strict';
var el = createElement.apply(document, arguments);
if (el.localName == 'template') {
if (el.localName === 'template') {
TemplateImpl.decorate(el);
}
return el;
@@ -152,7 +173,7 @@
var nativeCloneNode = Node.prototype.cloneNode;
TemplateImpl.cloneNode = function(template, deep) {
var clone = nativeCloneNode.call(template);
var clone = nativeCloneNode.call(template, false);
// NOTE: decorate doesn't auto-fix children because they are already
// decorated so they need special clone fixup.
if (this.decorate) {
@@ -169,7 +190,7 @@
return clone;
};
// Given a source and cloned subtree, find <template>'s in the cloned
// Given a source and cloned subtree, find <template>'s in the cloned
// subtree and replace them with cloned <template>'s from source.
// We must do this because only the source templates have proper .content.
TemplateImpl.fixClonedDom = function(clone, source) {
@@ -203,7 +224,7 @@
// NOTE: we are cloning instead of importing <template>'s.
// However, the ownerDocument of the cloned template will be correct!
// This is because the native import node creates the right document owned
// This is because the native import node creates the right document owned
// subtree and `fixClonedDom` inserts cloned templates into this subtree,
// thus updating the owner doc.
document.importNode = function(element, deep) {
@@ -223,7 +244,6 @@
return TemplateImpl.cloneNode(this, deep);
};
}
}
if (needsTemplate) {

View File

@@ -37,6 +37,32 @@
template = document.querySelector('template');
});
var canInnerHTML = (function() {
var el = document.createElement('div');
try {
Object.defineProperty(el, 'innerHTML', {
get: function(){},
set: function(){}
});
return true;
} catch(e) {
return false;
}
})();
function setupTemplate(template, string) {
if (canInnerHTML) {
template.innerHTML = string;
} else {
var el = document.createElement('div');
el.innerHTML = string;
var nodes = Array.prototype.slice.call(el.childNodes, 0);
for (var i = 0; i < nodes.length; i++) {
template.content.appendChild(nodes[i]);
}
}
}
test('No rendering', function() {
var bcr = template.getBoundingClientRect();
assert.equal(bcr.height, 0);
@@ -58,6 +84,9 @@
});
test('innerHTML', function() {
if (!canInnerHTML) {
this.skip();
}
var imp = document.createElement('template');
assert.equal(imp.innerHTML, '');
var s = 'pre<div>Hi</div><div>Bye</div>post';
@@ -84,7 +113,7 @@
test('clone', function() {
var imp = document.createElement('template');
var s = '<div>Hi</div>';
imp.innerHTML = s;
setupTemplate(imp, s);
var clone = imp.cloneNode();
assert.notEqual(clone, imp, 'element is not cloned');
assert.isDefined(clone.content, 'cloned template content dne');
@@ -100,8 +129,8 @@
test('clone nested', function() {
var imp = document.createElement('template');
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
imp.innerHTML = s;
var clone = imp.cloneNode();
setupTemplate(imp, s);
var clone = imp.cloneNode(false);
assert.notEqual(clone, imp, 'element is not cloned');
assert.isDefined(clone.content, 'cloned template content dne');
assert.equal(clone.content.childNodes.length, 0,
@@ -129,7 +158,7 @@
var imp = document.createElement('div');
var t = document.createElement('template');
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
t.innerHTML = s;
setupTemplate(t, s);
imp.appendChild(t);
var impClone = imp.cloneNode(true);
var imp = imp.firstChild;
@@ -155,7 +184,7 @@
test('importNode', function() {
var imp = document.createElement('template');
var s = '<div>Hi</div>';
imp.innerHTML = s;
setupTemplate(imp, s)
var clone = document.importNode(imp, false);
assert.notEqual(clone, imp, 'element is not cloned');
assert.isDefined(clone.content, 'cloned template content dne');
@@ -171,7 +200,7 @@
test('importNode: nested', function() {
var imp = document.createElement('template');
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
imp.innerHTML = s;
setupTemplate(imp, s);
var clone = document.importNode(imp, false);
assert.notEqual(clone, imp, 'element is not cloned');
assert.isDefined(clone.content, 'cloned template content dne');
@@ -200,7 +229,7 @@
var imp = document.createElement('div');
var t = document.createElement('template');
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
t.innerHTML = s;
setupTemplate(t, s);
imp.appendChild(t);
var impClone = document.importNode(imp, true);
imp = imp.firstChild;