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

Commit 857b82c

Browse files
committed
Upgrade elements when they are created, even if their definition has not flushed.
1 parent ec3c391 commit 857b82c

3 files changed

Lines changed: 79 additions & 16 deletions

File tree

src/CustomElementRegistry.js

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export default class CustomElementRegistry {
120120
constructionStack: [],
121121
};
122122

123+
this._internals.setDefinition(localName, definition);
123124
this._pendingDefinitions.push(definition);
124125

125126
// If we've already called the flush callback and it hasn't called back yet,
@@ -138,39 +139,58 @@ export default class CustomElementRegistry {
138139
this._flushPending = false;
139140

140141
const pendingDefinitions = this._pendingDefinitions;
141-
/** @type {!Map<string, !Array<!Element>>} */
142-
const localNameToUpgradableElements = new Map();
142+
143+
/**
144+
* Unupgraded elements with definitions that were defined *before* the last
145+
* flush, in document order.
146+
* @type {!Array<!Element>}
147+
*/
148+
const elementsWithStableDefinitions = [];
149+
150+
/**
151+
* A map from `localName`s of definitions that were defined *after* the last
152+
* flush to unupgraded elements matching that definition, in document order.
153+
* @type {!Map<string, !Array<!Element>>}
154+
*/
155+
const elementsWithPendingDefinitions = new Map();
143156
for (let i = 0; i < pendingDefinitions.length; i++) {
144-
localNameToUpgradableElements.set(pendingDefinitions[i].localName, []);
157+
elementsWithPendingDefinitions.set(pendingDefinitions[i].localName, []);
145158
}
146159

147160
this._internals.patchAndUpgradeTree(document, {
148161
upgrade: element => {
149-
// Attempt to upgrade using *non-pending* definitions.
150-
this._internals.upgradeElement(element);
151-
152-
// If the element was upgraded, then no pending definition applies to it.
162+
// Ignore the element if it has already upgraded or failed to upgrade.
153163
if (element.__CE_state !== undefined) return;
154164

165+
const localName = element.localName;
166+
155167
// If there is an applicable pending definition for the element, add the
156-
// element to the set of upgradable elements for that definition.
157-
let upgradableElements = localNameToUpgradableElements.get(element.localName);
158-
if (upgradableElements) {
159-
upgradableElements.push(element);
168+
// element to the list of elements to be upgraded with that definition.
169+
const pendingElements = elementsWithPendingDefinitions.get(localName);
170+
if (pendingElements) {
171+
pendingElements.push(element);
172+
// If there is *any other* applicable definition for the element, add it
173+
// to the list of elements with stable definitions that need to be upgraded.
174+
} else if (this._internals.localNameToDefinition(localName)) {
175+
elementsWithStableDefinitions.push(element);
160176
}
161177
},
162178
});
163179

180+
// Upgrade elements with 'stable' definitions first.
181+
for (let i = 0; i < elementsWithStableDefinitions.length; i++) {
182+
this._internals.upgradeElement(elementsWithStableDefinitions[i]);
183+
}
184+
185+
// Upgrade elements with 'pending' definitions in the order they were defined.
164186
while (pendingDefinitions.length > 0) {
165187
const definition = pendingDefinitions.shift();
166188
const localName = definition.localName;
167189

168-
this._internals.setDefinition(localName, definition);
169-
170190
// Attempt to upgrade all applicable elements.
171-
const upgradableElements = localNameToUpgradableElements.get(definition.localName);
172-
for (let i = 0; i < upgradableElements.length; i++) {
173-
this._internals.upgradeElement(upgradableElements[i]);
191+
const pendingUpgradableElements = elementsWithPendingDefinitions.get(definition.localName);
192+
for (let i = 0; i < pendingUpgradableElements.length; i++) {
193+
this._internals.upgradeElement(pendingUpgradableElements[i]);
174194
}
175195

176196
// Resolve any promises created by `whenDefined` for the definition.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>customElements#polyfillWrapFlushCallback</title>
5+
<script>
6+
(window.customElements = window.customElements || {}).forcePolyfill = true;
7+
</script>
8+
<script src="../../../../es6-promise/dist/es6-promise.auto.min.js"></script>
9+
<script src="../../../../web-component-tester/browser.js"></script>
10+
<script src="../../../custom-elements.min.js"></script>
11+
</head>
12+
<body>
13+
<script>
14+
/**
15+
* @license
16+
* Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
17+
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
18+
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
19+
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
20+
* Code distributed by Google as part of the polymer project is also
21+
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
22+
*/
23+
24+
test('Elements are upgraded when created imperatively, even if the flush ' +
25+
'callback has not been called.', function() {
26+
let flush = undefined;
27+
customElements.polyfillWrapFlushCallback(fn => {
28+
flush = fn;
29+
});
30+
31+
class CustomElement0 extends HTMLElement {}
32+
customElements.define('custom-element-0', CustomElement0);
33+
assert.equal(customElements.get('custom-element-0'), CustomElement0);
34+
35+
const element = document.createElement('custom-element-0');
36+
assert.instanceOf(element, CustomElement0);
37+
38+
flush();
39+
});
40+
</script>
41+
</body>
42+
</html>

tests/html/polyfillWrapFlushCallback/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
'./whenDefined_before.html',
1212
'./whenDefined_after.html',
1313
'./upgradeInDefineCallOrder.html',
14+
'./imperativelyCreatedBeforeFlush.html',
1415
]);
1516
</script>

0 commit comments

Comments
 (0)