@@ -260,15 +260,8 @@ const getNonce = memoize(
260260const insertRule = (
261261 container : CSSStyleSheet | CSSMediaRule | CSSKeyframesRule ,
262262 rule : string ,
263- index ? : number
263+ index : number
264264) : false | any => {
265- const maxIndex = container . cssRules . length
266- // In case previous insertion fails, passed index might be wrong
267- if ( index === undefined || index > maxIndex ) {
268- // eslint-disable-next-line no-param-reassign
269- index = maxIndex
270- }
271-
272265 try {
273266 if ( 'insertRule' in container ) {
274267 const c = ( ( container : any ) : CSSStyleSheet )
@@ -286,6 +279,19 @@ const insertRule = (
286279 return container . cssRules [ index ]
287280}
288281
282+ const getValidRuleInsertionIndex = (
283+ container : CSSStyleSheet | CSSMediaRule | CSSKeyframesRule ,
284+ index ? : number
285+ ) : number => {
286+ const maxIndex = container . cssRules . length
287+ // In case previous insertion fails, passed index might be wrong
288+ if ( index === undefined || index > maxIndex ) {
289+ // eslint-disable-next-line no-param-reassign
290+ return maxIndex
291+ }
292+ return index
293+ }
294+
289295const createStyle = ( ) : HTMLElement => {
290296 const el = document . createElement ( 'style' )
291297 // Without it, IE will have a broken source order specificity if we
@@ -311,6 +317,10 @@ export default class DomRenderer {
311317
312318 hasInsertedRules : boolean = false
313319
320+ // Will be empty if link: true option is not set, because
321+ // it is only for use together with insertRule API.
322+ cssRules : AnyCSSRule [ ] = [ ]
323+
314324 constructor ( sheet ?: StyleSheet ) {
315325 // There is no sheet when the renderer is used from a standalone StyleRule.
316326 if ( sheet ) sheets . add ( sheet )
@@ -386,8 +396,13 @@ export default class DomRenderer {
386396 const parent : ContainerRule = ( rule : any )
387397 let latestNativeParent = nativeParent
388398 if ( rule . type === 'conditional' || rule . type === 'keyframes' ) {
399+ const insertionIndex = getValidRuleInsertionIndex ( nativeParent , index )
389400 // We need to render the container without children first.
390- latestNativeParent = insertRule ( nativeParent , parent . toString ( { children : false } ) , index )
401+ latestNativeParent = insertRule (
402+ nativeParent ,
403+ parent . toString ( { children : false } ) ,
404+ insertionIndex
405+ )
391406 if ( latestNativeParent === false ) {
392407 return false
393408 }
@@ -407,13 +422,15 @@ export default class DomRenderer {
407422
408423 if ( ! ruleStr ) return false
409424
410- const nativeRule = insertRule ( nativeParent , ruleStr , index )
425+ const insertionIndex = getValidRuleInsertionIndex ( nativeParent , index )
426+ const nativeRule = insertRule ( nativeParent , ruleStr , insertionIndex )
411427 if ( nativeRule === false ) {
412428 return false
413429 }
414430
415431 this . hasInsertedRules = true
416432 rule . renderable = nativeRule
433+ this . cssRules [ insertionIndex ] = nativeRule
417434 return nativeRule
418435 }
419436
@@ -425,18 +442,15 @@ export default class DomRenderer {
425442 const index = this . indexOf ( cssRule )
426443 if ( index === - 1 ) return false
427444 sheet . deleteRule ( index )
445+ this . cssRules . splice ( index , 1 )
428446 return true
429447 }
430448
431449 /**
432450 * Get index of a CSS Rule.
433451 */
434452 indexOf ( cssRule : AnyCSSRule ) : number {
435- const { cssRules } = this . element . sheet
436- for ( let index = 0 ; index < cssRules . length ; index ++ ) {
437- if ( cssRule === cssRules [ index ] ) return index
438- }
439- return - 1
453+ return this . cssRules . indexOf ( cssRule )
440454 }
441455
442456 /**
@@ -448,6 +462,7 @@ export default class DomRenderer {
448462 const index = this . indexOf ( cssRule )
449463 if ( index === - 1 ) return false
450464 this . element . sheet . deleteRule ( index )
465+ this . cssRules . splice ( index , 1 )
451466 return this . insertRule ( rule , index )
452467 }
453468
0 commit comments