@samitouri / QOS-React / commits / dea43046ef

Dedupe unknown tag name warning and ignore <time> (#10275)

* Deduplicate unknown DOM tag warning * Don't warn about <time> because it is widely used Other browsers implement it, and Chrome will ship it soon too. * Use hasOwnProperty * Fix corner case: hasOwnProperty as a tag * Update comments to be more correct factually

Dan Abramov committed Jul 26, 2017 at 11:57 UTC dea43046ef75064279bc833149400beca500b825
3 files changed +75 -21
src/renderers/dom/fiber/ReactDOMFiberComponent.js
+23 -9
@@ -65,6 +65,14 @@ var {
65 } = DOMNamespaces;
66
67 if (__DEV__) {
68 + var warnedUnknownTags = {
69 + // Chrome is the only major browser not shipping <time>. But as of July
70 + // 2017 it intends to ship it due to widespread usage. We intentionally
71 + // *don't* warn for <time> even if it's unrecognized by Chrome because
72 + // it soon will be, and many apps have been using it anyway.
73 + time: true,
74 + };
75 +
76 var validatePropertiesInDevelopment = function(type, props) {
77 validateARIAProperties(type, props);
78 validateInputPropertes(type, props);
@@ -414,15 +422,21 @@ var ReactDOMFiberComponent = {
422
423 if (__DEV__) {
424 if (namespaceURI === HTML_NAMESPACE) {
417 - warning(
418 - isCustomComponentTag ||
419 - Object.prototype.toString.call(domElement) !==
420 - '[object HTMLUnknownElement]',
421 - 'The tag <%s> is unrecognized in this browser. ' +
422 - 'If you meant to render a React component, start its name with ' +
423 - 'an uppercase letter.',
424 - type,
425 - );
425 + if (
426 + !isCustomComponentTag &&
427 + Object.prototype.toString.call(domElement) ===
428 + '[object HTMLUnknownElement]' &&
429 + !Object.prototype.hasOwnProperty.call(warnedUnknownTags, type)
430 + ) {
431 + warnedUnknownTags[type] = true;
432 + warning(
433 + false,
434 + 'The tag <%s> is unrecognized in this browser. ' +
435 + 'If you meant to render a React component, start its name with ' +
436 + 'an uppercase letter.',
437 + type,
438 + );
439 + }
440 }
441 }
442
src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
+30 -3
@@ -822,17 +822,44 @@ describe('ReactDOMComponent', () => {
822 if (this instanceof window.HTMLUnknownElement) {
823 return '[object HTMLUnknownElement]';
824 }
825 + // Special case! Read explanation below in the test.
826 + if (this instanceof window.HTMLTimeElement) {
827 + return '[object HTMLUnknownElement]';
828 + }
829 return realToString.apply(this, arguments);
830 };
831 Object.prototype.toString = wrappedToString; // eslint-disable-line no-extend-native
828 - ReactTestUtils.renderIntoDocument(<mycustomcomponent />);
832 +
833 + ReactTestUtils.renderIntoDocument(<bar />);
834 + // Test deduplication
835 + ReactTestUtils.renderIntoDocument(<foo />);
836 + ReactTestUtils.renderIntoDocument(<foo />);
837 + // This is a funny case.
838 + // Chrome is the only major browser not shipping <time>. But as of July
839 + // 2017 it intends to ship it due to widespread usage. We intentionally
840 + // *don't* warn for <time> even if it's unrecognized by Chrome because
841 + // it soon will be, and many apps have been using it anyway.
842 + ReactTestUtils.renderIntoDocument(<time />);
843 + // Corner case. Make sure out deduplication logic doesn't break with weird tag.
844 + ReactTestUtils.renderIntoDocument(<hasOwnProperty />);
845 } finally {
846 Object.prototype.toString = realToString; // eslint-disable-line no-extend-native
847 }
848
833 - expectDev(console.error.calls.count()).toBe(1);
849 + expectDev(console.error.calls.count()).toBe(4);
850 expectDev(console.error.calls.argsFor(0)[0]).toContain(
835 - 'The tag <mycustomcomponent> is unrecognized in this browser',
851 + 'The tag <bar> is unrecognized in this browser',
852 + );
853 + expectDev(console.error.calls.argsFor(1)[0]).toContain(
854 + 'The tag <foo> is unrecognized in this browser',
855 + );
856 + expectDev(console.error.calls.argsFor(2)[0]).toContain(
857 + '<hasOwnProperty /> is using uppercase HTML',
858 + );
859 + expectDev(console.error.calls.argsFor(3)[0]).toContain(
860 + ReactDOMFeatureFlags.useFiber
861 + ? 'The tag <hasOwnProperty> is unrecognized in this browser'
862 + : 'The tag <hasownproperty> is unrecognized in this browser',
863 );
864 });
865
src/renderers/dom/stack/client/ReactDOMComponent.js
+22 -9
@@ -374,6 +374,13 @@ function validateDangerousTag(tag) {
374 }
375
376 var globalIdCounter = 1;
377 +var warnedUnknownTags = {
378 + // Chrome is the only major browser not shipping <time>. But as of July
379 + // 2017 it intends to ship it due to widespread usage. We intentionally
380 + // *don't* warn for <time> even if it's unrecognized by Chrome because
381 + // it soon will be, and many apps have been using it anyway.
382 + time: true,
383 +};
384
385 /**
386 * Creates a new React class that is idempotent and capable of containing other
@@ -578,15 +585,21 @@ ReactDOMComponent.Mixin = {
585 didWarnShadyDOM = true;
586 }
587 if (this._namespaceURI === DOMNamespaces.html) {
581 - warning(
582 - isCustomComponentTag ||
583 - Object.prototype.toString.call(el) !==
584 - '[object HTMLUnknownElement]',
585 - 'The tag <%s> is unrecognized in this browser. ' +
586 - 'If you meant to render a React component, start its name with ' +
587 - 'an uppercase letter.',
588 - this._tag,
589 - );
588 + if (
589 + !isCustomComponentTag &&
590 + Object.prototype.toString.call(el) ===
591 + '[object HTMLUnknownElement]' &&
592 + !Object.prototype.hasOwnProperty.call(warnedUnknownTags, this._tag)
593 + ) {
594 + warnedUnknownTags[this._tag] = true;
595 + warning(
596 + false,
597 + 'The tag <%s> is unrecognized in this browser. ' +
598 + 'If you meant to render a React component, start its name with ' +
599 + 'an uppercase letter.',
600 + this._tag,
601 + );
602 + }
603 }
604 }
605 ReactDOMComponentTree.precacheNode(this, el);