@@ -114,7 +114,7 @@ module.exports = function() {
114114 function createElement ( parent , vnode , hooks , ns , nextSibling ) {
115115 var tag = vnode . tag
116116 var attrs = vnode . attrs
117- var is = attrs && attrs . is
117+ var is = vnode . is
118118
119119 ns = getNameSpace ( vnode ) || ns
120120
@@ -396,7 +396,7 @@ module.exports = function() {
396396 }
397397 function updateNode ( parent , old , vnode , hooks , nextSibling , ns ) {
398398 var oldTag = old . tag , tag = vnode . tag
399- if ( oldTag === tag ) {
399+ if ( oldTag === tag && old . is === vnode . is ) {
400400 vnode . state = old . state
401401 vnode . events = old . events
402402 if ( shouldNotUpdate ( vnode , old ) ) return
@@ -426,7 +426,7 @@ module.exports = function() {
426426 }
427427 function updateHTML ( parent , old , vnode , ns , nextSibling ) {
428428 if ( old . children !== vnode . children ) {
429- removeDOM ( parent , old , undefined )
429+ removeDOM ( parent , old )
430430 createHTML ( parent , vnode , ns , nextSibling )
431431 }
432432 else {
@@ -585,71 +585,38 @@ module.exports = function() {
585585 if ( vnode != null ) removeNode ( parent , vnode )
586586 }
587587 }
588- function removeNode ( parent , vnode ) {
589- var mask = 0
588+ function tryBlockRemove ( parent , vnode , source , counter ) {
590589 var original = vnode . state
591- var stateResult , attrsResult
592- if ( typeof vnode . tag !== "string" && typeof vnode . state . onbeforeremove === "function" ) {
593- var result = callHook . call ( vnode . state . onbeforeremove , vnode )
594- if ( result != null && typeof result . then === "function" ) {
595- mask = 1
596- stateResult = result
597- }
598- }
599- if ( vnode . attrs && typeof vnode . attrs . onbeforeremove === "function" ) {
600- var result = callHook . call ( vnode . attrs . onbeforeremove , vnode )
601- if ( result != null && typeof result . then === "function" ) {
602- // eslint-disable-next-line no-bitwise
603- mask |= 2
604- attrsResult = result
605- }
606- }
607- checkState ( vnode , original )
608- var generation
609- // If we can, try to fast-path it and avoid all the overhead of awaiting
610- if ( ! mask ) {
590+ var result = callHook . call ( source . onbeforeremove , vnode )
591+ if ( result == null ) return
592+
593+ var generation = currentRender
594+ for ( var dom of domFor ( vnode ) ) delayedRemoval . set ( dom , generation )
595+ counter . v ++
596+
597+ Promise . resolve ( result ) . finally ( function ( ) {
598+ checkState ( vnode , original )
599+ tryResumeRemove ( parent , vnode , counter )
600+ } )
601+ }
602+ function tryResumeRemove ( parent , vnode , counter ) {
603+ if ( -- counter . v === 0 ) {
611604 onremove ( vnode )
612- removeDOM ( parent , vnode , generation )
613- } else {
614- generation = currentRender
615- for ( var dom of domFor ( vnode ) ) delayedRemoval . set ( dom , generation )
616- if ( stateResult != null ) {
617- stateResult . finally ( function ( ) {
618- // eslint-disable-next-line no-bitwise
619- if ( mask & 1 ) {
620- // eslint-disable-next-line no-bitwise
621- mask &= 2
622- if ( ! mask ) {
623- checkState ( vnode , original )
624- onremove ( vnode )
625- removeDOM ( parent , vnode , generation )
626- }
627- }
628- } )
629- }
630- if ( attrsResult != null ) {
631- attrsResult . finally ( function ( ) {
632- // eslint-disable-next-line no-bitwise
633- if ( mask & 2 ) {
634- // eslint-disable-next-line no-bitwise
635- mask &= 1
636- if ( ! mask ) {
637- checkState ( vnode , original )
638- onremove ( vnode )
639- removeDOM ( parent , vnode , generation )
640- }
641- }
642- } )
643- }
605+ removeDOM ( parent , vnode )
644606 }
645607 }
646- function removeDOM ( parent , vnode , generation ) {
608+ function removeNode ( parent , vnode ) {
609+ var counter = { v : 1 }
610+ if ( typeof vnode . tag !== "string" && typeof vnode . state . onbeforeremove === "function" ) tryBlockRemove ( parent , vnode , vnode . state , counter )
611+ if ( vnode . attrs && typeof vnode . attrs . onbeforeremove === "function" ) tryBlockRemove ( parent , vnode , vnode . attrs , counter )
612+ tryResumeRemove ( parent , vnode , counter )
613+ }
614+ function removeDOM ( parent , vnode ) {
647615 if ( vnode . dom == null ) return
648616 if ( vnode . domSize == null ) {
649- // don't allocate for the common case
650- if ( delayedRemoval . get ( vnode . dom ) === generation ) parent . removeChild ( vnode . dom )
617+ parent . removeChild ( vnode . dom )
651618 } else {
652- for ( var dom of domFor ( vnode , { generation } ) ) parent . removeChild ( dom )
619+ for ( var dom of domFor ( vnode ) ) parent . removeChild ( dom )
653620 }
654621 }
655622
@@ -676,7 +643,7 @@ module.exports = function() {
676643 }
677644 }
678645 function setAttr ( vnode , key , old , value , ns ) {
679- if ( key === "key" || key === "is" || value == null || isLifecycleMethod ( key ) || ( old === value && ! isFormAttribute ( vnode , key ) ) && typeof value !== "object" ) return
646+ if ( key === "key" || value == null || isLifecycleMethod ( key ) || ( old === value && ! isFormAttribute ( vnode , key ) ) && typeof value !== "object" ) return
680647 if ( key [ 0 ] === "o" && key [ 1 ] === "n" ) return updateEvent ( vnode , key , value )
681648 if ( key . slice ( 0 , 6 ) === "xlink:" ) vnode . dom . setAttributeNS ( "http://www.w3.org/1999/xlink" , key . slice ( 6 ) , value )
682649 else if ( key === "style" ) updateStyle ( vnode . dom , old , value )
@@ -709,7 +676,7 @@ module.exports = function() {
709676 }
710677 }
711678 function removeAttr ( vnode , key , old , ns ) {
712- if ( key === "key" || key === "is" || old == null || isLifecycleMethod ( key ) ) return
679+ if ( key === "key" || old == null || isLifecycleMethod ( key ) ) return
713680 if ( key [ 0 ] === "o" && key [ 1 ] === "n" ) updateEvent ( vnode , key , undefined )
714681 else if ( key === "style" ) updateStyle ( vnode . dom , old , null )
715682 else if (
@@ -743,22 +710,24 @@ module.exports = function() {
743710 if ( "selectedIndex" in attrs ) setAttr ( vnode , "selectedIndex" , null , attrs . selectedIndex , undefined )
744711 }
745712 function updateAttrs ( vnode , old , attrs , ns ) {
746- if ( old && old === attrs ) {
747- console . warn ( "Don't reuse attrs object, use new object for every redraw, this will throw in next major" )
748- }
749- if ( attrs != null ) {
750- for ( var key in attrs ) {
751- setAttr ( vnode , key , old && old [ key ] , attrs [ key ] , ns )
752- }
753- }
713+ // Some attributes may NOT be case-sensitive (e.g. data-***),
714+ // so removal should be done first to prevent accidental removal for newly setting values.
754715 var val
755716 if ( old != null ) {
717+ if ( old === attrs ) {
718+ console . warn ( "Don't reuse attrs object, use new object for every redraw, this will throw in next major" )
719+ }
756720 for ( var key in old ) {
757721 if ( ( ( val = old [ key ] ) != null ) && ( attrs == null || attrs [ key ] == null ) ) {
758722 removeAttr ( vnode , key , val , ns )
759723 }
760724 }
761725 }
726+ if ( attrs != null ) {
727+ for ( var key in attrs ) {
728+ setAttr ( vnode , key , old && old [ key ] , attrs [ key ] , ns )
729+ }
730+ }
762731 }
763732 function isFormAttribute ( vnode , attr ) {
764733 return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode . dom === activeElement ( vnode . dom ) || vnode . tag === "option" && vnode . dom . parentNode === activeElement ( vnode . dom )
@@ -770,7 +739,7 @@ module.exports = function() {
770739 // Filter out namespaced keys
771740 return ns === undefined && (
772741 // If it's a custom element, just keep it.
773- vnode . tag . indexOf ( "-" ) > - 1 || vnode . attrs != null && vnode . attrs . is ||
742+ vnode . tag . indexOf ( "-" ) > - 1 || vnode . is ||
774743 // If it's a normal element, let's try to avoid a few browser bugs.
775744 key !== "href" && key !== "list" && key !== "form" && key !== "width" && key !== "height" // && key !== "type"
776745 // Defer the property check until *after* we check everything.
@@ -789,7 +758,7 @@ module.exports = function() {
789758 element . style = style
790759 } else if ( old == null || typeof old !== "object" ) {
791760 // `old` is missing or a string, `style` is an object.
792- element . style . cssText = ""
761+ element . style = ""
793762 // Add new style properties
794763 for ( var key in style ) {
795764 var value = style [ key ]
@@ -800,6 +769,15 @@ module.exports = function() {
800769 }
801770 } else {
802771 // Both old & new are (different) objects.
772+ // Remove style properties that no longer exist
773+ // Style properties may have two cases(dash-case and camelCase),
774+ // so removal should be done first to prevent accidental removal for newly setting values.
775+ for ( var key in old ) {
776+ if ( old [ key ] != null && style [ key ] == null ) {
777+ if ( key . includes ( "-" ) ) element . style . removeProperty ( key )
778+ else element . style [ key ] = ""
779+ }
780+ }
803781 // Update style properties that have changed
804782 for ( var key in style ) {
805783 var value = style [ key ]
@@ -808,13 +786,6 @@ module.exports = function() {
808786 else element . style [ key ] = value
809787 }
810788 }
811- // Remove style properties that no longer exist
812- for ( var key in old ) {
813- if ( old [ key ] != null && style [ key ] == null ) {
814- if ( key . includes ( "-" ) ) element . style . removeProperty ( key )
815- else element . style [ key ] = ""
816- }
817- }
818789 }
819790 }
820791
0 commit comments