@@ -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.
0 commit comments