177
isCustomComponentTag: boolean,
178
): void {
179
for (var propKey in nextProps) {
180
- var nextProp = nextProps[propKey];
180
if (!nextProps.hasOwnProperty(propKey)) {
181
continue;
182
}
183
+ var nextProp = nextProps[propKey];
184
if (propKey === STYLE) {
185
if (__DEV__) {
186
if (nextProp) {
406
props = rawProps;
407
break;
408
case 'input':
409
- ReactDOMFiberInput.mountWrapper(domElement, rawProps);
409
+ ReactDOMFiberInput.initWrapperState(domElement, rawProps);
410
props = ReactDOMFiberInput.getHostProps(domElement, rawProps);
411
trapBubbledEventsLocal(domElement, tag);
412
// For controlled components we always need to ensure we're listening
414
ensureListeningTo(rootContainerElement, 'onChange');
415
break;
416
case 'option':
417
- ReactDOMFiberOption.mountWrapper(domElement, rawProps);
417
+ ReactDOMFiberOption.validateProps(domElement, rawProps);
418
props = ReactDOMFiberOption.getHostProps(domElement, rawProps);
419
break;
420
case 'select':
421
- ReactDOMFiberSelect.mountWrapper(domElement, rawProps);
421
+ ReactDOMFiberSelect.initWrapperState(domElement, rawProps);
422
props = ReactDOMFiberSelect.getHostProps(domElement, rawProps);
423
trapBubbledEventsLocal(domElement, tag);
424
// For controlled components we always need to ensure we're listening
426
ensureListeningTo(rootContainerElement, 'onChange');
427
break;
428
case 'textarea':
429
- ReactDOMFiberTextarea.mountWrapper(domElement, rawProps);
429
+ ReactDOMFiberTextarea.initWrapperState(domElement, rawProps);
430
props = ReactDOMFiberTextarea.getHostProps(domElement, rawProps);
431
trapBubbledEventsLocal(domElement, tag);
432
// For controlled components we always need to ensure we're listening
462
case 'option':
463
ReactDOMFiberOption.postMountWrapper(domElement, rawProps);
464
break;
465
+ case 'select':
466
+ ReactDOMFiberSelect.postMountWrapper(domElement, rawProps);
467
+ break;
468
default:
469
if (typeof props.onClick === 'function') {
470
// TODO: This cast may not be sound for SVG, MathML or custom elements.
707
}
708
},
709
710
+ diffHydratedProperties(
711
+ domElement: Element,
712
+ tag: string,
713
+ rawProps: Object,
714
+ rootContainerElement: Element | Document,
715
+ ): null | Array<mixed> {
716
+ if (__DEV__) {
717
+ var isCustomComponentTag = isCustomComponent(tag, rawProps);
718
+ validatePropertiesInDevelopment(tag, rawProps);
719
+ if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
720
+ warning(
721
+ false,
722
+ '%s is using shady DOM. Using shady DOM with React can ' +
723
+ 'cause things to break subtly.',
724
+ getCurrentFiberOwnerName() || 'A component',
725
+ );
726
+ didWarnShadyDOM = true;
727
+ }
728
+ }
729
+
730
+ switch (tag) {
731
+ case 'audio':
732
+ case 'form':
733
+ case 'iframe':
734
+ case 'img':
735
+ case 'image':
736
+ case 'link':
737
+ case 'object':
738
+ case 'source':
739
+ case 'video':
740
+ case 'details':
741
+ trapBubbledEventsLocal(domElement, tag);
742
+ break;
743
+ case 'input':
744
+ ReactDOMFiberInput.initWrapperState(domElement, rawProps);
745
+ trapBubbledEventsLocal(domElement, tag);
746
+ // For controlled components we always need to ensure we're listening
747
+ // to onChange. Even if there is no listener.
748
+ ensureListeningTo(rootContainerElement, 'onChange');
749
+ break;
750
+ case 'option':
751
+ ReactDOMFiberOption.validateProps(domElement, rawProps);
752
+ break;
753
+ case 'select':
754
+ ReactDOMFiberSelect.initWrapperState(domElement, rawProps);
755
+ trapBubbledEventsLocal(domElement, tag);
756
+ // For controlled components we always need to ensure we're listening
757
+ // to onChange. Even if there is no listener.
758
+ ensureListeningTo(rootContainerElement, 'onChange');
759
+ break;
760
+ case 'textarea':
761
+ ReactDOMFiberTextarea.initWrapperState(domElement, rawProps);
762
+ trapBubbledEventsLocal(domElement, tag);
763
+ // For controlled components we always need to ensure we're listening
764
+ // to onChange. Even if there is no listener.
765
+ ensureListeningTo(rootContainerElement, 'onChange');
766
+ break;
767
+ }
768
+
769
+ assertValidProps(tag, rawProps, getCurrentFiberOwnerName);
770
+
771
+ var updatePayload = null;
772
+ for (var propKey in rawProps) {
773
+ if (!rawProps.hasOwnProperty(propKey)) {
774
+ continue;
775
+ }
776
+ var nextProp = rawProps[propKey];
777
+ if (propKey === CHILDREN) {
778
+ // For text content children we compare against textContent. This
779
+ // might match additional HTML that is hidden when we read it using
780
+ // textContent. E.g. "foo" will match "f<span>oo</span>" but that still
781
+ // satisfies our requirement. Our requirement is not to produce perfect
782
+ // HTML and attributes. Ideally we should preserve structure but it's
783
+ // ok not to if the visible content is still enough to indicate what
784
+ // even listeners these nodes might be wired up to.
785
+ // TODO: Warn if there is more than a single textNode as a child.
786
+ // TODO: Should we use domElement.firstChild.nodeValue to compare?
787
+ if (typeof nextProp === 'string') {
788
+ if (domElement.textContent !== nextProp) {
789
+ updatePayload = [CHILDREN, nextProp];
790
+ }
791
+ } else if (typeof nextProp === 'number') {
792
+ if (domElement.textContent !== '' + nextProp) {
793
+ updatePayload = [CHILDREN, '' + nextProp];
794
+ }
795
+ }
796
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
797
+ if (nextProp) {
798
+ ensureListeningTo(rootContainerElement, propKey);
799
+ }
800
+ }
801
+ }
802
+
803
+ switch (tag) {
804
+ case 'input':
805
+ // TODO: Make sure we check if this is still unmounted or do any clean
806
+ // up necessary since we never stop tracking anymore.
807
+ inputValueTracking.trackNode((domElement: any));
808
+ ReactDOMFiberInput.postMountWrapper(domElement, rawProps);
809
+ break;
810
+ case 'textarea':
811
+ // TODO: Make sure we check if this is still unmounted or do any clean
812
+ // up necessary since we never stop tracking anymore.
813
+ inputValueTracking.trackNode((domElement: any));
814
+ ReactDOMFiberTextarea.postMountWrapper(domElement, rawProps);
815
+ break;
816
+ case 'select':
817
+ case 'option':
818
+ // For input and textarea we current always set the value property at
819
+ // post mount to force it to diverge from attributes. However, for
820
+ // option and select we don't quite do the same thing and select
821
+ // is not resilient to the DOM state changing so we don't do that here.
822
+ // TODO: Consider not doing this for input and textarea.
823
+ break;
824
+ default:
825
+ if (typeof rawProps.onClick === 'function') {
826
+ // TODO: This cast may not be sound for SVG, MathML or custom elements.
827
+ trapClickOnNonInteractiveElement(((domElement: any): HTMLElement));
828
+ }
829
+ break;
830
+ }
831
+
832
+ return updatePayload;
833
+ },
834
+
835
restoreControlledState(
836
domElement: Element,
837
tag: string,