Skip to content
This repository was archived by the owner on Sep 20, 2019. It is now read-only.

Commit 4d3355f

Browse files
committed
Merge pull request #522 from webcomponents/refix-import-node
Make sure IE11 importNode workaround for doc fragments is patch on importNode
2 parents 3ea23df + bffb86c commit 4d3355f

4 files changed

Lines changed: 75 additions & 49 deletions

File tree

.travis.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
language: node_js
2-
sudo: false
3-
node_js: 4
2+
sudo: required
3+
dist: trusty
4+
node_js: stable
45
addons:
56
sauce_connect: true
67
firefox: latest
78
apt:
89
sources:
910
- google-chrome
10-
- ubuntu-toolchain-r-test
1111
packages:
1212
- google-chrome-stable
13-
- g++-4.8
1413
before_script:
1514
- export PATH=$PWD/node_modules/.bin:$PATH
1615
script:
@@ -20,4 +19,3 @@ env:
2019
global:
2120
- secure: c0kVrjNDtqd06Gyg4Xi3iopr0KCz1k0LbZeL+TCbnyCdmAE7m9FcJASWvM2Zr7d774hTiMSi0Z79SlV6XZhLN2pi4EsbdEpsnVeAXXH/GYzDKgpXbdfD/nQv4n1nMXL6XSaZkAX7WwgmrjzJ9cXQJYV9vNHIBRcGoVRRyCFx9v4=
2221
- secure: Mo+AVRGUmlDENnZ2GioF5pU62WhyLUMnPlSqzeodZzJoAnwcNr9VnHiRCgQBLnHCZwjbMv6C0vhWopY7lN9w77vlS5vr8MDZKjYT/YRl9jk0+hStJ+diSS9MD+FnNNerXe+V+WA6NYVHno3vdWRqDDMYzCdH/pyLukkuKdMFaAU=
23-
- CXX=g++-4.8

src/CustomElements/register.js

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -350,27 +350,6 @@ function wrapDomMethodToForceUpgrade(obj, methodName) {
350350
wrapDomMethodToForceUpgrade(Node.prototype, 'cloneNode');
351351
wrapDomMethodToForceUpgrade(document, 'importNode');
352352

353-
// Patch document.importNode to work around IE11 bug that
354-
// casues children of a document fragment imported while
355-
// there is a mutation observer to not have a parentNode (!?!)
356-
if (isIE) {
357-
(function() {
358-
var importNode = document.importNode;
359-
document.importNode = function() {
360-
var n = importNode.apply(document, arguments);
361-
// Copy all children to a new document fragment since
362-
// this one may be broken
363-
if (n.nodeType == n.DOCUMENT_FRAGMENT_NODE) {
364-
var f = document.createDocumentFragment();
365-
f.appendChild(n);
366-
return f;
367-
} else {
368-
return n;
369-
}
370-
};
371-
})();
372-
}
373-
374353
// exports
375354
document.registerElement = register;
376355
document.createElement = createElement; // override

src/Template/Template.js

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,38 @@
1111
// minimal template polyfill
1212
(function() {
1313
var needsTemplate = (typeof HTMLTemplateElement === 'undefined');
14+
// NOTE: Patch document.importNode to work around IE11 bug that
15+
// casues children of a document fragment imported while
16+
// there is a mutation observer to not have a parentNode (!?!)
17+
// This needs to happen *after* patching importNode to fix template cloning
18+
if (/Trident/.test(navigator.userAgent)) {
19+
(function() {
20+
var importNode = document.importNode;
21+
document.importNode = function() {
22+
var n = importNode.apply(document, arguments);
23+
// Copy all children to a new document fragment since
24+
// this one may be broken
25+
if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
26+
var f = document.createDocumentFragment();
27+
f.appendChild(n);
28+
return f;
29+
} else {
30+
return n;
31+
}
32+
};
33+
})();
34+
}
1435

15-
// returns true if nested templates can be cloned (they cannot be on
36+
// returns true if nested templates cannot be cloned (they cannot be on
1637
// some impl's like Safari 8)
1738
var needsCloning = (function() {
1839
if (!needsTemplate) {
19-
var frag = document.createDocumentFragment();
2040
var t = document.createElement('template');
21-
frag.appendChild(t);
22-
t.content.appendChild(document.createElement('div'));
23-
var clone = frag.cloneNode(true);
24-
return (clone.firstChild.content.childNodes.length === 0);
41+
var t2 = document.createElement('template');
42+
t2.content.appendChild(document.createElement('div'));
43+
t.content.appendChild(t2);
44+
var clone = t.cloneNode(true);
45+
return (clone.content.childNodes.length === 0 || clone.content.firstChild.content.childNodes.length === 0);
2546
}
2647
})();
2748

@@ -42,7 +63,6 @@
4263
/**
4364
Provides a minimal shim for the <template> element.
4465
*/
45-
4666
TemplateImpl.prototype = Object.create(HTMLElement.prototype);
4767

4868
/**
@@ -59,6 +79,11 @@
5979
while (child = template.firstChild) {
6080
template.content.appendChild(child);
6181
}
82+
83+
template.cloneNode = function(deep) {
84+
return TemplateImpl.cloneNode(this, deep);
85+
};
86+
6287
// add innerHTML to template, if possible
6388
// Note: this throws on Safari 7
6489
if (canDecorate) {
@@ -84,10 +109,6 @@
84109
configurable: true
85110
});
86111

87-
template.cloneNode = function(deep) {
88-
return TemplateImpl.cloneNode(this, deep);
89-
};
90-
91112
} catch (err) {
92113
canDecorate = false;
93114
}
@@ -117,7 +138,7 @@
117138
document.createElement = function() {
118139
'use strict';
119140
var el = createElement.apply(document, arguments);
120-
if (el.localName == 'template') {
141+
if (el.localName === 'template') {
121142
TemplateImpl.decorate(el);
122143
}
123144
return el;
@@ -152,7 +173,7 @@
152173
var nativeCloneNode = Node.prototype.cloneNode;
153174

154175
TemplateImpl.cloneNode = function(template, deep) {
155-
var clone = nativeCloneNode.call(template);
176+
var clone = nativeCloneNode.call(template, false);
156177
// NOTE: decorate doesn't auto-fix children because they are already
157178
// decorated so they need special clone fixup.
158179
if (this.decorate) {
@@ -169,7 +190,7 @@
169190
return clone;
170191
};
171192

172-
// Given a source and cloned subtree, find <template>'s in the cloned
193+
// Given a source and cloned subtree, find <template>'s in the cloned
173194
// subtree and replace them with cloned <template>'s from source.
174195
// We must do this because only the source templates have proper .content.
175196
TemplateImpl.fixClonedDom = function(clone, source) {
@@ -203,7 +224,7 @@
203224

204225
// NOTE: we are cloning instead of importing <template>'s.
205226
// However, the ownerDocument of the cloned template will be correct!
206-
// This is because the native import node creates the right document owned
227+
// This is because the native import node creates the right document owned
207228
// subtree and `fixClonedDom` inserts cloned templates into this subtree,
208229
// thus updating the owner doc.
209230
document.importNode = function(element, deep) {
@@ -223,7 +244,6 @@
223244
return TemplateImpl.cloneNode(this, deep);
224245
};
225246
}
226-
227247
}
228248

229249
if (needsTemplate) {

tests/Template/tests.html

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,32 @@
3737
template = document.querySelector('template');
3838
});
3939

40+
var canInnerHTML = (function() {
41+
var el = document.createElement('div');
42+
try {
43+
Object.defineProperty(el, 'innerHTML', {
44+
get: function(){},
45+
set: function(){}
46+
});
47+
return true;
48+
} catch(e) {
49+
return false;
50+
}
51+
})();
52+
53+
function setupTemplate(template, string) {
54+
if (canInnerHTML) {
55+
template.innerHTML = string;
56+
} else {
57+
var el = document.createElement('div');
58+
el.innerHTML = string;
59+
var nodes = Array.prototype.slice.call(el.childNodes, 0);
60+
for (var i = 0; i < nodes.length; i++) {
61+
template.content.appendChild(nodes[i]);
62+
}
63+
}
64+
}
65+
4066
test('No rendering', function() {
4167
var bcr = template.getBoundingClientRect();
4268
assert.equal(bcr.height, 0);
@@ -58,6 +84,9 @@
5884
});
5985

6086
test('innerHTML', function() {
87+
if (!canInnerHTML) {
88+
this.skip();
89+
}
6190
var imp = document.createElement('template');
6291
assert.equal(imp.innerHTML, '');
6392
var s = 'pre<div>Hi</div><div>Bye</div>post';
@@ -84,7 +113,7 @@
84113
test('clone', function() {
85114
var imp = document.createElement('template');
86115
var s = '<div>Hi</div>';
87-
imp.innerHTML = s;
116+
setupTemplate(imp, s);
88117
var clone = imp.cloneNode();
89118
assert.notEqual(clone, imp, 'element is not cloned');
90119
assert.isDefined(clone.content, 'cloned template content dne');
@@ -100,8 +129,8 @@
100129
test('clone nested', function() {
101130
var imp = document.createElement('template');
102131
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
103-
imp.innerHTML = s;
104-
var clone = imp.cloneNode();
132+
setupTemplate(imp, s);
133+
var clone = imp.cloneNode(false);
105134
assert.notEqual(clone, imp, 'element is not cloned');
106135
assert.isDefined(clone.content, 'cloned template content dne');
107136
assert.equal(clone.content.childNodes.length, 0,
@@ -129,7 +158,7 @@
129158
var imp = document.createElement('div');
130159
var t = document.createElement('template');
131160
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
132-
t.innerHTML = s;
161+
setupTemplate(t, s);
133162
imp.appendChild(t);
134163
var impClone = imp.cloneNode(true);
135164
var imp = imp.firstChild;
@@ -155,7 +184,7 @@
155184
test('importNode', function() {
156185
var imp = document.createElement('template');
157186
var s = '<div>Hi</div>';
158-
imp.innerHTML = s;
187+
setupTemplate(imp, s)
159188
var clone = document.importNode(imp, false);
160189
assert.notEqual(clone, imp, 'element is not cloned');
161190
assert.isDefined(clone.content, 'cloned template content dne');
@@ -171,7 +200,7 @@
171200
test('importNode: nested', function() {
172201
var imp = document.createElement('template');
173202
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
174-
imp.innerHTML = s;
203+
setupTemplate(imp, s);
175204
var clone = document.importNode(imp, false);
176205
assert.notEqual(clone, imp, 'element is not cloned');
177206
assert.isDefined(clone.content, 'cloned template content dne');
@@ -200,7 +229,7 @@
200229
var imp = document.createElement('div');
201230
var t = document.createElement('template');
202231
var s = 'a<template id="a">b<template id="b">c<template id="c">d</template></template></template>';
203-
t.innerHTML = s;
232+
setupTemplate(t, s);
204233
imp.appendChild(t);
205234
var impClone = document.importNode(imp, true);
206235
imp = imp.firstChild;

0 commit comments

Comments
 (0)