@lwc/engine-core 2.7.2 → 2.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -442,62 +442,204 @@ function logWarn(message, vm) {
442
442
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
443
443
  */
444
444
 
445
- function handleEvent(event, vnode) {
446
- const {
447
- type
448
- } = event;
449
- const {
450
- data: {
451
- on
452
- }
453
- } = vnode;
454
- const handler = on && on[type]; // call event handler if exists
445
+ function isUndef(s) {
446
+ return s === undefined;
447
+ }
448
+
449
+ function sameVnode(vnode1, vnode2) {
450
+ return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
451
+ }
452
+
453
+ function isVNode(vnode) {
454
+ return vnode != null;
455
+ }
456
+
457
+ function createKeyToOldIdx(children, beginIdx, endIdx) {
458
+ const map = {};
459
+ let j, key, ch; // TODO [#1637]: simplify this by assuming that all vnodes has keys
460
+
461
+ for (j = beginIdx; j <= endIdx; ++j) {
462
+ ch = children[j];
455
463
 
456
- if (handler) {
457
- handler.call(undefined, event);
464
+ if (isVNode(ch)) {
465
+ key = ch.key;
466
+
467
+ if (key !== undefined) {
468
+ map[key] = j;
469
+ }
470
+ }
458
471
  }
472
+
473
+ return map;
459
474
  }
460
475
 
461
- function createListener() {
462
- return function handler(event) {
463
- handleEvent(event, handler.vnode);
464
- };
476
+ function addVnodes(parentElm, before, vnodes, startIdx, endIdx) {
477
+ for (; startIdx <= endIdx; ++startIdx) {
478
+ const ch = vnodes[startIdx];
479
+
480
+ if (isVNode(ch)) {
481
+ ch.hook.create(ch);
482
+ ch.hook.insert(ch, parentElm, before);
483
+ }
484
+ }
465
485
  }
466
486
 
467
- function updateAllEventListeners(oldVnode, vnode) {
468
- if (shared.isUndefined(oldVnode.listener)) {
469
- createAllEventListeners(vnode);
470
- } else {
471
- vnode.listener = oldVnode.listener;
472
- vnode.listener.vnode = vnode;
487
+ function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
488
+ for (; startIdx <= endIdx; ++startIdx) {
489
+ const ch = vnodes[startIdx]; // text nodes do not have logic associated to them
490
+
491
+ if (isVNode(ch)) {
492
+ ch.hook.remove(ch, parentElm);
493
+ }
473
494
  }
474
495
  }
475
496
 
476
- function createAllEventListeners(vnode) {
477
- const {
478
- elm,
479
- data: {
480
- on
497
+ function updateDynamicChildren(parentElm, oldCh, newCh) {
498
+ let oldStartIdx = 0;
499
+ let newStartIdx = 0;
500
+ let oldEndIdx = oldCh.length - 1;
501
+ let oldStartVnode = oldCh[0];
502
+ let oldEndVnode = oldCh[oldEndIdx];
503
+ const newChEnd = newCh.length - 1;
504
+ let newEndIdx = newChEnd;
505
+ let newStartVnode = newCh[0];
506
+ let newEndVnode = newCh[newEndIdx];
507
+ let oldKeyToIdx;
508
+ let idxInOld;
509
+ let elmToMove;
510
+ let before;
511
+
512
+ while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
513
+ if (!isVNode(oldStartVnode)) {
514
+ oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left
515
+ } else if (!isVNode(oldEndVnode)) {
516
+ oldEndVnode = oldCh[--oldEndIdx];
517
+ } else if (!isVNode(newStartVnode)) {
518
+ newStartVnode = newCh[++newStartIdx];
519
+ } else if (!isVNode(newEndVnode)) {
520
+ newEndVnode = newCh[--newEndIdx];
521
+ } else if (sameVnode(oldStartVnode, newStartVnode)) {
522
+ patchVnode(oldStartVnode, newStartVnode);
523
+ oldStartVnode = oldCh[++oldStartIdx];
524
+ newStartVnode = newCh[++newStartIdx];
525
+ } else if (sameVnode(oldEndVnode, newEndVnode)) {
526
+ patchVnode(oldEndVnode, newEndVnode);
527
+ oldEndVnode = oldCh[--oldEndIdx];
528
+ newEndVnode = newCh[--newEndIdx];
529
+ } else if (sameVnode(oldStartVnode, newEndVnode)) {
530
+ // Vnode moved right
531
+ patchVnode(oldStartVnode, newEndVnode);
532
+ newEndVnode.hook.move(oldStartVnode, parentElm, nextSibling(oldEndVnode.elm));
533
+ oldStartVnode = oldCh[++oldStartIdx];
534
+ newEndVnode = newCh[--newEndIdx];
535
+ } else if (sameVnode(oldEndVnode, newStartVnode)) {
536
+ // Vnode moved left
537
+ patchVnode(oldEndVnode, newStartVnode);
538
+ newStartVnode.hook.move(oldEndVnode, parentElm, oldStartVnode.elm);
539
+ oldEndVnode = oldCh[--oldEndIdx];
540
+ newStartVnode = newCh[++newStartIdx];
541
+ } else {
542
+ if (oldKeyToIdx === undefined) {
543
+ oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
544
+ }
545
+
546
+ idxInOld = oldKeyToIdx[newStartVnode.key];
547
+
548
+ if (isUndef(idxInOld)) {
549
+ // New element
550
+ newStartVnode.hook.create(newStartVnode);
551
+ newStartVnode.hook.insert(newStartVnode, parentElm, oldStartVnode.elm);
552
+ newStartVnode = newCh[++newStartIdx];
553
+ } else {
554
+ elmToMove = oldCh[idxInOld];
555
+
556
+ if (isVNode(elmToMove)) {
557
+ if (elmToMove.sel !== newStartVnode.sel) {
558
+ // New element
559
+ newStartVnode.hook.create(newStartVnode);
560
+ newStartVnode.hook.insert(newStartVnode, parentElm, oldStartVnode.elm);
561
+ } else {
562
+ patchVnode(elmToMove, newStartVnode);
563
+ oldCh[idxInOld] = undefined;
564
+ newStartVnode.hook.move(elmToMove, parentElm, oldStartVnode.elm);
565
+ }
566
+ }
567
+
568
+ newStartVnode = newCh[++newStartIdx];
569
+ }
481
570
  }
482
- } = vnode;
571
+ }
483
572
 
484
- if (shared.isUndefined(on)) {
573
+ if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {
574
+ if (oldStartIdx > oldEndIdx) {
575
+ // There's some cases in which the sub array of vnodes to be inserted is followed by null(s) and an
576
+ // already processed vnode, in such cases the vnodes to be inserted should be before that processed vnode.
577
+ let i = newEndIdx;
578
+ let n;
579
+
580
+ do {
581
+ n = newCh[++i];
582
+ } while (!isVNode(n) && i < newChEnd);
583
+
584
+ before = isVNode(n) ? n.elm : null;
585
+ addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx);
586
+ } else {
587
+ removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
588
+ }
589
+ }
590
+ }
591
+ function updateStaticChildren(parentElm, oldCh, newCh) {
592
+ const oldChLength = oldCh.length;
593
+ const newChLength = newCh.length;
594
+
595
+ if (oldChLength === 0) {
596
+ // the old list is empty, we can directly insert anything new
597
+ addVnodes(parentElm, null, newCh, 0, newChLength);
485
598
  return;
486
599
  }
487
600
 
488
- const listener = vnode.listener = createListener();
489
- listener.vnode = vnode;
490
- let name;
601
+ if (newChLength === 0) {
602
+ // the old list is nonempty and the new list is empty so we can directly remove all old nodes
603
+ // this is the case in which the dynamic children of an if-directive should be removed
604
+ removeVnodes(parentElm, oldCh, 0, oldChLength);
605
+ return;
606
+ } // if the old list is not empty, the new list MUST have the same
607
+ // amount of nodes, that's why we call this static children
608
+
609
+
610
+ let referenceElm = null;
611
+
612
+ for (let i = newChLength - 1; i >= 0; i -= 1) {
613
+ const vnode = newCh[i];
614
+ const oldVNode = oldCh[i];
615
+
616
+ if (vnode !== oldVNode) {
617
+ if (isVNode(oldVNode)) {
618
+ if (isVNode(vnode)) {
619
+ // both vnodes must be equivalent, and se just need to patch them
620
+ patchVnode(oldVNode, vnode);
621
+ referenceElm = vnode.elm;
622
+ } else {
623
+ // removing the old vnode since the new one is null
624
+ oldVNode.hook.remove(oldVNode, parentElm);
625
+ }
626
+ } else if (isVNode(vnode)) {
627
+ // this condition is unnecessary
628
+ vnode.hook.create(vnode); // insert the new node one since the old one is null
491
629
 
492
- for (name in on) {
493
- addEventListener(elm, name, listener);
630
+ vnode.hook.insert(vnode, parentElm, referenceElm);
631
+ referenceElm = vnode.elm;
632
+ }
633
+ }
494
634
  }
495
635
  }
496
636
 
497
- var modEvents = {
498
- update: updateAllEventListeners,
499
- create: createAllEventListeners
500
- };
637
+ function patchVnode(oldVnode, vnode) {
638
+ if (oldVnode !== vnode) {
639
+ vnode.elm = oldVnode.elm;
640
+ vnode.hook.update(oldVnode, vnode);
641
+ }
642
+ }
501
643
 
502
644
  /*
503
645
  * Copyright (c) 2018, salesforce.com, inc.
@@ -621,573 +763,49 @@ function unlockAttribute(elm, key) {
621
763
  * SPDX-License-Identifier: MIT
622
764
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
623
765
  */
624
- const xlinkNS = 'http://www.w3.org/1999/xlink';
625
- const xmlNS = 'http://www.w3.org/XML/1998/namespace';
626
- const ColonCharCode = 58;
627
-
628
- function updateAttrs(oldVnode, vnode) {
629
- const {
630
- data: {
631
- attrs
632
- }
633
- } = vnode;
634
766
 
635
- if (shared.isUndefined(attrs)) {
636
- return;
637
- }
767
+ function generateDataDescriptor(options) {
768
+ return shared.assign({
769
+ configurable: true,
770
+ enumerable: true,
771
+ writable: true
772
+ }, options);
773
+ }
638
774
 
639
- let {
640
- data: {
641
- attrs: oldAttrs
642
- }
643
- } = oldVnode;
775
+ function generateAccessorDescriptor(options) {
776
+ return shared.assign({
777
+ configurable: true,
778
+ enumerable: true
779
+ }, options);
780
+ }
644
781
 
645
- if (oldAttrs === attrs) {
646
- return;
782
+ let isDomMutationAllowed = false;
783
+ function unlockDomMutation() {
784
+ if (process.env.NODE_ENV === 'production') {
785
+ // this method should never leak to prod
786
+ throw new ReferenceError();
647
787
  }
648
788
 
649
- if (process.env.NODE_ENV !== 'production') {
650
- shared.assert.invariant(shared.isUndefined(oldAttrs) || shared.keys(oldAttrs).join(',') === shared.keys(attrs).join(','), `vnode.data.attrs cannot change shape.`);
789
+ isDomMutationAllowed = true;
790
+ }
791
+ function lockDomMutation() {
792
+ if (process.env.NODE_ENV === 'production') {
793
+ // this method should never leak to prod
794
+ throw new ReferenceError();
651
795
  }
652
796
 
653
- const elm = vnode.elm;
654
- let key;
655
- oldAttrs = shared.isUndefined(oldAttrs) ? EmptyObject : oldAttrs; // update modified attributes, add new attributes
656
- // this routine is only useful for data-* attributes in all kind of elements
657
- // and aria-* in standard elements (custom elements will use props for these)
797
+ isDomMutationAllowed = false;
798
+ }
658
799
 
659
- for (key in attrs) {
660
- const cur = attrs[key];
661
- const old = oldAttrs[key];
800
+ function logMissingPortalError(name, type) {
801
+ return logError(`The \`${name}\` ${type} is available only on elements that use the \`lwc:dom="manual"\` directive.`);
802
+ }
662
803
 
663
- if (old !== cur) {
664
- unlockAttribute(elm, key);
665
-
666
- if (shared.StringCharCodeAt.call(key, 3) === ColonCharCode) {
667
- // Assume xml namespace
668
- setAttribute(elm, key, cur, xmlNS);
669
- } else if (shared.StringCharCodeAt.call(key, 5) === ColonCharCode) {
670
- // Assume xlink namespace
671
- setAttribute(elm, key, cur, xlinkNS);
672
- } else if (shared.isNull(cur) || shared.isUndefined(cur)) {
673
- removeAttribute(elm, key);
674
- } else {
675
- setAttribute(elm, key, cur);
676
- }
677
-
678
- lockAttribute();
679
- }
680
- }
681
- }
682
-
683
- const emptyVNode$3 = {
684
- data: {}
685
- };
686
- var modAttrs = {
687
- create: vnode => updateAttrs(emptyVNode$3, vnode),
688
- update: updateAttrs
689
- };
690
-
691
- /*
692
- * Copyright (c) 2018, salesforce.com, inc.
693
- * All rights reserved.
694
- * SPDX-License-Identifier: MIT
695
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
696
- */
697
-
698
- function isLiveBindingProp(sel, key) {
699
- // For properties with live bindings, we read values from the DOM element
700
- // instead of relying on internally tracked values.
701
- return sel === 'input' && (key === 'value' || key === 'checked');
702
- }
703
-
704
- function update(oldVnode, vnode) {
705
- const props = vnode.data.props;
706
-
707
- if (shared.isUndefined(props)) {
708
- return;
709
- }
710
-
711
- const oldProps = oldVnode.data.props;
712
-
713
- if (oldProps === props) {
714
- return;
715
- }
716
-
717
- if (process.env.NODE_ENV !== 'production') {
718
- shared.assert.invariant(shared.isUndefined(oldProps) || shared.keys(oldProps).join(',') === shared.keys(props).join(','), 'vnode.data.props cannot change shape.');
719
- }
720
-
721
- const isFirstPatch = shared.isUndefined(oldProps);
722
- const {
723
- elm,
724
- sel
725
- } = vnode;
726
-
727
- for (const key in props) {
728
- const cur = props[key]; // if it is the first time this element is patched, or the current value is different to the previous value...
729
-
730
- if (isFirstPatch || cur !== (isLiveBindingProp(sel, key) ? getProperty(elm, key) : oldProps[key])) {
731
- setProperty(elm, key, cur);
732
- }
733
- }
734
- }
735
-
736
- const emptyVNode$2 = {
737
- data: {}
738
- };
739
- var modProps = {
740
- create: vnode => update(emptyVNode$2, vnode),
741
- update
742
- };
743
-
744
- /*
745
- * Copyright (c) 2018, salesforce.com, inc.
746
- * All rights reserved.
747
- * SPDX-License-Identifier: MIT
748
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
749
- */
750
- const classNameToClassMap = shared.create(null);
751
-
752
- function getMapFromClassName(className) {
753
- // Intentionally using == to match undefined and null values from computed style attribute
754
- if (className == null) {
755
- return EmptyObject;
756
- } // computed class names must be string
757
-
758
-
759
- className = shared.isString(className) ? className : className + '';
760
- let map = classNameToClassMap[className];
761
-
762
- if (map) {
763
- return map;
764
- }
765
-
766
- map = shared.create(null);
767
- let start = 0;
768
- let o;
769
- const len = className.length;
770
-
771
- for (o = 0; o < len; o++) {
772
- if (shared.StringCharCodeAt.call(className, o) === SPACE_CHAR) {
773
- if (o > start) {
774
- map[shared.StringSlice.call(className, start, o)] = true;
775
- }
776
-
777
- start = o + 1;
778
- }
779
- }
780
-
781
- if (o > start) {
782
- map[shared.StringSlice.call(className, start, o)] = true;
783
- }
784
-
785
- classNameToClassMap[className] = map;
786
-
787
- if (process.env.NODE_ENV !== 'production') {
788
- // just to make sure that this object never changes as part of the diffing algo
789
- shared.freeze(map);
790
- }
791
-
792
- return map;
793
- }
794
-
795
- function updateClassAttribute(oldVnode, vnode) {
796
- const {
797
- elm,
798
- data: {
799
- className: newClass
800
- }
801
- } = vnode;
802
- const {
803
- data: {
804
- className: oldClass
805
- }
806
- } = oldVnode;
807
-
808
- if (oldClass === newClass) {
809
- return;
810
- }
811
-
812
- const classList = getClassList(elm);
813
- const newClassMap = getMapFromClassName(newClass);
814
- const oldClassMap = getMapFromClassName(oldClass);
815
- let name;
816
-
817
- for (name in oldClassMap) {
818
- // remove only if it is not in the new class collection and it is not set from within the instance
819
- if (shared.isUndefined(newClassMap[name])) {
820
- classList.remove(name);
821
- }
822
- }
823
-
824
- for (name in newClassMap) {
825
- if (shared.isUndefined(oldClassMap[name])) {
826
- classList.add(name);
827
- }
828
- }
829
- }
830
-
831
- const emptyVNode$1 = {
832
- data: {}
833
- };
834
- var modComputedClassName = {
835
- create: vnode => updateClassAttribute(emptyVNode$1, vnode),
836
- update: updateClassAttribute
837
- };
838
-
839
- /*
840
- * Copyright (c) 2018, salesforce.com, inc.
841
- * All rights reserved.
842
- * SPDX-License-Identifier: MIT
843
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
844
- */
845
-
846
- function updateStyleAttribute(oldVnode, vnode) {
847
- const {
848
- elm,
849
- data: {
850
- style: newStyle
851
- }
852
- } = vnode;
853
-
854
- if (oldVnode.data.style === newStyle) {
855
- return;
856
- }
857
-
858
- if (!shared.isString(newStyle) || newStyle === '') {
859
- removeAttribute(elm, 'style');
860
- } else {
861
- setAttribute(elm, 'style', newStyle);
862
- }
863
- }
864
-
865
- const emptyVNode = {
866
- data: {}
867
- };
868
- var modComputedStyle = {
869
- create: vnode => updateStyleAttribute(emptyVNode, vnode),
870
- update: updateStyleAttribute
871
- };
872
-
873
- /*
874
- * Copyright (c) 2018, salesforce.com, inc.
875
- * All rights reserved.
876
- * SPDX-License-Identifier: MIT
877
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
878
- */
879
- // The compiler takes care of transforming the inline classnames into an object. It's faster to set the
880
- // different classnames properties individually instead of via a string.
881
-
882
- function createClassAttribute(vnode) {
883
- const {
884
- elm,
885
- data: {
886
- classMap
887
- }
888
- } = vnode;
889
-
890
- if (shared.isUndefined(classMap)) {
891
- return;
892
- }
893
-
894
- const classList = getClassList(elm);
895
-
896
- for (const name in classMap) {
897
- classList.add(name);
898
- }
899
- }
900
-
901
- var modStaticClassName = {
902
- create: createClassAttribute
903
- };
904
-
905
- /*
906
- * Copyright (c) 2018, salesforce.com, inc.
907
- * All rights reserved.
908
- * SPDX-License-Identifier: MIT
909
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
910
- */
911
- // The compiler takes care of transforming the inline style into an object. It's faster to set the
912
- // different style properties individually instead of via a string.
913
-
914
- function createStyleAttribute(vnode) {
915
- const {
916
- elm,
917
- data: {
918
- styleDecls
919
- }
920
- } = vnode;
921
-
922
- if (shared.isUndefined(styleDecls)) {
923
- return;
924
- }
925
-
926
- for (let i = 0; i < styleDecls.length; i++) {
927
- const [prop, value, important] = styleDecls[i];
928
- setCSSStyleProperty(elm, prop, value, important);
929
- }
930
- }
931
-
932
- var modStaticStyle = {
933
- create: createStyleAttribute
934
- };
935
-
936
- /*
937
- * Copyright (c) 2018, salesforce.com, inc.
938
- * All rights reserved.
939
- * SPDX-License-Identifier: MIT
940
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
941
- */
942
-
943
- function isUndef(s) {
944
- return s === undefined;
945
- }
946
-
947
- function sameVnode(vnode1, vnode2) {
948
- return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
949
- }
950
-
951
- function isVNode(vnode) {
952
- return vnode != null;
953
- }
954
-
955
- function createKeyToOldIdx(children, beginIdx, endIdx) {
956
- const map = {};
957
- let j, key, ch; // TODO [#1637]: simplify this by assuming that all vnodes has keys
958
-
959
- for (j = beginIdx; j <= endIdx; ++j) {
960
- ch = children[j];
961
-
962
- if (isVNode(ch)) {
963
- key = ch.key;
964
-
965
- if (key !== undefined) {
966
- map[key] = j;
967
- }
968
- }
969
- }
970
-
971
- return map;
972
- }
973
-
974
- function addVnodes(parentElm, before, vnodes, startIdx, endIdx) {
975
- for (; startIdx <= endIdx; ++startIdx) {
976
- const ch = vnodes[startIdx];
977
-
978
- if (isVNode(ch)) {
979
- ch.hook.create(ch);
980
- ch.hook.insert(ch, parentElm, before);
981
- }
982
- }
983
- }
984
-
985
- function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
986
- for (; startIdx <= endIdx; ++startIdx) {
987
- const ch = vnodes[startIdx]; // text nodes do not have logic associated to them
988
-
989
- if (isVNode(ch)) {
990
- ch.hook.remove(ch, parentElm);
991
- }
992
- }
993
- }
994
-
995
- function updateDynamicChildren(parentElm, oldCh, newCh) {
996
- let oldStartIdx = 0;
997
- let newStartIdx = 0;
998
- let oldEndIdx = oldCh.length - 1;
999
- let oldStartVnode = oldCh[0];
1000
- let oldEndVnode = oldCh[oldEndIdx];
1001
- const newChEnd = newCh.length - 1;
1002
- let newEndIdx = newChEnd;
1003
- let newStartVnode = newCh[0];
1004
- let newEndVnode = newCh[newEndIdx];
1005
- let oldKeyToIdx;
1006
- let idxInOld;
1007
- let elmToMove;
1008
- let before;
1009
-
1010
- while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
1011
- if (!isVNode(oldStartVnode)) {
1012
- oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left
1013
- } else if (!isVNode(oldEndVnode)) {
1014
- oldEndVnode = oldCh[--oldEndIdx];
1015
- } else if (!isVNode(newStartVnode)) {
1016
- newStartVnode = newCh[++newStartIdx];
1017
- } else if (!isVNode(newEndVnode)) {
1018
- newEndVnode = newCh[--newEndIdx];
1019
- } else if (sameVnode(oldStartVnode, newStartVnode)) {
1020
- patchVnode(oldStartVnode, newStartVnode);
1021
- oldStartVnode = oldCh[++oldStartIdx];
1022
- newStartVnode = newCh[++newStartIdx];
1023
- } else if (sameVnode(oldEndVnode, newEndVnode)) {
1024
- patchVnode(oldEndVnode, newEndVnode);
1025
- oldEndVnode = oldCh[--oldEndIdx];
1026
- newEndVnode = newCh[--newEndIdx];
1027
- } else if (sameVnode(oldStartVnode, newEndVnode)) {
1028
- // Vnode moved right
1029
- patchVnode(oldStartVnode, newEndVnode);
1030
- newEndVnode.hook.move(oldStartVnode, parentElm, nextSibling(oldEndVnode.elm));
1031
- oldStartVnode = oldCh[++oldStartIdx];
1032
- newEndVnode = newCh[--newEndIdx];
1033
- } else if (sameVnode(oldEndVnode, newStartVnode)) {
1034
- // Vnode moved left
1035
- patchVnode(oldEndVnode, newStartVnode);
1036
- newStartVnode.hook.move(oldEndVnode, parentElm, oldStartVnode.elm);
1037
- oldEndVnode = oldCh[--oldEndIdx];
1038
- newStartVnode = newCh[++newStartIdx];
1039
- } else {
1040
- if (oldKeyToIdx === undefined) {
1041
- oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
1042
- }
1043
-
1044
- idxInOld = oldKeyToIdx[newStartVnode.key];
1045
-
1046
- if (isUndef(idxInOld)) {
1047
- // New element
1048
- newStartVnode.hook.create(newStartVnode);
1049
- newStartVnode.hook.insert(newStartVnode, parentElm, oldStartVnode.elm);
1050
- newStartVnode = newCh[++newStartIdx];
1051
- } else {
1052
- elmToMove = oldCh[idxInOld];
1053
-
1054
- if (isVNode(elmToMove)) {
1055
- if (elmToMove.sel !== newStartVnode.sel) {
1056
- // New element
1057
- newStartVnode.hook.create(newStartVnode);
1058
- newStartVnode.hook.insert(newStartVnode, parentElm, oldStartVnode.elm);
1059
- } else {
1060
- patchVnode(elmToMove, newStartVnode);
1061
- oldCh[idxInOld] = undefined;
1062
- newStartVnode.hook.move(elmToMove, parentElm, oldStartVnode.elm);
1063
- }
1064
- }
1065
-
1066
- newStartVnode = newCh[++newStartIdx];
1067
- }
1068
- }
1069
- }
1070
-
1071
- if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {
1072
- if (oldStartIdx > oldEndIdx) {
1073
- // There's some cases in which the sub array of vnodes to be inserted is followed by null(s) and an
1074
- // already processed vnode, in such cases the vnodes to be inserted should be before that processed vnode.
1075
- let i = newEndIdx;
1076
- let n;
1077
-
1078
- do {
1079
- n = newCh[++i];
1080
- } while (!isVNode(n) && i < newChEnd);
1081
-
1082
- before = isVNode(n) ? n.elm : null;
1083
- addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx);
1084
- } else {
1085
- removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
1086
- }
1087
- }
1088
- }
1089
- function updateStaticChildren(parentElm, oldCh, newCh) {
1090
- const oldChLength = oldCh.length;
1091
- const newChLength = newCh.length;
1092
-
1093
- if (oldChLength === 0) {
1094
- // the old list is empty, we can directly insert anything new
1095
- addVnodes(parentElm, null, newCh, 0, newChLength);
1096
- return;
1097
- }
1098
-
1099
- if (newChLength === 0) {
1100
- // the old list is nonempty and the new list is empty so we can directly remove all old nodes
1101
- // this is the case in which the dynamic children of an if-directive should be removed
1102
- removeVnodes(parentElm, oldCh, 0, oldChLength);
1103
- return;
1104
- } // if the old list is not empty, the new list MUST have the same
1105
- // amount of nodes, that's why we call this static children
1106
-
1107
-
1108
- let referenceElm = null;
1109
-
1110
- for (let i = newChLength - 1; i >= 0; i -= 1) {
1111
- const vnode = newCh[i];
1112
- const oldVNode = oldCh[i];
1113
-
1114
- if (vnode !== oldVNode) {
1115
- if (isVNode(oldVNode)) {
1116
- if (isVNode(vnode)) {
1117
- // both vnodes must be equivalent, and se just need to patch them
1118
- patchVnode(oldVNode, vnode);
1119
- referenceElm = vnode.elm;
1120
- } else {
1121
- // removing the old vnode since the new one is null
1122
- oldVNode.hook.remove(oldVNode, parentElm);
1123
- }
1124
- } else if (isVNode(vnode)) {
1125
- // this condition is unnecessary
1126
- vnode.hook.create(vnode); // insert the new node one since the old one is null
1127
-
1128
- vnode.hook.insert(vnode, parentElm, referenceElm);
1129
- referenceElm = vnode.elm;
1130
- }
1131
- }
1132
- }
1133
- }
1134
-
1135
- function patchVnode(oldVnode, vnode) {
1136
- if (oldVnode !== vnode) {
1137
- vnode.elm = oldVnode.elm;
1138
- vnode.hook.update(oldVnode, vnode);
1139
- }
1140
- }
1141
-
1142
- /*
1143
- * Copyright (c) 2018, salesforce.com, inc.
1144
- * All rights reserved.
1145
- * SPDX-License-Identifier: MIT
1146
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1147
- */
1148
-
1149
- function generateDataDescriptor(options) {
1150
- return shared.assign({
1151
- configurable: true,
1152
- enumerable: true,
1153
- writable: true
1154
- }, options);
1155
- }
1156
-
1157
- function generateAccessorDescriptor(options) {
1158
- return shared.assign({
1159
- configurable: true,
1160
- enumerable: true
1161
- }, options);
1162
- }
1163
-
1164
- let isDomMutationAllowed = false;
1165
- function unlockDomMutation() {
1166
- if (process.env.NODE_ENV === 'production') {
1167
- // this method should never leak to prod
1168
- throw new ReferenceError();
1169
- }
1170
-
1171
- isDomMutationAllowed = true;
1172
- }
1173
- function lockDomMutation() {
1174
- if (process.env.NODE_ENV === 'production') {
1175
- // this method should never leak to prod
1176
- throw new ReferenceError();
1177
- }
1178
-
1179
- isDomMutationAllowed = false;
1180
- }
1181
-
1182
- function logMissingPortalError(name, type) {
1183
- return logError(`The \`${name}\` ${type} is available only on elements that use the \`lwc:dom="manual"\` directive.`);
1184
- }
1185
-
1186
- function patchElementWithRestrictions(elm, options) {
1187
- if (process.env.NODE_ENV === 'production') {
1188
- // this method should never leak to prod
1189
- throw new ReferenceError();
1190
- }
804
+ function patchElementWithRestrictions(elm, options) {
805
+ if (process.env.NODE_ENV === 'production') {
806
+ // this method should never leak to prod
807
+ throw new ReferenceError();
808
+ }
1191
809
 
1192
810
  const originalOuterHTMLDescriptor = shared.getPropertyDescriptor(elm, 'outerHTML');
1193
811
  const descriptors = {
@@ -3707,145 +3325,461 @@ function setActiveVM(vm) {
3707
3325
  throw new ReferenceError();
3708
3326
  }
3709
3327
 
3710
- if (features.runtimeFlags.ENABLE_HMR) {
3711
- // tracking active component
3712
- const Ctor = vm.def.ctor;
3713
- let componentVMs = activeComponents.get(Ctor);
3328
+ if (features.runtimeFlags.ENABLE_HMR) {
3329
+ // tracking active component
3330
+ const Ctor = vm.def.ctor;
3331
+ let componentVMs = activeComponents.get(Ctor);
3332
+
3333
+ if (shared.isUndefined(componentVMs)) {
3334
+ componentVMs = new Set();
3335
+ activeComponents.set(Ctor, componentVMs);
3336
+ } // this will allow us to keep track of the hot components
3337
+
3338
+
3339
+ componentVMs.add(vm); // tracking active template
3340
+
3341
+ const tpl = vm.cmpTemplate;
3342
+
3343
+ if (tpl) {
3344
+ let templateVMs = activeTemplates.get(tpl);
3345
+
3346
+ if (shared.isUndefined(templateVMs)) {
3347
+ templateVMs = new Set();
3348
+ activeTemplates.set(tpl, templateVMs);
3349
+ } // this will allow us to keep track of the templates that are
3350
+ // being used by a hot component
3351
+
3352
+
3353
+ templateVMs.add(vm); // tracking active styles associated to template
3354
+
3355
+ const stylesheets = tpl.stylesheets;
3356
+
3357
+ if (!shared.isUndefined(stylesheets)) {
3358
+ flattenStylesheets(stylesheets).forEach(stylesheet => {
3359
+ // this is necessary because we don't hold the list of styles
3360
+ // in the vm, we only hold the selected (already swapped template)
3361
+ // but the styles attached to the template might not be the actual
3362
+ // active ones, but the swapped versions of those.
3363
+ stylesheet = getStyleOrSwappedStyle(stylesheet);
3364
+ let stylesheetVMs = activeStyles.get(stylesheet);
3365
+
3366
+ if (shared.isUndefined(stylesheetVMs)) {
3367
+ stylesheetVMs = new Set();
3368
+ activeStyles.set(stylesheet, stylesheetVMs);
3369
+ } // this will allow us to keep track of the stylesheet that are
3370
+ // being used by a hot component
3371
+
3372
+
3373
+ stylesheetVMs.add(vm);
3374
+ });
3375
+ }
3376
+ }
3377
+ }
3378
+ }
3379
+ function removeActiveVM(vm) {
3380
+ if (process.env.NODE_ENV === 'production') {
3381
+ // this method should never leak to prod
3382
+ throw new ReferenceError();
3383
+ }
3384
+
3385
+ if (features.runtimeFlags.ENABLE_HMR) {
3386
+ // tracking inactive component
3387
+ const Ctor = vm.def.ctor;
3388
+ let list = activeComponents.get(Ctor);
3389
+
3390
+ if (!shared.isUndefined(list)) {
3391
+ // deleting the vm from the set to avoid leaking memory
3392
+ list.delete(vm);
3393
+ } // removing inactive template
3394
+
3395
+
3396
+ const tpl = vm.cmpTemplate;
3397
+
3398
+ if (tpl) {
3399
+ list = activeTemplates.get(tpl);
3400
+
3401
+ if (!shared.isUndefined(list)) {
3402
+ // deleting the vm from the set to avoid leaking memory
3403
+ list.delete(vm);
3404
+ } // removing active styles associated to template
3405
+
3406
+
3407
+ const styles = tpl.stylesheets;
3408
+
3409
+ if (!shared.isUndefined(styles)) {
3410
+ flattenStylesheets(styles).forEach(style => {
3411
+ list = activeStyles.get(style);
3412
+
3413
+ if (!shared.isUndefined(list)) {
3414
+ // deleting the vm from the set to avoid leaking memory
3415
+ list.delete(vm);
3416
+ }
3417
+ });
3418
+ }
3419
+ }
3420
+ }
3421
+ }
3422
+ function swapTemplate(oldTpl, newTpl) {
3423
+ if (process.env.NODE_ENV !== 'production') {
3424
+ if (isTemplateRegistered(oldTpl) && isTemplateRegistered(newTpl)) {
3425
+ swappedTemplateMap.set(oldTpl, newTpl);
3426
+ return rehydrateHotTemplate(oldTpl);
3427
+ } else {
3428
+ throw new TypeError(`Invalid Template`);
3429
+ }
3430
+ }
3431
+
3432
+ if (!features.runtimeFlags.ENABLE_HMR) {
3433
+ throw new Error('HMR is not enabled');
3434
+ }
3435
+
3436
+ return false;
3437
+ }
3438
+ function swapComponent(oldComponent, newComponent) {
3439
+ if (process.env.NODE_ENV !== 'production') {
3440
+ if (isComponentConstructor(oldComponent) && isComponentConstructor(newComponent)) {
3441
+ swappedComponentMap.set(oldComponent, newComponent);
3442
+ return rehydrateHotComponent(oldComponent);
3443
+ } else {
3444
+ throw new TypeError(`Invalid Component`);
3445
+ }
3446
+ }
3447
+
3448
+ if (!features.runtimeFlags.ENABLE_HMR) {
3449
+ throw new Error('HMR is not enabled');
3450
+ }
3451
+
3452
+ return false;
3453
+ }
3454
+ function swapStyle(oldStyle, newStyle) {
3455
+ if (process.env.NODE_ENV !== 'production') {
3456
+ // TODO [#1887]: once the support for registering styles is implemented
3457
+ // we can add the validation of both styles around this block.
3458
+ swappedStyleMap.set(oldStyle, newStyle);
3459
+ return rehydrateHotStyle(oldStyle);
3460
+ }
3461
+
3462
+ if (!features.runtimeFlags.ENABLE_HMR) {
3463
+ throw new Error('HMR is not enabled');
3464
+ }
3465
+
3466
+ return false;
3467
+ }
3468
+
3469
+ /*
3470
+ * Copyright (c) 2018, salesforce.com, inc.
3471
+ * All rights reserved.
3472
+ * SPDX-License-Identifier: MIT
3473
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3474
+ */
3475
+ const CtorToDefMap = new WeakMap();
3476
+
3477
+ function getCtorProto(Ctor) {
3478
+ let proto = shared.getPrototypeOf(Ctor);
3479
+
3480
+ if (shared.isNull(proto)) {
3481
+ throw new ReferenceError(`Invalid prototype chain for ${Ctor.name}, you must extend LightningElement.`);
3482
+ } // covering the cases where the ref is circular in AMD
3483
+
3484
+
3485
+ if (isCircularModuleDependency(proto)) {
3486
+ const p = resolveCircularModuleDependency(proto);
3487
+
3488
+ if (process.env.NODE_ENV !== 'production') {
3489
+ if (shared.isNull(p)) {
3490
+ throw new ReferenceError(`Circular module dependency for ${Ctor.name}, must resolve to a constructor that extends LightningElement.`);
3491
+ }
3492
+ } // escape hatch for Locker and other abstractions to provide their own base class instead
3493
+ // of our Base class without having to leak it to user-land. If the circular function returns
3494
+ // itself, that's the signal that we have hit the end of the proto chain, which must always
3495
+ // be base.
3496
+
3497
+
3498
+ proto = p === proto ? LightningElement : p;
3499
+ }
3500
+
3501
+ return proto;
3502
+ }
3503
+
3504
+ function createComponentDef(Ctor) {
3505
+ const {
3506
+ shadowSupportMode: ctorShadowSupportMode,
3507
+ renderMode: ctorRenderMode
3508
+ } = Ctor;
3509
+
3510
+ if (process.env.NODE_ENV !== 'production') {
3511
+ const ctorName = Ctor.name; // Removing the following assert until https://bugs.webkit.org/show_bug.cgi?id=190140 is fixed.
3512
+ // assert.isTrue(ctorName && isString(ctorName), `${toString(Ctor)} should have a "name" property with string value, but found ${ctorName}.`);
3513
+
3514
+ shared.assert.isTrue(Ctor.constructor, `Missing ${ctorName}.constructor, ${ctorName} should have a "constructor" property.`);
3515
+
3516
+ if (!shared.isUndefined(ctorShadowSupportMode)) {
3517
+ shared.assert.invariant(ctorShadowSupportMode === "any"
3518
+ /* Any */
3519
+ || ctorShadowSupportMode === "reset"
3520
+ /* Default */
3521
+ , `Invalid value for static property shadowSupportMode: '${ctorShadowSupportMode}'`);
3522
+ }
3523
+
3524
+ if (!shared.isUndefined(ctorRenderMode)) {
3525
+ shared.assert.invariant(ctorRenderMode === 'light' || ctorRenderMode === 'shadow', `Invalid value for static property renderMode: '${ctorRenderMode}'. renderMode must be either 'light' or 'shadow'.`);
3526
+ }
3527
+ }
3528
+
3529
+ const decoratorsMeta = getDecoratorsMeta(Ctor);
3530
+ const {
3531
+ apiFields,
3532
+ apiFieldsConfig,
3533
+ apiMethods,
3534
+ wiredFields,
3535
+ wiredMethods,
3536
+ observedFields
3537
+ } = decoratorsMeta;
3538
+ const proto = Ctor.prototype;
3539
+ let {
3540
+ connectedCallback,
3541
+ disconnectedCallback,
3542
+ renderedCallback,
3543
+ errorCallback,
3544
+ render
3545
+ } = proto;
3546
+ const superProto = getCtorProto(Ctor);
3547
+ const superDef = superProto !== LightningElement ? getComponentInternalDef(superProto) : lightingElementDef;
3548
+ const bridge = HTMLBridgeElementFactory(superDef.bridge, shared.keys(apiFields), shared.keys(apiMethods));
3549
+ const props = shared.assign(shared.create(null), superDef.props, apiFields);
3550
+ const propsConfig = shared.assign(shared.create(null), superDef.propsConfig, apiFieldsConfig);
3551
+ const methods = shared.assign(shared.create(null), superDef.methods, apiMethods);
3552
+ const wire = shared.assign(shared.create(null), superDef.wire, wiredFields, wiredMethods);
3553
+ connectedCallback = connectedCallback || superDef.connectedCallback;
3554
+ disconnectedCallback = disconnectedCallback || superDef.disconnectedCallback;
3555
+ renderedCallback = renderedCallback || superDef.renderedCallback;
3556
+ errorCallback = errorCallback || superDef.errorCallback;
3557
+ render = render || superDef.render;
3558
+ let shadowSupportMode = superDef.shadowSupportMode;
3559
+
3560
+ if (!shared.isUndefined(ctorShadowSupportMode)) {
3561
+ shadowSupportMode = ctorShadowSupportMode;
3562
+ }
3563
+
3564
+ let renderMode = superDef.renderMode;
3714
3565
 
3715
- if (shared.isUndefined(componentVMs)) {
3716
- componentVMs = new Set();
3717
- activeComponents.set(Ctor, componentVMs);
3718
- } // this will allow us to keep track of the hot components
3566
+ if (!shared.isUndefined(ctorRenderMode)) {
3567
+ renderMode = ctorRenderMode === 'light' ? 0
3568
+ /* Light */
3569
+ : 1
3570
+ /* Shadow */
3571
+ ;
3572
+ }
3719
3573
 
3574
+ const template = getComponentRegisteredTemplate(Ctor) || superDef.template;
3575
+ const name = Ctor.name || superDef.name; // installing observed fields into the prototype.
3720
3576
 
3721
- componentVMs.add(vm); // tracking active template
3577
+ shared.defineProperties(proto, observedFields);
3578
+ const def = {
3579
+ ctor: Ctor,
3580
+ name,
3581
+ wire,
3582
+ props,
3583
+ propsConfig,
3584
+ methods,
3585
+ bridge,
3586
+ template,
3587
+ renderMode,
3588
+ shadowSupportMode,
3589
+ connectedCallback,
3590
+ disconnectedCallback,
3591
+ renderedCallback,
3592
+ errorCallback,
3593
+ render
3594
+ };
3722
3595
 
3723
- const tpl = vm.cmpTemplate;
3596
+ if (process.env.NODE_ENV !== 'production') {
3597
+ shared.freeze(Ctor.prototype);
3598
+ }
3724
3599
 
3725
- if (tpl) {
3726
- let templateVMs = activeTemplates.get(tpl);
3600
+ return def;
3601
+ }
3602
+ /**
3603
+ * EXPERIMENTAL: This function allows for the identification of LWC constructors. This API is
3604
+ * subject to change or being removed.
3605
+ */
3727
3606
 
3728
- if (shared.isUndefined(templateVMs)) {
3729
- templateVMs = new Set();
3730
- activeTemplates.set(tpl, templateVMs);
3731
- } // this will allow us to keep track of the templates that are
3732
- // being used by a hot component
3733
3607
 
3608
+ function isComponentConstructor(ctor) {
3609
+ if (!shared.isFunction(ctor)) {
3610
+ return false;
3611
+ } // Fast path: LightningElement is part of the prototype chain of the constructor.
3734
3612
 
3735
- templateVMs.add(vm); // tracking active styles associated to template
3736
3613
 
3737
- const stylesheets = tpl.stylesheets;
3614
+ if (ctor.prototype instanceof LightningElement) {
3615
+ return true;
3616
+ } // Slow path: LightningElement is not part of the prototype chain of the constructor, we need
3617
+ // climb up the constructor prototype chain to check in case there are circular dependencies
3618
+ // to resolve.
3738
3619
 
3739
- if (!shared.isUndefined(stylesheets)) {
3740
- flattenStylesheets(stylesheets).forEach(stylesheet => {
3741
- // this is necessary because we don't hold the list of styles
3742
- // in the vm, we only hold the selected (already swapped template)
3743
- // but the styles attached to the template might not be the actual
3744
- // active ones, but the swapped versions of those.
3745
- stylesheet = getStyleOrSwappedStyle(stylesheet);
3746
- let stylesheetVMs = activeStyles.get(stylesheet);
3747
3620
 
3748
- if (shared.isUndefined(stylesheetVMs)) {
3749
- stylesheetVMs = new Set();
3750
- activeStyles.set(stylesheet, stylesheetVMs);
3751
- } // this will allow us to keep track of the stylesheet that are
3752
- // being used by a hot component
3621
+ let current = ctor;
3753
3622
 
3623
+ do {
3624
+ if (isCircularModuleDependency(current)) {
3625
+ const circularResolved = resolveCircularModuleDependency(current); // If the circular function returns itself, that's the signal that we have hit the end
3626
+ // of the proto chain, which must always be a valid base constructor.
3754
3627
 
3755
- stylesheetVMs.add(vm);
3756
- });
3628
+ if (circularResolved === current) {
3629
+ return true;
3757
3630
  }
3631
+
3632
+ current = circularResolved;
3758
3633
  }
3759
- }
3634
+
3635
+ if (current === LightningElement) {
3636
+ return true;
3637
+ }
3638
+ } while (!shared.isNull(current) && (current = shared.getPrototypeOf(current))); // Finally return false if the LightningElement is not part of the prototype chain.
3639
+
3640
+
3641
+ return false;
3760
3642
  }
3761
- function removeActiveVM(vm) {
3762
- if (process.env.NODE_ENV === 'production') {
3763
- // this method should never leak to prod
3764
- throw new ReferenceError();
3643
+ function getComponentInternalDef(Ctor) {
3644
+ if (process.env.NODE_ENV !== 'production') {
3645
+ Ctor = getComponentOrSwappedComponent(Ctor);
3765
3646
  }
3766
3647
 
3767
- if (features.runtimeFlags.ENABLE_HMR) {
3768
- // tracking inactive component
3769
- const Ctor = vm.def.ctor;
3770
- let list = activeComponents.get(Ctor);
3771
-
3772
- if (!shared.isUndefined(list)) {
3773
- // deleting the vm from the set to avoid leaking memory
3774
- list.delete(vm);
3775
- } // removing inactive template
3648
+ let def = CtorToDefMap.get(Ctor);
3776
3649
 
3650
+ if (shared.isUndefined(def)) {
3651
+ if (isCircularModuleDependency(Ctor)) {
3652
+ const resolvedCtor = resolveCircularModuleDependency(Ctor);
3653
+ def = getComponentInternalDef(resolvedCtor); // Cache the unresolved component ctor too. The next time if the same unresolved ctor is used,
3654
+ // look up the definition in cache instead of re-resolving and recreating the def.
3777
3655
 
3778
- const tpl = vm.cmpTemplate;
3656
+ CtorToDefMap.set(Ctor, def);
3657
+ return def;
3658
+ }
3779
3659
 
3780
- if (tpl) {
3781
- list = activeTemplates.get(tpl);
3660
+ if (!isComponentConstructor(Ctor)) {
3661
+ throw new TypeError(`${Ctor} is not a valid component, or does not extends LightningElement from "lwc". You probably forgot to add the extend clause on the class declaration.`);
3662
+ }
3782
3663
 
3783
- if (!shared.isUndefined(list)) {
3784
- // deleting the vm from the set to avoid leaking memory
3785
- list.delete(vm);
3786
- } // removing active styles associated to template
3664
+ def = createComponentDef(Ctor);
3665
+ CtorToDefMap.set(Ctor, def);
3666
+ }
3787
3667
 
3668
+ return def;
3669
+ }
3670
+ const lightingElementDef = {
3671
+ ctor: LightningElement,
3672
+ name: LightningElement.name,
3673
+ props: lightningBasedDescriptors,
3674
+ propsConfig: EmptyObject,
3675
+ methods: EmptyObject,
3676
+ renderMode: 1
3677
+ /* Shadow */
3678
+ ,
3679
+ shadowSupportMode: "reset"
3680
+ /* Default */
3681
+ ,
3682
+ wire: EmptyObject,
3683
+ bridge: BaseBridgeElement,
3684
+ template: defaultEmptyTemplate,
3685
+ render: LightningElement.prototype.render
3686
+ };
3687
+ /**
3688
+ * EXPERIMENTAL: This function allows for the collection of internal component metadata. This API is
3689
+ * subject to change or being removed.
3690
+ */
3788
3691
 
3789
- const styles = tpl.stylesheets;
3692
+ function getComponentDef(Ctor) {
3693
+ const def = getComponentInternalDef(Ctor); // From the internal def object, we need to extract the info that is useful
3694
+ // for some external services, e.g.: Locker Service, usually, all they care
3695
+ // is about the shape of the constructor, the internals of it are not relevant
3696
+ // because they don't have a way to mess with that.
3790
3697
 
3791
- if (!shared.isUndefined(styles)) {
3792
- flattenStylesheets(styles).forEach(style => {
3793
- list = activeStyles.get(style);
3698
+ const {
3699
+ ctor,
3700
+ name,
3701
+ props,
3702
+ propsConfig,
3703
+ methods
3704
+ } = def;
3705
+ const publicProps = {};
3794
3706
 
3795
- if (!shared.isUndefined(list)) {
3796
- // deleting the vm from the set to avoid leaking memory
3797
- list.delete(vm);
3798
- }
3799
- });
3800
- }
3801
- }
3802
- }
3803
- }
3804
- function swapTemplate(oldTpl, newTpl) {
3805
- if (process.env.NODE_ENV !== 'production') {
3806
- if (isTemplateRegistered(oldTpl) && isTemplateRegistered(newTpl)) {
3807
- swappedTemplateMap.set(oldTpl, newTpl);
3808
- return rehydrateHotTemplate(oldTpl);
3809
- } else {
3810
- throw new TypeError(`Invalid Template`);
3811
- }
3707
+ for (const key in props) {
3708
+ // avoid leaking the reference to the public props descriptors
3709
+ publicProps[key] = {
3710
+ config: propsConfig[key] || 0,
3711
+ type: "any"
3712
+ /* any */
3713
+ ,
3714
+ attr: shared.htmlPropertyToAttribute(key)
3715
+ };
3812
3716
  }
3813
3717
 
3814
- if (!features.runtimeFlags.ENABLE_HMR) {
3815
- throw new Error('HMR is not enabled');
3718
+ const publicMethods = {};
3719
+
3720
+ for (const key in methods) {
3721
+ // avoid leaking the reference to the public method descriptors
3722
+ publicMethods[key] = methods[key].value;
3816
3723
  }
3817
3724
 
3818
- return false;
3725
+ return {
3726
+ ctor,
3727
+ name,
3728
+ props: publicProps,
3729
+ methods: publicMethods
3730
+ };
3819
3731
  }
3820
- function swapComponent(oldComponent, newComponent) {
3821
- if (process.env.NODE_ENV !== 'production') {
3822
- if (isComponentConstructor(oldComponent) && isComponentConstructor(newComponent)) {
3823
- swappedComponentMap.set(oldComponent, newComponent);
3824
- return rehydrateHotComponent(oldComponent);
3825
- } else {
3826
- throw new TypeError(`Invalid Component`);
3827
- }
3828
- }
3829
3732
 
3830
- if (!features.runtimeFlags.ENABLE_HMR) {
3831
- throw new Error('HMR is not enabled');
3733
+ /*
3734
+ * Copyright (c) 2018, salesforce.com, inc.
3735
+ * All rights reserved.
3736
+ * SPDX-License-Identifier: MIT
3737
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3738
+ */
3739
+ const xlinkNS = 'http://www.w3.org/1999/xlink';
3740
+ const xmlNS = 'http://www.w3.org/XML/1998/namespace';
3741
+ const ColonCharCode = 58;
3742
+ function patchAttributes(oldVnode, vnode) {
3743
+ const {
3744
+ attrs
3745
+ } = vnode.data;
3746
+
3747
+ if (shared.isUndefined(attrs)) {
3748
+ return;
3832
3749
  }
3833
3750
 
3834
- return false;
3835
- }
3836
- function swapStyle(oldStyle, newStyle) {
3837
- if (process.env.NODE_ENV !== 'production') {
3838
- // TODO [#1887]: once the support for registering styles is implemented
3839
- // we can add the validation of both styles around this block.
3840
- swappedStyleMap.set(oldStyle, newStyle);
3841
- return rehydrateHotStyle(oldStyle);
3751
+ const oldAttrs = shared.isNull(oldVnode) ? EmptyObject : oldVnode.data.attrs;
3752
+
3753
+ if (oldAttrs === attrs) {
3754
+ return;
3842
3755
  }
3843
3756
 
3844
- if (!features.runtimeFlags.ENABLE_HMR) {
3845
- throw new Error('HMR is not enabled');
3846
- }
3757
+ const {
3758
+ elm
3759
+ } = vnode;
3760
+
3761
+ for (const key in attrs) {
3762
+ const cur = attrs[key];
3763
+ const old = oldAttrs[key];
3764
+
3765
+ if (old !== cur) {
3766
+ unlockAttribute(elm, key);
3847
3767
 
3848
- return false;
3768
+ if (shared.StringCharCodeAt.call(key, 3) === ColonCharCode) {
3769
+ // Assume xml namespace
3770
+ setAttribute(elm, key, cur, xmlNS);
3771
+ } else if (shared.StringCharCodeAt.call(key, 5) === ColonCharCode) {
3772
+ // Assume xlink namespace
3773
+ setAttribute(elm, key, cur, xlinkNS);
3774
+ } else if (shared.isNull(cur) || shared.isUndefined(cur)) {
3775
+ removeAttribute(elm, key);
3776
+ } else {
3777
+ setAttribute(elm, key, cur);
3778
+ }
3779
+
3780
+ lockAttribute();
3781
+ }
3782
+ }
3849
3783
  }
3850
3784
 
3851
3785
  /*
@@ -3854,262 +3788,231 @@ function swapStyle(oldStyle, newStyle) {
3854
3788
  * SPDX-License-Identifier: MIT
3855
3789
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3856
3790
  */
3857
- const CtorToDefMap = new WeakMap();
3858
3791
 
3859
- function getCtorProto(Ctor) {
3860
- let proto = shared.getPrototypeOf(Ctor);
3792
+ function isLiveBindingProp(sel, key) {
3793
+ // For properties with live bindings, we read values from the DOM element
3794
+ // instead of relying on internally tracked values.
3795
+ return sel === 'input' && (key === 'value' || key === 'checked');
3796
+ }
3861
3797
 
3862
- if (shared.isNull(proto)) {
3863
- throw new ReferenceError(`Invalid prototype chain for ${Ctor.name}, you must extend LightningElement.`);
3864
- } // covering the cases where the ref is circular in AMD
3798
+ function patchProps(oldVnode, vnode) {
3799
+ const {
3800
+ props
3801
+ } = vnode.data;
3865
3802
 
3803
+ if (shared.isUndefined(props)) {
3804
+ return;
3805
+ }
3866
3806
 
3867
- if (isCircularModuleDependency(proto)) {
3868
- const p = resolveCircularModuleDependency(proto);
3807
+ const oldProps = shared.isNull(oldVnode) ? EmptyObject : oldVnode.data.props;
3869
3808
 
3870
- if (process.env.NODE_ENV !== 'production') {
3871
- if (shared.isNull(p)) {
3872
- throw new ReferenceError(`Circular module dependency for ${Ctor.name}, must resolve to a constructor that extends LightningElement.`);
3873
- }
3874
- } // escape hatch for Locker and other abstractions to provide their own base class instead
3875
- // of our Base class without having to leak it to user-land. If the circular function returns
3876
- // itself, that's the signal that we have hit the end of the proto chain, which must always
3877
- // be base.
3809
+ if (oldProps === props) {
3810
+ return;
3811
+ }
3878
3812
 
3813
+ const isFirstPatch = shared.isNull(oldVnode);
3814
+ const {
3815
+ elm,
3816
+ sel
3817
+ } = vnode;
3879
3818
 
3880
- proto = p === proto ? LightningElement : p;
3881
- }
3819
+ for (const key in props) {
3820
+ const cur = props[key]; // Set the property if it's the first time is is patched or if the previous property is
3821
+ // different than the one previously set.
3882
3822
 
3883
- return proto;
3823
+ if (isFirstPatch || cur !== (isLiveBindingProp(sel, key) ? getProperty(elm, key) : oldProps[key])) {
3824
+ setProperty(elm, key, cur);
3825
+ }
3826
+ }
3884
3827
  }
3885
3828
 
3886
- function createComponentDef(Ctor) {
3887
- const {
3888
- shadowSupportMode: ctorShadowSupportMode,
3889
- renderMode: ctorRenderMode
3890
- } = Ctor;
3829
+ /*
3830
+ * Copyright (c) 2018, salesforce.com, inc.
3831
+ * All rights reserved.
3832
+ * SPDX-License-Identifier: MIT
3833
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3834
+ */
3835
+ const classNameToClassMap = shared.create(null);
3891
3836
 
3892
- if (process.env.NODE_ENV !== 'production') {
3893
- const ctorName = Ctor.name; // Removing the following assert until https://bugs.webkit.org/show_bug.cgi?id=190140 is fixed.
3894
- // assert.isTrue(ctorName && isString(ctorName), `${toString(Ctor)} should have a "name" property with string value, but found ${ctorName}.`);
3837
+ function getMapFromClassName(className) {
3838
+ // Intentionally using == to match undefined and null values from computed style attribute
3839
+ if (className == null) {
3840
+ return EmptyObject;
3841
+ } // computed class names must be string
3895
3842
 
3896
- shared.assert.isTrue(Ctor.constructor, `Missing ${ctorName}.constructor, ${ctorName} should have a "constructor" property.`);
3897
3843
 
3898
- if (!shared.isUndefined(ctorShadowSupportMode)) {
3899
- shared.assert.invariant(ctorShadowSupportMode === "any"
3900
- /* Any */
3901
- || ctorShadowSupportMode === "reset"
3902
- /* Default */
3903
- , `Invalid value for static property shadowSupportMode: '${ctorShadowSupportMode}'`);
3904
- }
3844
+ className = shared.isString(className) ? className : className + '';
3845
+ let map = classNameToClassMap[className];
3905
3846
 
3906
- if (!shared.isUndefined(ctorRenderMode)) {
3907
- shared.assert.invariant(ctorRenderMode === 'light' || ctorRenderMode === 'shadow', `Invalid value for static property renderMode: '${ctorRenderMode}'. renderMode must be either 'light' or 'shadow'.`);
3908
- }
3847
+ if (map) {
3848
+ return map;
3909
3849
  }
3910
3850
 
3911
- const decoratorsMeta = getDecoratorsMeta(Ctor);
3912
- const {
3913
- apiFields,
3914
- apiFieldsConfig,
3915
- apiMethods,
3916
- wiredFields,
3917
- wiredMethods,
3918
- observedFields
3919
- } = decoratorsMeta;
3920
- const proto = Ctor.prototype;
3921
- let {
3922
- connectedCallback,
3923
- disconnectedCallback,
3924
- renderedCallback,
3925
- errorCallback,
3926
- render
3927
- } = proto;
3928
- const superProto = getCtorProto(Ctor);
3929
- const superDef = superProto !== LightningElement ? getComponentInternalDef(superProto) : lightingElementDef;
3930
- const bridge = HTMLBridgeElementFactory(superDef.bridge, shared.keys(apiFields), shared.keys(apiMethods));
3931
- const props = shared.assign(shared.create(null), superDef.props, apiFields);
3932
- const propsConfig = shared.assign(shared.create(null), superDef.propsConfig, apiFieldsConfig);
3933
- const methods = shared.assign(shared.create(null), superDef.methods, apiMethods);
3934
- const wire = shared.assign(shared.create(null), superDef.wire, wiredFields, wiredMethods);
3935
- connectedCallback = connectedCallback || superDef.connectedCallback;
3936
- disconnectedCallback = disconnectedCallback || superDef.disconnectedCallback;
3937
- renderedCallback = renderedCallback || superDef.renderedCallback;
3938
- errorCallback = errorCallback || superDef.errorCallback;
3939
- render = render || superDef.render;
3940
- let shadowSupportMode = superDef.shadowSupportMode;
3941
-
3942
- if (!shared.isUndefined(ctorShadowSupportMode)) {
3943
- shadowSupportMode = ctorShadowSupportMode;
3944
- }
3851
+ map = shared.create(null);
3852
+ let start = 0;
3853
+ let o;
3854
+ const len = className.length;
3945
3855
 
3946
- let renderMode = superDef.renderMode;
3856
+ for (o = 0; o < len; o++) {
3857
+ if (shared.StringCharCodeAt.call(className, o) === SPACE_CHAR) {
3858
+ if (o > start) {
3859
+ map[shared.StringSlice.call(className, start, o)] = true;
3860
+ }
3947
3861
 
3948
- if (!shared.isUndefined(ctorRenderMode)) {
3949
- renderMode = ctorRenderMode === 'light' ? 0
3950
- /* Light */
3951
- : 1
3952
- /* Shadow */
3953
- ;
3862
+ start = o + 1;
3863
+ }
3954
3864
  }
3955
3865
 
3956
- const template = getComponentRegisteredTemplate(Ctor) || superDef.template;
3957
- const name = Ctor.name || superDef.name; // installing observed fields into the prototype.
3866
+ if (o > start) {
3867
+ map[shared.StringSlice.call(className, start, o)] = true;
3868
+ }
3958
3869
 
3959
- shared.defineProperties(proto, observedFields);
3960
- const def = {
3961
- ctor: Ctor,
3962
- name,
3963
- wire,
3964
- props,
3965
- propsConfig,
3966
- methods,
3967
- bridge,
3968
- template,
3969
- renderMode,
3970
- shadowSupportMode,
3971
- connectedCallback,
3972
- disconnectedCallback,
3973
- renderedCallback,
3974
- errorCallback,
3975
- render
3976
- };
3870
+ classNameToClassMap[className] = map;
3977
3871
 
3978
3872
  if (process.env.NODE_ENV !== 'production') {
3979
- shared.freeze(Ctor.prototype);
3873
+ // just to make sure that this object never changes as part of the diffing algo
3874
+ shared.freeze(map);
3980
3875
  }
3981
3876
 
3982
- return def;
3877
+ return map;
3983
3878
  }
3984
- /**
3985
- * EXPERIMENTAL: This function allows for the identification of LWC constructors. This API is
3986
- * subject to change or being removed.
3987
- */
3988
3879
 
3880
+ function patchClassAttribute(oldVnode, vnode) {
3881
+ const {
3882
+ elm,
3883
+ data: {
3884
+ className: newClass
3885
+ }
3886
+ } = vnode;
3887
+ const oldClass = shared.isNull(oldVnode) ? undefined : oldVnode.data.className;
3989
3888
 
3990
- function isComponentConstructor(ctor) {
3991
- if (!shared.isFunction(ctor)) {
3992
- return false;
3993
- } // Fast path: LightningElement is part of the prototype chain of the constructor.
3889
+ if (oldClass === newClass) {
3890
+ return;
3891
+ }
3994
3892
 
3893
+ const classList = getClassList(elm);
3894
+ const newClassMap = getMapFromClassName(newClass);
3895
+ const oldClassMap = getMapFromClassName(oldClass);
3896
+ let name;
3995
3897
 
3996
- if (ctor.prototype instanceof LightningElement) {
3997
- return true;
3998
- } // Slow path: LightningElement is not part of the prototype chain of the constructor, we need
3999
- // climb up the constructor prototype chain to check in case there are circular dependencies
4000
- // to resolve.
3898
+ for (name in oldClassMap) {
3899
+ // remove only if it is not in the new class collection and it is not set from within the instance
3900
+ if (shared.isUndefined(newClassMap[name])) {
3901
+ classList.remove(name);
3902
+ }
3903
+ }
4001
3904
 
3905
+ for (name in newClassMap) {
3906
+ if (shared.isUndefined(oldClassMap[name])) {
3907
+ classList.add(name);
3908
+ }
3909
+ }
3910
+ }
4002
3911
 
4003
- let current = ctor;
3912
+ /*
3913
+ * Copyright (c) 2018, salesforce.com, inc.
3914
+ * All rights reserved.
3915
+ * SPDX-License-Identifier: MIT
3916
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3917
+ */
4004
3918
 
4005
- do {
4006
- if (isCircularModuleDependency(current)) {
4007
- const circularResolved = resolveCircularModuleDependency(current); // If the circular function returns itself, that's the signal that we have hit the end
4008
- // of the proto chain, which must always be a valid base constructor.
3919
+ function patchStyleAttribute(oldVnode, vnode) {
3920
+ const {
3921
+ elm,
3922
+ data: {
3923
+ style: newStyle
3924
+ }
3925
+ } = vnode;
3926
+ const oldStyle = shared.isNull(oldVnode) ? undefined : oldVnode.data.style;
4009
3927
 
4010
- if (circularResolved === current) {
4011
- return true;
4012
- }
3928
+ if (oldStyle === newStyle) {
3929
+ return;
3930
+ }
4013
3931
 
4014
- current = circularResolved;
4015
- }
3932
+ if (!shared.isString(newStyle) || newStyle === '') {
3933
+ removeAttribute(elm, 'style');
3934
+ } else {
3935
+ setAttribute(elm, 'style', newStyle);
3936
+ }
3937
+ }
4016
3938
 
4017
- if (current === LightningElement) {
4018
- return true;
3939
+ /*
3940
+ * Copyright (c) 2018, salesforce.com, inc.
3941
+ * All rights reserved.
3942
+ * SPDX-License-Identifier: MIT
3943
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3944
+ */
3945
+ function applyEventListeners(vnode) {
3946
+ const {
3947
+ elm,
3948
+ data: {
3949
+ on
4019
3950
  }
4020
- } while (!shared.isNull(current) && (current = shared.getPrototypeOf(current))); // Finally return false if the LightningElement is not part of the prototype chain.
4021
-
3951
+ } = vnode;
4022
3952
 
4023
- return false;
4024
- }
4025
- function getComponentInternalDef(Ctor) {
4026
- if (process.env.NODE_ENV !== 'production') {
4027
- Ctor = getComponentOrSwappedComponent(Ctor);
3953
+ if (shared.isUndefined(on)) {
3954
+ return;
4028
3955
  }
4029
3956
 
4030
- let def = CtorToDefMap.get(Ctor);
4031
-
4032
- if (shared.isUndefined(def)) {
4033
- if (isCircularModuleDependency(Ctor)) {
4034
- const resolvedCtor = resolveCircularModuleDependency(Ctor);
4035
- def = getComponentInternalDef(resolvedCtor); // Cache the unresolved component ctor too. The next time if the same unresolved ctor is used,
4036
- // look up the definition in cache instead of re-resolving and recreating the def.
3957
+ for (const name in on) {
3958
+ const handler = on[name];
3959
+ addEventListener(elm, name, handler);
3960
+ }
3961
+ }
4037
3962
 
4038
- CtorToDefMap.set(Ctor, def);
4039
- return def;
4040
- }
3963
+ /*
3964
+ * Copyright (c) 2018, salesforce.com, inc.
3965
+ * All rights reserved.
3966
+ * SPDX-License-Identifier: MIT
3967
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3968
+ */
3969
+ // The compiler takes care of transforming the inline classnames into an object. It's faster to set the
3970
+ // different classnames properties individually instead of via a string.
4041
3971
 
4042
- if (!isComponentConstructor(Ctor)) {
4043
- throw new TypeError(`${Ctor} is not a valid component, or does not extends LightningElement from "lwc". You probably forgot to add the extend clause on the class declaration.`);
3972
+ function applyStaticClassAttribute(vnode) {
3973
+ const {
3974
+ elm,
3975
+ data: {
3976
+ classMap
4044
3977
  }
3978
+ } = vnode;
4045
3979
 
4046
- def = createComponentDef(Ctor);
4047
- CtorToDefMap.set(Ctor, def);
3980
+ if (shared.isUndefined(classMap)) {
3981
+ return;
4048
3982
  }
4049
3983
 
4050
- return def;
3984
+ const classList = getClassList(elm);
3985
+
3986
+ for (const name in classMap) {
3987
+ classList.add(name);
3988
+ }
4051
3989
  }
4052
- const lightingElementDef = {
4053
- ctor: LightningElement,
4054
- name: LightningElement.name,
4055
- props: lightningBasedDescriptors,
4056
- propsConfig: EmptyObject,
4057
- methods: EmptyObject,
4058
- renderMode: 1
4059
- /* Shadow */
4060
- ,
4061
- shadowSupportMode: "reset"
4062
- /* Default */
4063
- ,
4064
- wire: EmptyObject,
4065
- bridge: BaseBridgeElement,
4066
- template: defaultEmptyTemplate,
4067
- render: LightningElement.prototype.render
4068
- };
4069
- /**
4070
- * EXPERIMENTAL: This function allows for the collection of internal component metadata. This API is
4071
- * subject to change or being removed.
4072
- */
4073
3990
 
4074
- function getComponentDef(Ctor) {
4075
- const def = getComponentInternalDef(Ctor); // From the internal def object, we need to extract the info that is useful
4076
- // for some external services, e.g.: Locker Service, usually, all they care
4077
- // is about the shape of the constructor, the internals of it are not relevant
4078
- // because they don't have a way to mess with that.
3991
+ /*
3992
+ * Copyright (c) 2018, salesforce.com, inc.
3993
+ * All rights reserved.
3994
+ * SPDX-License-Identifier: MIT
3995
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3996
+ */
3997
+ // The compiler takes care of transforming the inline style into an object. It's faster to set the
3998
+ // different style properties individually instead of via a string.
4079
3999
 
4000
+ function applyStaticStyleAttribute(vnode) {
4080
4001
  const {
4081
- ctor,
4082
- name,
4083
- props,
4084
- propsConfig,
4085
- methods
4086
- } = def;
4087
- const publicProps = {};
4002
+ elm,
4003
+ data: {
4004
+ styleDecls
4005
+ }
4006
+ } = vnode;
4088
4007
 
4089
- for (const key in props) {
4090
- // avoid leaking the reference to the public props descriptors
4091
- publicProps[key] = {
4092
- config: propsConfig[key] || 0,
4093
- type: "any"
4094
- /* any */
4095
- ,
4096
- attr: shared.htmlPropertyToAttribute(key)
4097
- };
4008
+ if (shared.isUndefined(styleDecls)) {
4009
+ return;
4098
4010
  }
4099
4011
 
4100
- const publicMethods = {};
4101
-
4102
- for (const key in methods) {
4103
- // avoid leaking the reference to the public method descriptors
4104
- publicMethods[key] = methods[key].value;
4012
+ for (let i = 0; i < styleDecls.length; i++) {
4013
+ const [prop, value, important] = styleDecls[i];
4014
+ setCSSStyleProperty(elm, prop, value, important);
4105
4015
  }
4106
-
4107
- return {
4108
- ctor,
4109
- name,
4110
- props: publicProps,
4111
- methods: publicMethods
4112
- };
4113
4016
  }
4114
4017
 
4115
4018
  /*
@@ -4180,27 +4083,23 @@ function removeNodeHook(vnode, parentNode) {
4180
4083
  lockDomMutation();
4181
4084
  }
4182
4085
  }
4183
- function createElmHook(vnode) {
4184
- modEvents.create(vnode); // Attrs need to be applied to element before props
4185
- // IE11 will wipe out value on radio inputs if value
4186
- // is set before type=radio.
4086
+ function patchElementPropsAndAttrs(oldVnode, vnode) {
4087
+ if (shared.isNull(oldVnode)) {
4088
+ applyEventListeners(vnode);
4089
+ applyStaticClassAttribute(vnode);
4090
+ applyStaticStyleAttribute(vnode);
4091
+ } // Attrs need to be applied to element before props IE11 will wipe out value on radio inputs if
4092
+ // value is set before type=radio.
4187
4093
 
4188
- modAttrs.create(vnode);
4189
- modProps.create(vnode);
4190
- modStaticClassName.create(vnode);
4191
- modStaticStyle.create(vnode);
4192
- modComputedClassName.create(vnode);
4193
- modComputedStyle.create(vnode);
4094
+
4095
+ patchClassAttribute(oldVnode, vnode);
4096
+ patchStyleAttribute(oldVnode, vnode);
4097
+ patchAttributes(oldVnode, vnode);
4098
+ patchProps(oldVnode, vnode);
4194
4099
  }
4195
4100
  function hydrateElmHook(vnode) {
4196
- modEvents.create(vnode); // Attrs are already on the element.
4197
- // modAttrs.create(vnode);
4198
-
4199
- modProps.create(vnode); // Already set.
4200
- // modStaticClassName.create(vnode);
4201
- // modStaticStyle.create(vnode);
4202
- // modComputedClassName.create(vnode);
4203
- // modComputedStyle.create(vnode);
4101
+ applyEventListeners(vnode);
4102
+ patchProps(null, vnode);
4204
4103
  }
4205
4104
  function fallbackElmHook(elm, vnode) {
4206
4105
  const {
@@ -4250,25 +4149,11 @@ function fallbackElmHook(elm, vnode) {
4250
4149
  });
4251
4150
  }
4252
4151
  }
4253
- function updateElmHook(oldVnode, vnode) {
4254
- // Attrs need to be applied to element before props
4255
- // IE11 will wipe out value on radio inputs if value
4256
- // is set before type=radio.
4257
- modAttrs.update(oldVnode, vnode);
4258
- modProps.update(oldVnode, vnode);
4259
- modComputedClassName.update(oldVnode, vnode);
4260
- modComputedStyle.update(oldVnode, vnode);
4261
- }
4262
- function updateChildrenHook(oldVnode, vnode) {
4263
- const {
4264
- elm,
4265
- children
4266
- } = vnode;
4267
-
4268
- if (hasDynamicChildren(children)) {
4269
- updateDynamicChildren(elm, oldVnode.children, children);
4152
+ function patchChildren(parent, oldCh, newCh) {
4153
+ if (hasDynamicChildren(newCh)) {
4154
+ updateDynamicChildren(parent, oldCh, newCh);
4270
4155
  } else {
4271
- updateStaticChildren(elm, oldVnode.children, children);
4156
+ updateStaticChildren(parent, oldCh, newCh);
4272
4157
  }
4273
4158
  }
4274
4159
  function allocateChildrenHook(vnode, vm) {
@@ -4340,18 +4225,6 @@ function createViewModelHook(elm, vnode) {
4340
4225
  shared.assert.isTrue(shared.isArray(vnode.children), `Invalid vnode for a custom element, it must have children defined.`);
4341
4226
  }
4342
4227
  }
4343
- function createCustomElmHook(vnode) {
4344
- modEvents.create(vnode); // Attrs need to be applied to element before props
4345
- // IE11 will wipe out value on radio inputs if value
4346
- // is set before type=radio.
4347
-
4348
- modAttrs.create(vnode);
4349
- modProps.create(vnode);
4350
- modStaticClassName.create(vnode);
4351
- modStaticStyle.create(vnode);
4352
- modComputedClassName.create(vnode);
4353
- modComputedStyle.create(vnode);
4354
- }
4355
4228
  function createChildrenHook(vnode) {
4356
4229
  const {
4357
4230
  elm,
@@ -4531,15 +4404,6 @@ function hydrateChildrenHook(elmChildren, children, vm) {
4531
4404
  }
4532
4405
  }
4533
4406
  }
4534
- function updateCustomElmHook(oldVnode, vnode) {
4535
- // Attrs need to be applied to element before props
4536
- // IE11 will wipe out value on radio inputs if value
4537
- // is set before type=radio.
4538
- modAttrs.update(oldVnode, vnode);
4539
- modProps.update(oldVnode, vnode);
4540
- modComputedClassName.update(oldVnode, vnode);
4541
- modComputedStyle.update(oldVnode, vnode);
4542
- }
4543
4407
  function removeElmHook(vnode) {
4544
4408
  // this method only needs to search on child vnodes from template
4545
4409
  // to trigger the remove hook just in case some of those children
@@ -4556,14 +4420,76 @@ function removeElmHook(vnode) {
4556
4420
  ch.hook.remove(ch, elm);
4557
4421
  }
4558
4422
  }
4423
+ }
4424
+
4425
+ function allocateInSlot(vm, children) {
4426
+ const {
4427
+ cmpSlots: oldSlots
4428
+ } = vm;
4429
+ const cmpSlots = vm.cmpSlots = shared.create(null);
4430
+
4431
+ for (let i = 0, len = children.length; i < len; i += 1) {
4432
+ const vnode = children[i];
4433
+
4434
+ if (shared.isNull(vnode)) {
4435
+ continue;
4436
+ }
4437
+
4438
+ const {
4439
+ data
4440
+ } = vnode;
4441
+ const slotName = data.attrs && data.attrs.slot || '';
4442
+ const vnodes = cmpSlots[slotName] = cmpSlots[slotName] || []; // re-keying the vnodes is necessary to avoid conflicts with default content for the slot
4443
+ // which might have similar keys. Each vnode will always have a key that
4444
+ // starts with a numeric character from compiler. In this case, we add a unique
4445
+ // notation for slotted vnodes keys, e.g.: `@foo:1:1`
4446
+
4447
+ if (!shared.isUndefined(vnode.key)) {
4448
+ vnode.key = `@${slotName}:${vnode.key}`;
4449
+ }
4450
+
4451
+ shared.ArrayPush.call(vnodes, vnode);
4452
+ }
4453
+
4454
+ if (shared.isFalse(vm.isDirty)) {
4455
+ // We need to determine if the old allocation is really different from the new one
4456
+ // and mark the vm as dirty
4457
+ const oldKeys = shared.keys(oldSlots);
4458
+
4459
+ if (oldKeys.length !== shared.keys(cmpSlots).length) {
4460
+ markComponentAsDirty(vm);
4461
+ return;
4462
+ }
4463
+
4464
+ for (let i = 0, len = oldKeys.length; i < len; i += 1) {
4465
+ const key = oldKeys[i];
4466
+
4467
+ if (shared.isUndefined(cmpSlots[key]) || oldSlots[key].length !== cmpSlots[key].length) {
4468
+ markComponentAsDirty(vm);
4469
+ return;
4470
+ }
4471
+
4472
+ const oldVNodes = oldSlots[key];
4473
+ const vnodes = cmpSlots[key];
4474
+
4475
+ for (let j = 0, a = cmpSlots[key].length; j < a; j += 1) {
4476
+ if (oldVNodes[j] !== vnodes[j]) {
4477
+ markComponentAsDirty(vm);
4478
+ return;
4479
+ }
4480
+ }
4481
+ }
4482
+ }
4559
4483
  } // Using a WeakMap instead of a WeakSet because this one works in IE11 :(
4560
4484
 
4485
+
4561
4486
  const FromIteration = new WeakMap(); // dynamic children means it was generated by an iteration
4562
4487
  // in a template, and will require a more complex diffing algo.
4563
4488
 
4564
4489
  function markAsDynamicChildren(children) {
4565
4490
  FromIteration.set(children, 1);
4566
4491
  }
4492
+
4567
4493
  function hasDynamicChildren(children) {
4568
4494
  return FromIteration.has(children);
4569
4495
  }
@@ -4698,11 +4624,11 @@ const ElementHook = {
4698
4624
  linkNodeToShadow(elm, owner);
4699
4625
  fallbackElmHook(elm, vnode);
4700
4626
  vnode.elm = elm;
4701
- createElmHook(vnode);
4627
+ patchElementPropsAndAttrs(null, vnode);
4702
4628
  },
4703
4629
  update: (oldVnode, vnode) => {
4704
- updateElmHook(oldVnode, vnode);
4705
- updateChildrenHook(oldVnode, vnode);
4630
+ patchElementPropsAndAttrs(oldVnode, vnode);
4631
+ patchChildren(vnode.elm, oldVnode.children, vnode.children);
4706
4632
  },
4707
4633
  insert: (vnode, parentNode, referenceNode) => {
4708
4634
  insertNodeHook(vnode, parentNode, referenceNode);
@@ -4776,10 +4702,10 @@ const CustomElementHook = {
4776
4702
  throw new TypeError(`Incorrect Component Constructor`);
4777
4703
  }
4778
4704
 
4779
- createCustomElmHook(vnode);
4705
+ patchElementPropsAndAttrs(null, vnode);
4780
4706
  },
4781
4707
  update: (oldVnode, vnode) => {
4782
- updateCustomElmHook(oldVnode, vnode);
4708
+ patchElementPropsAndAttrs(oldVnode, vnode);
4783
4709
  const vm = getAssociatedVMIfPresent(vnode.elm);
4784
4710
 
4785
4711
  if (vm) {
@@ -4790,7 +4716,7 @@ const CustomElementHook = {
4790
4716
  // will happen, but in native, it does allocate the light dom
4791
4717
 
4792
4718
 
4793
- updateChildrenHook(oldVnode, vnode);
4719
+ patchChildren(vnode.elm, oldVnode.children, vnode.children);
4794
4720
 
4795
4721
  if (vm) {
4796
4722
  if (process.env.NODE_ENV !== 'production') {
@@ -6456,7 +6382,6 @@ function patchShadowRoot(vm, newCh) {
6456
6382
  // patch function mutates vnodes by adding the element reference,
6457
6383
  // however, if patching fails it contains partial changes.
6458
6384
  if (oldCh !== newCh) {
6459
- const fn = hasDynamicChildren(newCh) ? updateDynamicChildren : updateStaticChildren;
6460
6385
  runWithBoundaryProtection(vm, vm, () => {
6461
6386
  // pre
6462
6387
  logOperationStart(2
@@ -6464,8 +6389,8 @@ function patchShadowRoot(vm, newCh) {
6464
6389
  , vm);
6465
6390
  }, () => {
6466
6391
  // job
6467
- const elementToRenderTo = getRenderRoot(vm);
6468
- fn(elementToRenderTo, oldCh, newCh);
6392
+ const renderRoot = getRenderRoot(vm);
6393
+ patchChildren(renderRoot, oldCh, newCh);
6469
6394
  }, () => {
6470
6395
  // post
6471
6396
  logOperationEnd(2
@@ -6759,70 +6684,8 @@ function getErrorBoundaryVM(vm) {
6759
6684
 
6760
6685
  currentVm = currentVm.owner;
6761
6686
  }
6762
- } // slow path routine
6763
- // NOTE: we should probably more this routine to the synthetic shadow folder
6764
- // and get the allocation to be cached by in the elm instead of in the VM
6765
-
6766
-
6767
- function allocateInSlot(vm, children) {
6768
- const {
6769
- cmpSlots: oldSlots
6770
- } = vm;
6771
- const cmpSlots = vm.cmpSlots = shared.create(null);
6772
-
6773
- for (let i = 0, len = children.length; i < len; i += 1) {
6774
- const vnode = children[i];
6775
-
6776
- if (shared.isNull(vnode)) {
6777
- continue;
6778
- }
6779
-
6780
- const {
6781
- data
6782
- } = vnode;
6783
- const slotName = data.attrs && data.attrs.slot || '';
6784
- const vnodes = cmpSlots[slotName] = cmpSlots[slotName] || []; // re-keying the vnodes is necessary to avoid conflicts with default content for the slot
6785
- // which might have similar keys. Each vnode will always have a key that
6786
- // starts with a numeric character from compiler. In this case, we add a unique
6787
- // notation for slotted vnodes keys, e.g.: `@foo:1:1`
6788
-
6789
- if (!shared.isUndefined(vnode.key)) {
6790
- vnode.key = `@${slotName}:${vnode.key}`;
6791
- }
6792
-
6793
- shared.ArrayPush.call(vnodes, vnode);
6794
- }
6795
-
6796
- if (shared.isFalse(vm.isDirty)) {
6797
- // We need to determine if the old allocation is really different from the new one
6798
- // and mark the vm as dirty
6799
- const oldKeys = shared.keys(oldSlots);
6800
-
6801
- if (oldKeys.length !== shared.keys(cmpSlots).length) {
6802
- markComponentAsDirty(vm);
6803
- return;
6804
- }
6805
-
6806
- for (let i = 0, len = oldKeys.length; i < len; i += 1) {
6807
- const key = oldKeys[i];
6808
-
6809
- if (shared.isUndefined(cmpSlots[key]) || oldSlots[key].length !== cmpSlots[key].length) {
6810
- markComponentAsDirty(vm);
6811
- return;
6812
- }
6813
-
6814
- const oldVNodes = oldSlots[key];
6815
- const vnodes = cmpSlots[key];
6816
-
6817
- for (let j = 0, a = cmpSlots[key].length; j < a; j += 1) {
6818
- if (oldVNodes[j] !== vnodes[j]) {
6819
- markComponentAsDirty(vm);
6820
- return;
6821
- }
6822
- }
6823
- }
6824
- }
6825
6687
  }
6688
+
6826
6689
  function runWithBoundaryProtection(vm, owner, pre, job, post) {
6827
6690
  let error;
6828
6691
  pre();
@@ -7332,4 +7195,4 @@ exports.swapTemplate = swapTemplate;
7332
7195
  exports.track = track;
7333
7196
  exports.unwrap = unwrap;
7334
7197
  exports.wire = wire;
7335
- /* version: 2.7.2 */
7198
+ /* version: 2.7.3 */