Skip to content
This repository was archived by the owner on Oct 26, 2021. It is now read-only.

Commit f74bcc9

Browse files
committed
Merge remote-tracking branch 'origin/master' into visitedImports-typo
2 parents 651bab2 + f4f5f43 commit f74bcc9

File tree

10 files changed

+1041
-119
lines changed

10 files changed

+1041
-119
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ and [HTML](https://html.spec.whatwg.org/) specifications are marked with the
8080
If you replace the prototype of your constructor `F`, you must make sure
8181
that `F.prototype.constructor === F` remains true. Otherwise, the polyfill
8282
will not be able to create or upgrade your custom elements.
83+
- The [`:defined` CSS pseudo-class](https://html.spec.whatwg.org/multipage/semantics-other.html#pseudo-classes)
84+
is not supported.
8385

8486
### ES5 vs ES2015
8587

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@webcomponents/custom-elements",
3-
"version": "1.0.2",
3+
"version": "1.0.3",
44
"description": "HTML Custom Elements Polyfill",
55
"main": "custom-elements.min.js",
66
"directories": {

src/Patch/DocumentFragment.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1-
// DocumentFragment implements ParentNode, but inserting into a DocumentFragment
2-
// can never cause a tree to be upgraded or connected, because DocumentFragments
3-
// are always disconnected.
1+
import CustomElementInternals from '../CustomElementInternals.js';
2+
import Native from './Native.js';
3+
import PatchParentNode from './Interface/ParentNode.js';
4+
5+
/**
6+
* @param {!CustomElementInternals} internals
7+
*/
8+
export default function(internals) {
9+
PatchParentNode(internals, DocumentFragment.prototype, {
10+
prepend: Native.DocumentFragment_prepend,
11+
append: Native.DocumentFragment_append,
12+
});
13+
};

src/Patch/Element.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ export default function(internals) {
2222
this.__CE_shadowRoot = shadowRoot;
2323
return shadowRoot;
2424
});
25-
} else {
26-
console.warn('Custom Elements: `Element#attachShadow` was not patched.');
2725
}
2826

2927

src/Patch/Interface/ChildNode.js

Lines changed: 105 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -18,93 +18,128 @@ let ChildNodeNativeMethods;
1818
*/
1919
export default function(internals, destination, builtIn) {
2020
/**
21-
* @param {...(!Node|string)} nodes
21+
* @param {!function(...(!Node|string))} builtInMethod
22+
* @return {!function(...(!Node|string))}
2223
*/
23-
destination['before'] = function(...nodes) {
24-
// TODO: Fix this for when one of `nodes` is a DocumentFragment!
25-
const connectedBefore = /** @type {!Array<!Node>} */ (nodes.filter(node => {
26-
// DocumentFragments are not connected and will not be added to the list.
27-
return node instanceof Node && Utilities.isConnected(node);
28-
}));
29-
30-
builtIn.before.apply(this, nodes);
24+
function beforeAfterPatch(builtInMethod) {
25+
return function(...nodes) {
26+
/**
27+
* A copy of `nodes`, with any DocumentFragment replaced by its children.
28+
* @type {!Array<!Node>}
29+
*/
30+
const flattenedNodes = [];
31+
32+
/**
33+
* Elements in `nodes` that were connected before this call.
34+
* @type {!Array<!Node>}
35+
*/
36+
const connectedElements = [];
37+
38+
for (var i = 0; i < nodes.length; i++) {
39+
const node = nodes[i];
3140

32-
for (let i = 0; i < connectedBefore.length; i++) {
33-
internals.disconnectTree(connectedBefore[i]);
34-
}
41+
if (node instanceof Element && Utilities.isConnected(node)) {
42+
connectedElements.push(node);
43+
}
3544

36-
if (Utilities.isConnected(this)) {
37-
for (let i = 0; i < nodes.length; i++) {
38-
const node = nodes[i];
39-
if (node instanceof Element) {
40-
internals.connectTree(node);
45+
if (node instanceof DocumentFragment) {
46+
for (let child = node.firstChild; child; child = child.nextSibling) {
47+
flattenedNodes.push(child);
48+
}
49+
} else {
50+
flattenedNodes.push(node);
4151
}
4252
}
43-
}
44-
};
4553

46-
/**
47-
* @param {...(!Node|string)} nodes
48-
*/
49-
destination['after'] = function(...nodes) {
50-
// TODO: Fix this for when one of `nodes` is a DocumentFragment!
51-
const connectedBefore = /** @type {!Array<!Node>} */ (nodes.filter(node => {
52-
// DocumentFragments are not connected and will not be added to the list.
53-
return node instanceof Node && Utilities.isConnected(node);
54-
}));
55-
56-
builtIn.after.apply(this, nodes);
54+
builtInMethod.apply(this, nodes);
5755

58-
for (let i = 0; i < connectedBefore.length; i++) {
59-
internals.disconnectTree(connectedBefore[i]);
60-
}
56+
for (let i = 0; i < connectedElements.length; i++) {
57+
internals.disconnectTree(connectedElements[i]);
58+
}
6159

62-
if (Utilities.isConnected(this)) {
63-
for (let i = 0; i < nodes.length; i++) {
64-
const node = nodes[i];
65-
if (node instanceof Element) {
66-
internals.connectTree(node);
60+
if (Utilities.isConnected(this)) {
61+
for (let i = 0; i < flattenedNodes.length; i++) {
62+
const node = flattenedNodes[i];
63+
if (node instanceof Element) {
64+
internals.connectTree(node);
65+
}
6766
}
6867
}
69-
}
70-
};
71-
72-
/**
73-
* @param {...(!Node|string)} nodes
74-
*/
75-
destination['replaceWith'] = function(...nodes) {
76-
// TODO: Fix this for when one of `nodes` is a DocumentFragment!
77-
const connectedBefore = /** @type {!Array<!Node>} */ (nodes.filter(node => {
78-
// DocumentFragments are not connected and will not be added to the list.
79-
return node instanceof Node && Utilities.isConnected(node);
80-
}));
68+
};
69+
}
70+
71+
if (builtIn.before !== undefined) {
72+
Utilities.setPropertyUnchecked(destination, 'before', beforeAfterPatch(builtIn.before));
73+
}
74+
75+
if (builtIn.before !== undefined) {
76+
Utilities.setPropertyUnchecked(destination, 'after', beforeAfterPatch(builtIn.after));
77+
}
78+
79+
if (builtIn.replaceWith !== undefined) {
80+
Utilities.setPropertyUnchecked(destination, 'replaceWith',
81+
/**
82+
* @param {...(!Node|string)} nodes
83+
*/
84+
function(...nodes) {
85+
/**
86+
* A copy of `nodes`, with any DocumentFragment replaced by its children.
87+
* @type {!Array<!Node>}
88+
*/
89+
const flattenedNodes = [];
90+
91+
/**
92+
* Elements in `nodes` that were connected before this call.
93+
* @type {!Array<!Node>}
94+
*/
95+
const connectedElements = [];
96+
97+
for (var i = 0; i < nodes.length; i++) {
98+
const node = nodes[i];
99+
100+
if (node instanceof Element && Utilities.isConnected(node)) {
101+
connectedElements.push(node);
102+
}
103+
104+
if (node instanceof DocumentFragment) {
105+
for (let child = node.firstChild; child; child = child.nextSibling) {
106+
flattenedNodes.push(child);
107+
}
108+
} else {
109+
flattenedNodes.push(node);
110+
}
111+
}
81112

82-
const wasConnected = Utilities.isConnected(this);
113+
const wasConnected = Utilities.isConnected(this);
83114

84-
builtIn.replaceWith.apply(this, nodes);
115+
builtIn.replaceWith.apply(this, nodes);
85116

86-
for (let i = 0; i < connectedBefore.length; i++) {
87-
internals.disconnectTree(connectedBefore[i]);
88-
}
117+
for (let i = 0; i < connectedElements.length; i++) {
118+
internals.disconnectTree(connectedElements[i]);
119+
}
89120

90-
if (wasConnected) {
91-
internals.disconnectTree(this);
92-
for (let i = 0; i < nodes.length; i++) {
93-
const node = nodes[i];
94-
if (node instanceof Element) {
95-
internals.connectTree(node);
121+
if (wasConnected) {
122+
internals.disconnectTree(this);
123+
for (let i = 0; i < flattenedNodes.length; i++) {
124+
const node = flattenedNodes[i];
125+
if (node instanceof Element) {
126+
internals.connectTree(node);
127+
}
128+
}
96129
}
97-
}
130+
});
98131
}
99-
};
100132

101-
destination['remove'] = function() {
102-
const wasConnected = Utilities.isConnected(this);
133+
if (builtIn.remove !== undefined) {
134+
Utilities.setPropertyUnchecked(destination, 'remove',
135+
function() {
136+
const wasConnected = Utilities.isConnected(this);
103137

104-
builtIn.remove.call(this);
138+
builtIn.remove.call(this);
105139

106-
if (wasConnected) {
107-
internals.disconnectTree(this);
108-
}
109-
};
140+
if (wasConnected) {
141+
internals.disconnectTree(this);
142+
}
143+
});
144+
}
110145
};

src/Patch/Interface/ParentNode.js

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,54 +16,61 @@ let ParentNodeNativeMethods;
1616
*/
1717
export default function(internals, destination, builtIn) {
1818
/**
19-
* @param {...(!Node|string)} nodes
19+
* @param {!function(...(!Node|string))} builtInMethod
20+
* @return {!function(...(!Node|string))}
2021
*/
21-
destination['prepend'] = function(...nodes) {
22-
// TODO: Fix this for when one of `nodes` is a DocumentFragment!
23-
const connectedBefore = /** @type {!Array<!Node>} */ (nodes.filter(node => {
24-
// DocumentFragments are not connected and will not be added to the list.
25-
return node instanceof Node && Utilities.isConnected(node);
26-
}));
22+
function appendPrependPatch(builtInMethod) {
23+
return function(...nodes) {
24+
/**
25+
* A copy of `nodes`, with any DocumentFragment replaced by its children.
26+
* @type {!Array<!Node>}
27+
*/
28+
const flattenedNodes = [];
2729

28-
builtIn.prepend.apply(this, nodes);
30+
/**
31+
* Elements in `nodes` that were connected before this call.
32+
* @type {!Array<!Node>}
33+
*/
34+
const connectedElements = [];
2935

30-
for (let i = 0; i < connectedBefore.length; i++) {
31-
internals.disconnectTree(connectedBefore[i]);
32-
}
33-
34-
if (Utilities.isConnected(this)) {
35-
for (let i = 0; i < nodes.length; i++) {
36+
for (var i = 0; i < nodes.length; i++) {
3637
const node = nodes[i];
37-
if (node instanceof Element) {
38-
internals.connectTree(node);
38+
39+
if (node instanceof Element && Utilities.isConnected(node)) {
40+
connectedElements.push(node);
3941
}
40-
}
41-
}
42-
};
4342

44-
/**
45-
* @param {...(!Node|string)} nodes
46-
*/
47-
destination['append'] = function(...nodes) {
48-
// TODO: Fix this for when one of `nodes` is a DocumentFragment!
49-
const connectedBefore = /** @type {!Array<!Node>} */ (nodes.filter(node => {
50-
// DocumentFragments are not connected and will not be added to the list.
51-
return node instanceof Node && Utilities.isConnected(node);
52-
}));
43+
if (node instanceof DocumentFragment) {
44+
for (let child = node.firstChild; child; child = child.nextSibling) {
45+
flattenedNodes.push(child);
46+
}
47+
} else {
48+
flattenedNodes.push(node);
49+
}
50+
}
5351

54-
builtIn.append.apply(this, nodes);
52+
builtInMethod.apply(this, nodes);
5553

56-
for (let i = 0; i < connectedBefore.length; i++) {
57-
internals.disconnectTree(connectedBefore[i]);
58-
}
54+
for (let i = 0; i < connectedElements.length; i++) {
55+
internals.disconnectTree(connectedElements[i]);
56+
}
5957

60-
if (Utilities.isConnected(this)) {
61-
for (let i = 0; i < nodes.length; i++) {
62-
const node = nodes[i];
63-
if (node instanceof Element) {
64-
internals.connectTree(node);
58+
if (Utilities.isConnected(this)) {
59+
for (let i = 0; i < flattenedNodes.length; i++) {
60+
const node = flattenedNodes[i];
61+
if (node instanceof Element) {
62+
internals.connectTree(node);
63+
}
6564
}
6665
}
67-
}
68-
};
66+
};
67+
}
68+
69+
if (builtIn.prepend !== undefined) {
70+
Utilities.setPropertyUnchecked(destination, 'prepend', appendPrependPatch(builtIn.prepend));
71+
}
72+
73+
if (builtIn.append !== undefined) {
74+
Utilities.setPropertyUnchecked(destination, 'append', appendPrependPatch(builtIn.append));
75+
}
6976
};

src/Patch/Native.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ export default {
44
Document_importNode: window.Document.prototype.importNode,
55
Document_prepend: window.Document.prototype['prepend'],
66
Document_append: window.Document.prototype['append'],
7+
DocumentFragment_prepend: window.DocumentFragment.prototype['prepend'],
8+
DocumentFragment_append: window.DocumentFragment.prototype['append'],
79
Node_cloneNode: window.Node.prototype.cloneNode,
810
Node_appendChild: window.Node.prototype.appendChild,
911
Node_insertBefore: window.Node.prototype.insertBefore,

src/custom-elements.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import CustomElementRegistry from './CustomElementRegistry.js';
1313

1414
import PatchHTMLElement from './Patch/HTMLElement.js';
1515
import PatchDocument from './Patch/Document.js';
16+
import PatchDocumentFragment from './Patch/DocumentFragment.js';
1617
import PatchNode from './Patch/Node.js';
1718
import PatchElement from './Patch/Element.js';
1819

@@ -27,6 +28,7 @@ if (!priorCustomElements ||
2728

2829
PatchHTMLElement(internals);
2930
PatchDocument(internals);
31+
PatchDocumentFragment(internals);
3032
PatchNode(internals);
3133
PatchElement(internals);
3234

0 commit comments

Comments
 (0)