mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
Avoid meta programming to initialize functions in module scope (#26388)
I'm trying to get rid of all meta programming in the module scope so
that closure can do a better job figuring out cyclic dependencies and
ability to reorder.
This is converting a lot of the patterns that assign functions
conditionally to using function declarations instead.
```
let fn;
if (__DEV__) {
fn = function() {
...
};
}
```
->
```
function fn() {
if (__DEV__) {
...
}
}
```
This commit is contained in:
parent
21aee59e45
commit
d310d654a7
|
|
@ -13,7 +13,7 @@
|
||||||
* Change environment support for PointerEvent.
|
* Change environment support for PointerEvent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const emptyFunction = function () {};
|
function emptyFunction() {}
|
||||||
|
|
||||||
export function hasPointerEvent() {
|
export function hasPointerEvent() {
|
||||||
return global != null && global.PointerEvent != null;
|
return global != null && global.PointerEvent != null;
|
||||||
|
|
|
||||||
|
|
@ -94,15 +94,8 @@ const HTML = '__html';
|
||||||
let warnedUnknownTags: {
|
let warnedUnknownTags: {
|
||||||
[key: string]: boolean,
|
[key: string]: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
let validatePropertiesInDevelopment;
|
|
||||||
let warnForPropDifference;
|
|
||||||
let warnForExtraAttributes;
|
|
||||||
let warnForInvalidEventListener;
|
|
||||||
let canDiffStyleForHydrationWarning;
|
let canDiffStyleForHydrationWarning;
|
||||||
|
|
||||||
let normalizeHTML;
|
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
warnedUnknownTags = {
|
warnedUnknownTags = {
|
||||||
// There are working polyfills for <dialog>. Let people use it.
|
// There are working polyfills for <dialog>. Let people use it.
|
||||||
|
|
@ -115,15 +108,6 @@ if (__DEV__) {
|
||||||
webview: true,
|
webview: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
validatePropertiesInDevelopment = function (type: string, props: any) {
|
|
||||||
validateARIAProperties(type, props);
|
|
||||||
validateInputProperties(type, props);
|
|
||||||
validateUnknownProperties(type, props, {
|
|
||||||
registrationNameDependencies,
|
|
||||||
possibleRegistrationNames,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// IE 11 parses & normalizes the style attribute as opposed to other
|
// IE 11 parses & normalizes the style attribute as opposed to other
|
||||||
// browsers. It adds spaces and sorts the properties in some
|
// browsers. It adds spaces and sorts the properties in some
|
||||||
// non-alphabetical order. Handling that would require sorting CSS
|
// non-alphabetical order. Handling that would require sorting CSS
|
||||||
|
|
@ -133,12 +117,25 @@ if (__DEV__) {
|
||||||
// in that browser completely in favor of doing all that work.
|
// in that browser completely in favor of doing all that work.
|
||||||
// See https://github.com/facebook/react/issues/11807
|
// See https://github.com/facebook/react/issues/11807
|
||||||
canDiffStyleForHydrationWarning = canUseDOM && !document.documentMode;
|
canDiffStyleForHydrationWarning = canUseDOM && !document.documentMode;
|
||||||
|
}
|
||||||
|
|
||||||
warnForPropDifference = function (
|
function validatePropertiesInDevelopment(type: string, props: any) {
|
||||||
propName: string,
|
if (__DEV__) {
|
||||||
serverValue: mixed,
|
validateARIAProperties(type, props);
|
||||||
clientValue: mixed,
|
validateInputProperties(type, props);
|
||||||
) {
|
validateUnknownProperties(type, props, {
|
||||||
|
registrationNameDependencies,
|
||||||
|
possibleRegistrationNames,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function warnForPropDifference(
|
||||||
|
propName: string,
|
||||||
|
serverValue: mixed,
|
||||||
|
clientValue: mixed,
|
||||||
|
) {
|
||||||
|
if (__DEV__) {
|
||||||
if (didWarnInvalidHydration) {
|
if (didWarnInvalidHydration) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -156,9 +153,11 @@ if (__DEV__) {
|
||||||
JSON.stringify(normalizedServerValue),
|
JSON.stringify(normalizedServerValue),
|
||||||
JSON.stringify(normalizedClientValue),
|
JSON.stringify(normalizedClientValue),
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
warnForExtraAttributes = function (attributeNames: Set<string>) {
|
function warnForExtraAttributes(attributeNames: Set<string>) {
|
||||||
|
if (__DEV__) {
|
||||||
if (didWarnInvalidHydration) {
|
if (didWarnInvalidHydration) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -168,12 +167,11 @@ if (__DEV__) {
|
||||||
names.push(name);
|
names.push(name);
|
||||||
});
|
});
|
||||||
console.error('Extra attributes from the server: %s', names);
|
console.error('Extra attributes from the server: %s', names);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
warnForInvalidEventListener = function (
|
function warnForInvalidEventListener(registrationName: string, listener: any) {
|
||||||
registrationName: string,
|
if (__DEV__) {
|
||||||
listener: any,
|
|
||||||
) {
|
|
||||||
if (listener === false) {
|
if (listener === false) {
|
||||||
console.error(
|
console.error(
|
||||||
'Expected `%s` listener to be a function, instead got `false`.\n\n' +
|
'Expected `%s` listener to be a function, instead got `false`.\n\n' +
|
||||||
|
|
@ -190,11 +188,13 @@ if (__DEV__) {
|
||||||
typeof listener,
|
typeof listener,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the HTML and read it back to normalize the HTML string so that it
|
// Parse the HTML and read it back to normalize the HTML string so that it
|
||||||
// can be used for comparison.
|
// can be used for comparison.
|
||||||
normalizeHTML = function (parent: Element, html: string) {
|
function normalizeHTML(parent: Element, html: string) {
|
||||||
|
if (__DEV__) {
|
||||||
// We could have created a separate document here to avoid
|
// We could have created a separate document here to avoid
|
||||||
// re-initializing custom elements if they exist. But this breaks
|
// re-initializing custom elements if they exist. But this breaks
|
||||||
// how <noscript> is being handled. So we use the same document.
|
// how <noscript> is being handled. So we use the same document.
|
||||||
|
|
@ -208,7 +208,7 @@ if (__DEV__) {
|
||||||
);
|
);
|
||||||
testElement.innerHTML = html;
|
testElement.innerHTML = html;
|
||||||
return testElement.innerHTML;
|
return testElement.innerHTML;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTML parsing normalizes CR and CRLF to LF.
|
// HTML parsing normalizes CR and CRLF to LF.
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* globals MSApp */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a function which has 'unsafe' privileges (required by windows8 apps)
|
|
||||||
*/
|
|
||||||
const createMicrosoftUnsafeLocalFunction = function (func) {
|
|
||||||
if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
|
|
||||||
return function (arg0, arg1, arg2, arg3) {
|
|
||||||
MSApp.execUnsafeLocalFunction(function () {
|
|
||||||
return func(arg0, arg1, arg2, arg3);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return func;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default createMicrosoftUnsafeLocalFunction;
|
|
||||||
|
|
@ -7,24 +7,15 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* globals MSApp */
|
||||||
|
|
||||||
import {SVG_NAMESPACE} from './DOMNamespaces';
|
import {SVG_NAMESPACE} from './DOMNamespaces';
|
||||||
import createMicrosoftUnsafeLocalFunction from './createMicrosoftUnsafeLocalFunction';
|
|
||||||
import {enableTrustedTypesIntegration} from 'shared/ReactFeatureFlags';
|
import {enableTrustedTypesIntegration} from 'shared/ReactFeatureFlags';
|
||||||
|
|
||||||
// SVG temp container for IE lacking innerHTML
|
// SVG temp container for IE lacking innerHTML
|
||||||
let reusableSVGContainer: HTMLElement;
|
let reusableSVGContainer: HTMLElement;
|
||||||
|
|
||||||
/**
|
function setInnerHTMLImpl(
|
||||||
* Set the innerHTML property of a node
|
|
||||||
*
|
|
||||||
* @param {DOMElement} node
|
|
||||||
* @param {string} html
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
const setInnerHTML: (
|
|
||||||
node: Element,
|
|
||||||
html: {valueOf(): {toString(): string, ...}, ...},
|
|
||||||
) => void = createMicrosoftUnsafeLocalFunction(function (
|
|
||||||
node: Element,
|
node: Element,
|
||||||
html: {valueOf(): {toString(): string, ...}, ...},
|
html: {valueOf(): {toString(): string, ...}, ...},
|
||||||
): void {
|
): void {
|
||||||
|
|
@ -66,6 +57,26 @@ const setInnerHTML: (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.innerHTML = (html: any);
|
node.innerHTML = (html: any);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
let setInnerHTML: (
|
||||||
|
node: Element,
|
||||||
|
html: {valueOf(): {toString(): string, ...}, ...},
|
||||||
|
) => void = setInnerHTMLImpl;
|
||||||
|
// $FlowFixMe[cannot-resolve-name]
|
||||||
|
if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
|
||||||
|
/**
|
||||||
|
* Create a function which has 'unsafe' privileges (required by windows8 apps)
|
||||||
|
*/
|
||||||
|
setInnerHTML = function (
|
||||||
|
node: Element,
|
||||||
|
html: {valueOf(): {toString(): string, ...}, ...},
|
||||||
|
): void {
|
||||||
|
// $FlowFixMe[cannot-resolve-name]
|
||||||
|
return MSApp.execUnsafeLocalFunction(function () {
|
||||||
|
return setInnerHTMLImpl(node, html);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default setInnerHTML;
|
export default setInnerHTML;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import {TEXT_NODE} from './HTMLNodeType';
|
||||||
* @param {string} text
|
* @param {string} text
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
const setTextContent = function (node: Element, text: string): void {
|
function setTextContent(node: Element, text: string): void {
|
||||||
if (text) {
|
if (text) {
|
||||||
const firstChild = node.firstChild;
|
const firstChild = node.firstChild;
|
||||||
|
|
||||||
|
|
@ -32,6 +32,6 @@ const setTextContent = function (node: Element, text: string): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.textContent = text;
|
node.textContent = text;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default setTextContent;
|
export default setTextContent;
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,6 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type ValidateDOMNesting = (?string, ?string, AncestorInfoDev) => void;
|
|
||||||
let validateDOMNesting: ValidateDOMNesting = (() => {}: any);
|
|
||||||
|
|
||||||
type UpdatedAncestorInfoDev = (?AncestorInfoDev, string) => AncestorInfoDev;
|
|
||||||
let updatedAncestorInfoDev: UpdatedAncestorInfoDev = (() => {}: any);
|
|
||||||
|
|
||||||
type Info = {tag: string};
|
type Info = {tag: string};
|
||||||
export type AncestorInfoDev = {
|
export type AncestorInfoDev = {
|
||||||
current: ?Info,
|
current: ?Info,
|
||||||
|
|
@ -30,156 +24,159 @@ export type AncestorInfoDev = {
|
||||||
containerTagInScope: ?Info,
|
containerTagInScope: ?Info,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (__DEV__) {
|
// This validation code was written based on the HTML5 parsing spec:
|
||||||
// This validation code was written based on the HTML5 parsing spec:
|
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
|
//
|
||||||
//
|
// Note: this does not catch all invalid nesting, nor does it try to (as it's
|
||||||
// Note: this does not catch all invalid nesting, nor does it try to (as it's
|
// not clear what practical benefit doing so provides); instead, we warn only
|
||||||
// not clear what practical benefit doing so provides); instead, we warn only
|
// for cases where the parser will give a parse tree differing from what React
|
||||||
// for cases where the parser will give a parse tree differing from what React
|
// intended. For example, <b><div></div></b> is invalid but we don't warn
|
||||||
// intended. For example, <b><div></div></b> is invalid but we don't warn
|
// because it still parses correctly; we do warn for other cases like nested
|
||||||
// because it still parses correctly; we do warn for other cases like nested
|
// <p> tags where the beginning of the second element implicitly closes the
|
||||||
// <p> tags where the beginning of the second element implicitly closes the
|
// first, causing a confusing mess.
|
||||||
// first, causing a confusing mess.
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#special
|
// https://html.spec.whatwg.org/multipage/syntax.html#special
|
||||||
const specialTags = [
|
const specialTags = [
|
||||||
'address',
|
'address',
|
||||||
'applet',
|
'applet',
|
||||||
'area',
|
'area',
|
||||||
'article',
|
'article',
|
||||||
'aside',
|
'aside',
|
||||||
'base',
|
'base',
|
||||||
'basefont',
|
'basefont',
|
||||||
'bgsound',
|
'bgsound',
|
||||||
'blockquote',
|
'blockquote',
|
||||||
'body',
|
'body',
|
||||||
'br',
|
'br',
|
||||||
'button',
|
'button',
|
||||||
'caption',
|
'caption',
|
||||||
'center',
|
'center',
|
||||||
'col',
|
'col',
|
||||||
'colgroup',
|
'colgroup',
|
||||||
'dd',
|
'dd',
|
||||||
'details',
|
'details',
|
||||||
'dir',
|
'dir',
|
||||||
'div',
|
'div',
|
||||||
'dl',
|
'dl',
|
||||||
'dt',
|
'dt',
|
||||||
'embed',
|
'embed',
|
||||||
'fieldset',
|
'fieldset',
|
||||||
'figcaption',
|
'figcaption',
|
||||||
'figure',
|
'figure',
|
||||||
'footer',
|
'footer',
|
||||||
'form',
|
'form',
|
||||||
'frame',
|
'frame',
|
||||||
'frameset',
|
'frameset',
|
||||||
'h1',
|
'h1',
|
||||||
'h2',
|
'h2',
|
||||||
'h3',
|
'h3',
|
||||||
'h4',
|
'h4',
|
||||||
'h5',
|
'h5',
|
||||||
'h6',
|
'h6',
|
||||||
'head',
|
'head',
|
||||||
'header',
|
'header',
|
||||||
'hgroup',
|
'hgroup',
|
||||||
'hr',
|
'hr',
|
||||||
'html',
|
'html',
|
||||||
'iframe',
|
'iframe',
|
||||||
'img',
|
'img',
|
||||||
'input',
|
'input',
|
||||||
'isindex',
|
'isindex',
|
||||||
'li',
|
'li',
|
||||||
'link',
|
'link',
|
||||||
'listing',
|
'listing',
|
||||||
'main',
|
'main',
|
||||||
'marquee',
|
'marquee',
|
||||||
'menu',
|
'menu',
|
||||||
'menuitem',
|
'menuitem',
|
||||||
'meta',
|
'meta',
|
||||||
'nav',
|
'nav',
|
||||||
'noembed',
|
'noembed',
|
||||||
'noframes',
|
'noframes',
|
||||||
'noscript',
|
'noscript',
|
||||||
'object',
|
'object',
|
||||||
'ol',
|
'ol',
|
||||||
'p',
|
'p',
|
||||||
'param',
|
'param',
|
||||||
'plaintext',
|
'plaintext',
|
||||||
'pre',
|
'pre',
|
||||||
'script',
|
'script',
|
||||||
'section',
|
'section',
|
||||||
'select',
|
'select',
|
||||||
'source',
|
'source',
|
||||||
'style',
|
'style',
|
||||||
'summary',
|
'summary',
|
||||||
'table',
|
'table',
|
||||||
'tbody',
|
'tbody',
|
||||||
'td',
|
'td',
|
||||||
'template',
|
'template',
|
||||||
'textarea',
|
'textarea',
|
||||||
'tfoot',
|
'tfoot',
|
||||||
'th',
|
'th',
|
||||||
'thead',
|
'thead',
|
||||||
'title',
|
'title',
|
||||||
'tr',
|
'tr',
|
||||||
'track',
|
'track',
|
||||||
'ul',
|
'ul',
|
||||||
'wbr',
|
'wbr',
|
||||||
'xmp',
|
'xmp',
|
||||||
];
|
];
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
|
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
|
||||||
const inScopeTags = [
|
const inScopeTags = [
|
||||||
'applet',
|
'applet',
|
||||||
'caption',
|
'caption',
|
||||||
'html',
|
'html',
|
||||||
'table',
|
'table',
|
||||||
'td',
|
'td',
|
||||||
'th',
|
'th',
|
||||||
'marquee',
|
'marquee',
|
||||||
'object',
|
'object',
|
||||||
'template',
|
'template',
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
|
// https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
|
||||||
// TODO: Distinguish by namespace here -- for <title>, including it here
|
// TODO: Distinguish by namespace here -- for <title>, including it here
|
||||||
// errs on the side of fewer warnings
|
// errs on the side of fewer warnings
|
||||||
'foreignObject',
|
'foreignObject',
|
||||||
'desc',
|
'desc',
|
||||||
'title',
|
'title',
|
||||||
];
|
];
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
|
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
|
||||||
const buttonScopeTags = inScopeTags.concat(['button']);
|
const buttonScopeTags = __DEV__ ? inScopeTags.concat(['button']) : [];
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
|
// https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
|
||||||
const impliedEndTags = [
|
const impliedEndTags = [
|
||||||
'dd',
|
'dd',
|
||||||
'dt',
|
'dt',
|
||||||
'li',
|
'li',
|
||||||
'option',
|
'option',
|
||||||
'optgroup',
|
'optgroup',
|
||||||
'p',
|
'p',
|
||||||
'rp',
|
'rp',
|
||||||
'rt',
|
'rt',
|
||||||
];
|
];
|
||||||
|
|
||||||
const emptyAncestorInfoDev: AncestorInfoDev = {
|
const emptyAncestorInfoDev: AncestorInfoDev = {
|
||||||
current: null,
|
current: null,
|
||||||
|
|
||||||
formTag: null,
|
formTag: null,
|
||||||
aTagInScope: null,
|
aTagInScope: null,
|
||||||
buttonTagInScope: null,
|
buttonTagInScope: null,
|
||||||
nobrTagInScope: null,
|
nobrTagInScope: null,
|
||||||
pTagInButtonScope: null,
|
pTagInButtonScope: null,
|
||||||
|
|
||||||
listItemTagAutoclosing: null,
|
listItemTagAutoclosing: null,
|
||||||
dlItemTagAutoclosing: null,
|
dlItemTagAutoclosing: null,
|
||||||
|
|
||||||
containerTagInScope: null,
|
containerTagInScope: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
updatedAncestorInfoDev = function (oldInfo: ?AncestorInfoDev, tag: string) {
|
function updatedAncestorInfoDev(
|
||||||
|
oldInfo: ?AncestorInfoDev,
|
||||||
|
tag: string,
|
||||||
|
): AncestorInfoDev {
|
||||||
|
if (__DEV__) {
|
||||||
const ancestorInfo = {...(oldInfo || emptyAncestorInfoDev)};
|
const ancestorInfo = {...(oldInfo || emptyAncestorInfoDev)};
|
||||||
const info = {tag};
|
const info = {tag};
|
||||||
|
|
||||||
|
|
@ -234,213 +231,214 @@ if (__DEV__) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return ancestorInfo;
|
return ancestorInfo;
|
||||||
};
|
} else {
|
||||||
|
return (null: any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether
|
* Returns whether
|
||||||
*/
|
*/
|
||||||
const isTagValidWithParent = function (
|
function isTagValidWithParent(tag: string, parentTag: ?string): boolean {
|
||||||
tag: string,
|
// First, let's check if we're in an unusual parsing mode...
|
||||||
parentTag: ?string,
|
switch (parentTag) {
|
||||||
): boolean {
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
|
||||||
// First, let's check if we're in an unusual parsing mode...
|
case 'select':
|
||||||
switch (parentTag) {
|
return tag === 'option' || tag === 'optgroup' || tag === '#text';
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
|
case 'optgroup':
|
||||||
case 'select':
|
return tag === 'option' || tag === '#text';
|
||||||
return tag === 'option' || tag === 'optgroup' || tag === '#text';
|
// Strictly speaking, seeing an <option> doesn't mean we're in a <select>
|
||||||
case 'optgroup':
|
// but
|
||||||
return tag === 'option' || tag === '#text';
|
case 'option':
|
||||||
// Strictly speaking, seeing an <option> doesn't mean we're in a <select>
|
return tag === '#text';
|
||||||
// but
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
|
||||||
case 'option':
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
|
||||||
return tag === '#text';
|
// No special behavior since these rules fall back to "in body" mode for
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
|
// all except special table nodes which cause bad parsing behavior anyway.
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
|
|
||||||
// No special behavior since these rules fall back to "in body" mode for
|
|
||||||
// all except special table nodes which cause bad parsing behavior anyway.
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
|
||||||
case 'tr':
|
case 'tr':
|
||||||
return (
|
return (
|
||||||
tag === 'th' ||
|
tag === 'th' ||
|
||||||
tag === 'td' ||
|
tag === 'td' ||
|
||||||
tag === 'style' ||
|
tag === 'style' ||
|
||||||
tag === 'script' ||
|
tag === 'script' ||
|
||||||
tag === 'template'
|
tag === 'template'
|
||||||
);
|
);
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
|
||||||
case 'tbody':
|
case 'tbody':
|
||||||
case 'thead':
|
case 'thead':
|
||||||
case 'tfoot':
|
case 'tfoot':
|
||||||
return (
|
return (
|
||||||
tag === 'tr' ||
|
tag === 'tr' ||
|
||||||
tag === 'style' ||
|
tag === 'style' ||
|
||||||
tag === 'script' ||
|
tag === 'script' ||
|
||||||
tag === 'template'
|
tag === 'template'
|
||||||
);
|
);
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
|
||||||
case 'colgroup':
|
case 'colgroup':
|
||||||
return tag === 'col' || tag === 'template';
|
return tag === 'col' || tag === 'template';
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
|
||||||
case 'table':
|
case 'table':
|
||||||
return (
|
return (
|
||||||
tag === 'caption' ||
|
tag === 'caption' ||
|
||||||
tag === 'colgroup' ||
|
tag === 'colgroup' ||
|
||||||
tag === 'tbody' ||
|
tag === 'tbody' ||
|
||||||
tag === 'tfoot' ||
|
tag === 'tfoot' ||
|
||||||
tag === 'thead' ||
|
tag === 'thead' ||
|
||||||
tag === 'style' ||
|
tag === 'style' ||
|
||||||
tag === 'script' ||
|
tag === 'script' ||
|
||||||
tag === 'template'
|
tag === 'template'
|
||||||
);
|
);
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
|
||||||
case 'head':
|
case 'head':
|
||||||
return (
|
return (
|
||||||
tag === 'base' ||
|
tag === 'base' ||
|
||||||
tag === 'basefont' ||
|
tag === 'basefont' ||
|
||||||
tag === 'bgsound' ||
|
tag === 'bgsound' ||
|
||||||
tag === 'link' ||
|
tag === 'link' ||
|
||||||
tag === 'meta' ||
|
tag === 'meta' ||
|
||||||
tag === 'title' ||
|
tag === 'title' ||
|
||||||
tag === 'noscript' ||
|
tag === 'noscript' ||
|
||||||
tag === 'noframes' ||
|
tag === 'noframes' ||
|
||||||
tag === 'style' ||
|
tag === 'style' ||
|
||||||
tag === 'script' ||
|
tag === 'script' ||
|
||||||
tag === 'template'
|
tag === 'template'
|
||||||
);
|
);
|
||||||
// https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
|
// https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
|
||||||
case 'html':
|
case 'html':
|
||||||
return tag === 'head' || tag === 'body' || tag === 'frameset';
|
return tag === 'head' || tag === 'body' || tag === 'frameset';
|
||||||
case 'frameset':
|
case 'frameset':
|
||||||
return tag === 'frame';
|
return tag === 'frame';
|
||||||
case '#document':
|
case '#document':
|
||||||
return tag === 'html';
|
return tag === 'html';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Probably in the "in body" parsing mode, so we outlaw only tag combos
|
// Probably in the "in body" parsing mode, so we outlaw only tag combos
|
||||||
// where the parsing rules cause implicit opens or closes to be added.
|
// where the parsing rules cause implicit opens or closes to be added.
|
||||||
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case 'h1':
|
case 'h1':
|
||||||
case 'h2':
|
case 'h2':
|
||||||
case 'h3':
|
case 'h3':
|
||||||
case 'h4':
|
case 'h4':
|
||||||
case 'h5':
|
case 'h5':
|
||||||
case 'h6':
|
case 'h6':
|
||||||
return (
|
return (
|
||||||
parentTag !== 'h1' &&
|
parentTag !== 'h1' &&
|
||||||
parentTag !== 'h2' &&
|
parentTag !== 'h2' &&
|
||||||
parentTag !== 'h3' &&
|
parentTag !== 'h3' &&
|
||||||
parentTag !== 'h4' &&
|
parentTag !== 'h4' &&
|
||||||
parentTag !== 'h5' &&
|
parentTag !== 'h5' &&
|
||||||
parentTag !== 'h6'
|
parentTag !== 'h6'
|
||||||
);
|
);
|
||||||
|
|
||||||
case 'rp':
|
case 'rp':
|
||||||
case 'rt':
|
case 'rt':
|
||||||
return impliedEndTags.indexOf(parentTag) === -1;
|
return impliedEndTags.indexOf(parentTag) === -1;
|
||||||
|
|
||||||
case 'body':
|
case 'body':
|
||||||
case 'caption':
|
case 'caption':
|
||||||
case 'col':
|
case 'col':
|
||||||
case 'colgroup':
|
case 'colgroup':
|
||||||
case 'frameset':
|
case 'frameset':
|
||||||
case 'frame':
|
case 'frame':
|
||||||
case 'head':
|
case 'head':
|
||||||
case 'html':
|
case 'html':
|
||||||
case 'tbody':
|
case 'tbody':
|
||||||
case 'td':
|
case 'td':
|
||||||
case 'tfoot':
|
case 'tfoot':
|
||||||
case 'th':
|
case 'th':
|
||||||
case 'thead':
|
case 'thead':
|
||||||
case 'tr':
|
case 'tr':
|
||||||
// These tags are only valid with a few parents that have special child
|
// These tags are only valid with a few parents that have special child
|
||||||
// parsing rules -- if we're down here, then none of those matched and
|
// parsing rules -- if we're down here, then none of those matched and
|
||||||
// so we allow it only if we don't know what the parent is, as all other
|
// so we allow it only if we don't know what the parent is, as all other
|
||||||
// cases are invalid.
|
// cases are invalid.
|
||||||
return parentTag == null;
|
return parentTag == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether
|
* Returns whether
|
||||||
*/
|
*/
|
||||||
const findInvalidAncestorForTag = function (
|
function findInvalidAncestorForTag(
|
||||||
tag: string,
|
tag: string,
|
||||||
ancestorInfo: AncestorInfoDev,
|
ancestorInfo: AncestorInfoDev,
|
||||||
): ?Info {
|
): ?Info {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case 'address':
|
case 'address':
|
||||||
case 'article':
|
case 'article':
|
||||||
case 'aside':
|
case 'aside':
|
||||||
case 'blockquote':
|
case 'blockquote':
|
||||||
case 'center':
|
case 'center':
|
||||||
case 'details':
|
case 'details':
|
||||||
case 'dialog':
|
case 'dialog':
|
||||||
case 'dir':
|
case 'dir':
|
||||||
case 'div':
|
case 'div':
|
||||||
case 'dl':
|
case 'dl':
|
||||||
case 'fieldset':
|
case 'fieldset':
|
||||||
case 'figcaption':
|
case 'figcaption':
|
||||||
case 'figure':
|
case 'figure':
|
||||||
case 'footer':
|
case 'footer':
|
||||||
case 'header':
|
case 'header':
|
||||||
case 'hgroup':
|
case 'hgroup':
|
||||||
case 'main':
|
case 'main':
|
||||||
case 'menu':
|
case 'menu':
|
||||||
case 'nav':
|
case 'nav':
|
||||||
case 'ol':
|
case 'ol':
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'section':
|
case 'section':
|
||||||
case 'summary':
|
case 'summary':
|
||||||
case 'ul':
|
case 'ul':
|
||||||
case 'pre':
|
case 'pre':
|
||||||
case 'listing':
|
case 'listing':
|
||||||
case 'table':
|
case 'table':
|
||||||
case 'hr':
|
case 'hr':
|
||||||
case 'xmp':
|
case 'xmp':
|
||||||
case 'h1':
|
case 'h1':
|
||||||
case 'h2':
|
case 'h2':
|
||||||
case 'h3':
|
case 'h3':
|
||||||
case 'h4':
|
case 'h4':
|
||||||
case 'h5':
|
case 'h5':
|
||||||
case 'h6':
|
case 'h6':
|
||||||
return ancestorInfo.pTagInButtonScope;
|
return ancestorInfo.pTagInButtonScope;
|
||||||
|
|
||||||
case 'form':
|
case 'form':
|
||||||
return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
|
return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
|
||||||
|
|
||||||
case 'li':
|
case 'li':
|
||||||
return ancestorInfo.listItemTagAutoclosing;
|
return ancestorInfo.listItemTagAutoclosing;
|
||||||
|
|
||||||
case 'dd':
|
case 'dd':
|
||||||
case 'dt':
|
case 'dt':
|
||||||
return ancestorInfo.dlItemTagAutoclosing;
|
return ancestorInfo.dlItemTagAutoclosing;
|
||||||
|
|
||||||
case 'button':
|
case 'button':
|
||||||
return ancestorInfo.buttonTagInScope;
|
return ancestorInfo.buttonTagInScope;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
// Spec says something about storing a list of markers, but it sounds
|
// Spec says something about storing a list of markers, but it sounds
|
||||||
// equivalent to this check.
|
// equivalent to this check.
|
||||||
return ancestorInfo.aTagInScope;
|
return ancestorInfo.aTagInScope;
|
||||||
|
|
||||||
case 'nobr':
|
case 'nobr':
|
||||||
return ancestorInfo.nobrTagInScope;
|
return ancestorInfo.nobrTagInScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
|
|
||||||
const didWarn: {[string]: boolean} = {};
|
const didWarn: {[string]: boolean} = {};
|
||||||
|
|
||||||
validateDOMNesting = function (
|
function validateDOMNesting(
|
||||||
childTag: ?string,
|
childTag: ?string,
|
||||||
childText: ?string,
|
childText: ?string,
|
||||||
ancestorInfo: AncestorInfoDev,
|
ancestorInfo: AncestorInfoDev,
|
||||||
) {
|
): void {
|
||||||
|
if (__DEV__) {
|
||||||
ancestorInfo = ancestorInfo || emptyAncestorInfoDev;
|
ancestorInfo = ancestorInfo || emptyAncestorInfoDev;
|
||||||
const parentInfo = ancestorInfo.current;
|
const parentInfo = ancestorInfo.current;
|
||||||
const parentTag = parentInfo && parentInfo.tag;
|
const parentTag = parentInfo && parentInfo.tag;
|
||||||
|
|
@ -517,7 +515,7 @@ if (__DEV__) {
|
||||||
ancestorTag,
|
ancestorTag,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {updatedAncestorInfoDev, validateDOMNesting};
|
export {updatedAncestorInfoDev, validateDOMNesting};
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,18 @@ import isCustomComponent from './isCustomComponent';
|
||||||
import possibleStandardNames from './possibleStandardNames';
|
import possibleStandardNames from './possibleStandardNames';
|
||||||
import hasOwnProperty from 'shared/hasOwnProperty';
|
import hasOwnProperty from 'shared/hasOwnProperty';
|
||||||
|
|
||||||
let validateProperty = () => {};
|
const warnedProperties = {};
|
||||||
|
const EVENT_NAME_REGEX = /^on./;
|
||||||
|
const INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;
|
||||||
|
const rARIA = __DEV__
|
||||||
|
? new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$')
|
||||||
|
: null;
|
||||||
|
const rARIACamel = __DEV__
|
||||||
|
? new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$')
|
||||||
|
: null;
|
||||||
|
|
||||||
if (__DEV__) {
|
function validateProperty(tagName, name, value, eventRegistry) {
|
||||||
const warnedProperties = {};
|
if (__DEV__) {
|
||||||
const EVENT_NAME_REGEX = /^on./;
|
|
||||||
const INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;
|
|
||||||
const rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
|
|
||||||
const rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
|
|
||||||
|
|
||||||
validateProperty = function (tagName, name, value, eventRegistry) {
|
|
||||||
if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {
|
if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -234,10 +236,10 @@ if (__DEV__) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const warnUnknownProperties = function (type, props, eventRegistry) {
|
function warnUnknownProperties(type, props, eventRegistry) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
const unknownProps = [];
|
const unknownProps = [];
|
||||||
for (const key in props) {
|
for (const key in props) {
|
||||||
|
|
@ -268,7 +270,7 @@ const warnUnknownProperties = function (type, props, eventRegistry) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export function validateProperties(type, props, eventRegistry) {
|
export function validateProperties(type, props, eventRegistry) {
|
||||||
if (isCustomComponent(type, props)) {
|
if (isCustomComponent(type, props)) {
|
||||||
|
|
|
||||||
|
|
@ -5,29 +5,27 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let warnValidStyle = () => {};
|
// 'msTransform' is correct, but the other prefixes should be capitalized
|
||||||
|
const badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
|
||||||
|
const msPattern = /^-ms-/;
|
||||||
|
const hyphenPattern = /-(.)/g;
|
||||||
|
|
||||||
if (__DEV__) {
|
// style values shouldn't contain a semicolon
|
||||||
// 'msTransform' is correct, but the other prefixes should be capitalized
|
const badStyleValueWithSemicolonPattern = /;\s*$/;
|
||||||
const badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
|
|
||||||
const msPattern = /^-ms-/;
|
|
||||||
const hyphenPattern = /-(.)/g;
|
|
||||||
|
|
||||||
// style values shouldn't contain a semicolon
|
const warnedStyleNames = {};
|
||||||
const badStyleValueWithSemicolonPattern = /;\s*$/;
|
const warnedStyleValues = {};
|
||||||
|
let warnedForNaNValue = false;
|
||||||
|
let warnedForInfinityValue = false;
|
||||||
|
|
||||||
const warnedStyleNames = {};
|
function camelize(string) {
|
||||||
const warnedStyleValues = {};
|
return string.replace(hyphenPattern, function (_, character) {
|
||||||
let warnedForNaNValue = false;
|
return character.toUpperCase();
|
||||||
let warnedForInfinityValue = false;
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const camelize = function (string) {
|
function warnHyphenatedStyleName(name) {
|
||||||
return string.replace(hyphenPattern, function (_, character) {
|
if (__DEV__) {
|
||||||
return character.toUpperCase();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const warnHyphenatedStyleName = function (name) {
|
|
||||||
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
|
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -41,9 +39,11 @@ if (__DEV__) {
|
||||||
// is converted to lowercase `ms`.
|
// is converted to lowercase `ms`.
|
||||||
camelize(name.replace(msPattern, 'ms-')),
|
camelize(name.replace(msPattern, 'ms-')),
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const warnBadVendoredStyleName = function (name) {
|
function warnBadVendoredStyleName(name) {
|
||||||
|
if (__DEV__) {
|
||||||
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
|
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -54,9 +54,11 @@ if (__DEV__) {
|
||||||
name,
|
name,
|
||||||
name.charAt(0).toUpperCase() + name.slice(1),
|
name.charAt(0).toUpperCase() + name.slice(1),
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const warnStyleValueWithSemicolon = function (name, value) {
|
function warnStyleValueWithSemicolon(name, value) {
|
||||||
|
if (__DEV__) {
|
||||||
if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
|
if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -68,9 +70,11 @@ if (__DEV__) {
|
||||||
name,
|
name,
|
||||||
value.replace(badStyleValueWithSemicolonPattern, ''),
|
value.replace(badStyleValueWithSemicolonPattern, ''),
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const warnStyleValueIsNaN = function (name, value) {
|
function warnStyleValueIsNaN(name, value) {
|
||||||
|
if (__DEV__) {
|
||||||
if (warnedForNaNValue) {
|
if (warnedForNaNValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -80,9 +84,11 @@ if (__DEV__) {
|
||||||
'`NaN` is an invalid value for the `%s` css style property.',
|
'`NaN` is an invalid value for the `%s` css style property.',
|
||||||
name,
|
name,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const warnStyleValueIsInfinity = function (name, value) {
|
function warnStyleValueIsInfinity(name, value) {
|
||||||
|
if (__DEV__) {
|
||||||
if (warnedForInfinityValue) {
|
if (warnedForInfinityValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -92,9 +98,11 @@ if (__DEV__) {
|
||||||
'`Infinity` is an invalid value for the `%s` css style property.',
|
'`Infinity` is an invalid value for the `%s` css style property.',
|
||||||
name,
|
name,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
warnValidStyle = function (name, value) {
|
function warnValidStyle(name, value) {
|
||||||
|
if (__DEV__) {
|
||||||
if (name.indexOf('-') > -1) {
|
if (name.indexOf('-') > -1) {
|
||||||
warnHyphenatedStyleName(name);
|
warnHyphenatedStyleName(name);
|
||||||
} else if (badVendoredStyleNamePattern.test(name)) {
|
} else if (badVendoredStyleNamePattern.test(name)) {
|
||||||
|
|
@ -110,7 +118,7 @@ if (__DEV__) {
|
||||||
warnStyleValueIsInfinity(name, value);
|
warnStyleValueIsInfinity(name, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default warnValidStyle;
|
export default warnValidStyle;
|
||||||
|
|
|
||||||
|
|
@ -392,7 +392,7 @@ function executeDispatchesInOrder(event) {
|
||||||
* @param {?object} event Synthetic event to be dispatched.
|
* @param {?object} event Synthetic event to be dispatched.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const executeDispatchesAndRelease = function (event /* ReactSyntheticEvent */) {
|
function executeDispatchesAndRelease(event /* ReactSyntheticEvent */) {
|
||||||
if (event) {
|
if (event) {
|
||||||
executeDispatchesInOrder(event);
|
executeDispatchesInOrder(event);
|
||||||
|
|
||||||
|
|
@ -400,7 +400,7 @@ const executeDispatchesAndRelease = function (event /* ReactSyntheticEvent */) {
|
||||||
event.constructor.release(event);
|
event.constructor.release(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function isInteractive(tag) {
|
function isInteractive(tag) {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,13 @@ const EMPTY_NATIVE_EVENT = (({}: any): AnyNativeEvent);
|
||||||
* @return {Array<Touch>} Subsequence of touch objects.
|
* @return {Array<Touch>} Subsequence of touch objects.
|
||||||
*/
|
*/
|
||||||
// $FlowFixMe[missing-local-annot]
|
// $FlowFixMe[missing-local-annot]
|
||||||
const touchSubsequence = function (touches, indices) {
|
function touchSubsequence(touches, indices) {
|
||||||
const ret = [];
|
const ret = [];
|
||||||
for (let i = 0; i < indices.length; i++) {
|
for (let i = 0; i < indices.length; i++) {
|
||||||
ret.push(touches[indices[i]]);
|
ret.push(touches[indices[i]]);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Pool all of this.
|
* TODO: Pool all of this.
|
||||||
|
|
@ -63,7 +63,7 @@ const touchSubsequence = function (touches, indices) {
|
||||||
* @param {Array<number>} indices Indices to remove from `touches`.
|
* @param {Array<number>} indices Indices to remove from `touches`.
|
||||||
* @return {Array<Touch>} Subsequence of removed touch objects.
|
* @return {Array<Touch>} Subsequence of removed touch objects.
|
||||||
*/
|
*/
|
||||||
const removeTouchesAtIndices = function (
|
function removeTouchesAtIndices(
|
||||||
touches: Array<Object>,
|
touches: Array<Object>,
|
||||||
indices: Array<number>,
|
indices: Array<number>,
|
||||||
): Array<Object> {
|
): Array<Object> {
|
||||||
|
|
@ -85,7 +85,7 @@ const removeTouchesAtIndices = function (
|
||||||
}
|
}
|
||||||
temp.length = fillAt;
|
temp.length = fillAt;
|
||||||
return rippedOut;
|
return rippedOut;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal version of `receiveEvent` in terms of normalized (non-tag)
|
* Internal version of `receiveEvent` in terms of normalized (non-tag)
|
||||||
|
|
|
||||||
|
|
@ -28,49 +28,39 @@ if (__DEV__) {
|
||||||
Object.freeze(emptyObject);
|
Object.freeze(emptyObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
let createHierarchy;
|
// $FlowFixMe[missing-local-annot]
|
||||||
let getHostNode;
|
function createHierarchy(fiberHierarchy) {
|
||||||
let getHostProps;
|
return fiberHierarchy.map(fiber => ({
|
||||||
let lastNonHostInstance;
|
name: getComponentNameFromType(fiber.type),
|
||||||
let getInspectorDataForInstance: (
|
getInspectorData: findNodeHandle => {
|
||||||
closestInstance: Fiber | null,
|
return {
|
||||||
) => InspectorData;
|
props: getHostProps(fiber),
|
||||||
let getOwnerHierarchy;
|
source: fiber._debugSource,
|
||||||
let traverseOwnerTreeUp: (hierarchy: Array<$FlowFixMe>, instance: any) => void;
|
measure: callback => {
|
||||||
|
// If this is Fabric, we'll find a shadow node and use that to measure.
|
||||||
|
const hostFiber = findCurrentHostFiber(fiber);
|
||||||
|
const node =
|
||||||
|
hostFiber != null &&
|
||||||
|
hostFiber.stateNode !== null &&
|
||||||
|
hostFiber.stateNode.node;
|
||||||
|
|
||||||
if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
|
if (node) {
|
||||||
// $FlowFixMe[missing-local-annot]
|
nativeFabricUIManager.measure(node, callback);
|
||||||
createHierarchy = function (fiberHierarchy) {
|
} else {
|
||||||
return fiberHierarchy.map(fiber => ({
|
return UIManager.measure(
|
||||||
name: getComponentNameFromType(fiber.type),
|
getHostNode(fiber, findNodeHandle),
|
||||||
getInspectorData: findNodeHandle => {
|
callback,
|
||||||
return {
|
);
|
||||||
props: getHostProps(fiber),
|
}
|
||||||
source: fiber._debugSource,
|
},
|
||||||
measure: callback => {
|
};
|
||||||
// If this is Fabric, we'll find a shadow node and use that to measure.
|
},
|
||||||
const hostFiber = findCurrentHostFiber(fiber);
|
}));
|
||||||
const node =
|
}
|
||||||
hostFiber != null &&
|
|
||||||
hostFiber.stateNode !== null &&
|
|
||||||
hostFiber.stateNode.node;
|
|
||||||
|
|
||||||
if (node) {
|
// $FlowFixMe[missing-local-annot]
|
||||||
nativeFabricUIManager.measure(node, callback);
|
function getHostNode(fiber: Fiber | null, findNodeHandle) {
|
||||||
} else {
|
if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
|
||||||
return UIManager.measure(
|
|
||||||
getHostNode(fiber, findNodeHandle),
|
|
||||||
callback,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
// $FlowFixMe[missing-local-annot]
|
|
||||||
getHostNode = function (fiber: Fiber | null, findNodeHandle) {
|
|
||||||
let hostNode;
|
let hostNode;
|
||||||
// look for children first for the hostNode
|
// look for children first for the hostNode
|
||||||
// as composite fibers do not have a hostNode
|
// as composite fibers do not have a hostNode
|
||||||
|
|
@ -84,20 +74,22 @@ if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
|
||||||
fiber = fiber.child;
|
fiber = fiber.child;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// $FlowFixMe[missing-local-annot]
|
// $FlowFixMe[missing-local-annot]
|
||||||
getHostProps = function (fiber) {
|
function getHostProps(fiber) {
|
||||||
const host = findCurrentHostFiber(fiber);
|
const host = findCurrentHostFiber(fiber);
|
||||||
if (host) {
|
if (host) {
|
||||||
return host.memoizedProps || emptyObject;
|
return host.memoizedProps || emptyObject;
|
||||||
}
|
}
|
||||||
return emptyObject;
|
return emptyObject;
|
||||||
};
|
}
|
||||||
|
|
||||||
getInspectorDataForInstance = function (
|
function getInspectorDataForInstance(
|
||||||
closestInstance: Fiber | null,
|
closestInstance: Fiber | null,
|
||||||
): InspectorData {
|
): InspectorData {
|
||||||
|
if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
|
||||||
// Handle case where user clicks outside of ReactNative
|
// Handle case where user clicks outside of ReactNative
|
||||||
if (!closestInstance) {
|
if (!closestInstance) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -123,46 +115,44 @@ if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
source,
|
source,
|
||||||
};
|
};
|
||||||
};
|
} else {
|
||||||
|
return (null: any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getOwnerHierarchy = function (instance: any) {
|
function getOwnerHierarchy(instance: any) {
|
||||||
const hierarchy: Array<$FlowFixMe> = [];
|
const hierarchy: Array<$FlowFixMe> = [];
|
||||||
traverseOwnerTreeUp(hierarchy, instance);
|
traverseOwnerTreeUp(hierarchy, instance);
|
||||||
return hierarchy;
|
return hierarchy;
|
||||||
};
|
}
|
||||||
|
|
||||||
// $FlowFixMe[missing-local-annot]
|
// $FlowFixMe[missing-local-annot]
|
||||||
lastNonHostInstance = function (hierarchy) {
|
function lastNonHostInstance(hierarchy) {
|
||||||
for (let i = hierarchy.length - 1; i > 1; i--) {
|
for (let i = hierarchy.length - 1; i > 1; i--) {
|
||||||
const instance = hierarchy[i];
|
const instance = hierarchy[i];
|
||||||
|
|
||||||
if (instance.tag !== HostComponent) {
|
if (instance.tag !== HostComponent) {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return hierarchy[0];
|
}
|
||||||
};
|
return hierarchy[0];
|
||||||
|
}
|
||||||
|
|
||||||
// $FlowFixMe[missing-local-annot]
|
// $FlowFixMe[missing-local-annot]
|
||||||
traverseOwnerTreeUp = function (hierarchy, instance: any): void {
|
function traverseOwnerTreeUp(
|
||||||
|
hierarchy: Array<$FlowFixMe>,
|
||||||
|
instance: any,
|
||||||
|
): void {
|
||||||
|
if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
|
||||||
if (instance) {
|
if (instance) {
|
||||||
hierarchy.unshift(instance);
|
hierarchy.unshift(instance);
|
||||||
traverseOwnerTreeUp(hierarchy, instance._debugOwner);
|
traverseOwnerTreeUp(hierarchy, instance._debugOwner);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let getInspectorDataForViewTag: (viewTag: number) => Object;
|
function getInspectorDataForViewTag(viewTag: number): Object {
|
||||||
let getInspectorDataForViewAtPoint: (
|
if (__DEV__) {
|
||||||
findNodeHandle: (componentOrHandle: any) => ?number,
|
|
||||||
inspectedView: Object,
|
|
||||||
locationX: number,
|
|
||||||
locationY: number,
|
|
||||||
callback: (viewData: TouchedViewDataAtPoint) => mixed,
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
if (__DEV__) {
|
|
||||||
getInspectorDataForViewTag = function (viewTag: number): Object {
|
|
||||||
const closestInstance = getClosestInstanceFromNode(viewTag);
|
const closestInstance = getClosestInstanceFromNode(viewTag);
|
||||||
|
|
||||||
// Handle case where user clicks outside of ReactNative
|
// Handle case where user clicks outside of ReactNative
|
||||||
|
|
@ -189,15 +179,21 @@ if (__DEV__) {
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
source,
|
source,
|
||||||
};
|
};
|
||||||
};
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
'getInspectorDataForViewTag() is not available in production',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getInspectorDataForViewAtPoint = function (
|
function getInspectorDataForViewAtPoint(
|
||||||
findNodeHandle: (componentOrHandle: any) => ?number,
|
findNodeHandle: (componentOrHandle: any) => ?number,
|
||||||
inspectedView: Object,
|
inspectedView: Object,
|
||||||
locationX: number,
|
locationX: number,
|
||||||
locationY: number,
|
locationY: number,
|
||||||
callback: (viewData: TouchedViewDataAtPoint) => mixed,
|
callback: (viewData: TouchedViewDataAtPoint) => mixed,
|
||||||
): void {
|
): void {
|
||||||
|
if (__DEV__) {
|
||||||
let closestInstance = null;
|
let closestInstance = null;
|
||||||
|
|
||||||
const fabricInstanceHandle =
|
const fabricInstanceHandle =
|
||||||
|
|
@ -271,25 +267,11 @@ if (__DEV__) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
} else {
|
|
||||||
getInspectorDataForViewTag = () => {
|
|
||||||
throw new Error(
|
|
||||||
'getInspectorDataForViewTag() is not available in production',
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
getInspectorDataForViewAtPoint = (
|
|
||||||
findNodeHandle: (componentOrHandle: any) => ?number,
|
|
||||||
inspectedView: Object,
|
|
||||||
locationX: number,
|
|
||||||
locationY: number,
|
|
||||||
callback: (viewData: TouchedViewDataAtPoint) => mixed,
|
|
||||||
): void => {
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'getInspectorDataForViewAtPoint() is not available in production.',
|
'getInspectorDataForViewAtPoint() is not available in production.',
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type Options = {+unsafelyIgnoreFunctions?: boolean};
|
||||||
/*
|
/*
|
||||||
* @returns {bool} true if different, false if equal
|
* @returns {bool} true if different, false if equal
|
||||||
*/
|
*/
|
||||||
const deepDiffer = function (
|
function deepDiffer(
|
||||||
one: any,
|
one: any,
|
||||||
two: any,
|
two: any,
|
||||||
maxDepthOrOptions: Options | number = -1,
|
maxDepthOrOptions: Options | number = -1,
|
||||||
|
|
@ -79,6 +79,6 @@ const deepDiffer = function (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = deepDiffer;
|
module.exports = deepDiffer;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,6 @@
|
||||||
|
|
||||||
// TODO: move into react or fbjs
|
// TODO: move into react or fbjs
|
||||||
|
|
||||||
const deepFreezeAndThrowOnMutationInDev = function () {};
|
function deepFreezeAndThrowOnMutationInDev() {}
|
||||||
|
|
||||||
module.exports = deepFreezeAndThrowOnMutationInDev;
|
module.exports = deepFreezeAndThrowOnMutationInDev;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,6 @@
|
||||||
|
|
||||||
// TODO: Move flattenStyle into react
|
// TODO: Move flattenStyle into react
|
||||||
|
|
||||||
const flattenStyle = function () {};
|
function flattenStyle() {}
|
||||||
|
|
||||||
module.exports = flattenStyle;
|
module.exports = flattenStyle;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ let eventQueue: ?(Array<ReactSyntheticEvent> | ReactSyntheticEvent) = null;
|
||||||
* @param {?object} event Synthetic event to be dispatched.
|
* @param {?object} event Synthetic event to be dispatched.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const executeDispatchesAndRelease = function (event: ReactSyntheticEvent) {
|
function executeDispatchesAndRelease(event: ReactSyntheticEvent) {
|
||||||
if (event) {
|
if (event) {
|
||||||
executeDispatchesInOrder(event);
|
executeDispatchesInOrder(event);
|
||||||
|
|
||||||
|
|
@ -33,11 +33,11 @@ const executeDispatchesAndRelease = function (event: ReactSyntheticEvent) {
|
||||||
event.constructor.release(event);
|
event.constructor.release(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
// $FlowFixMe[missing-local-annot]
|
// $FlowFixMe[missing-local-annot]
|
||||||
const executeDispatchesAndReleaseTopLevel = function (e) {
|
function executeDispatchesAndReleaseTopLevel(e) {
|
||||||
return executeDispatchesAndRelease(e);
|
return executeDispatchesAndRelease(e);
|
||||||
};
|
}
|
||||||
|
|
||||||
export function runEventsInBatch(
|
export function runEventsInBatch(
|
||||||
events: Array<ReactSyntheticEvent> | ReactSyntheticEvent | null,
|
events: Array<ReactSyntheticEvent> | ReactSyntheticEvent | null,
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,8 @@ export function setComponentTree(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let validateEventDispatches;
|
function validateEventDispatches(event) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
validateEventDispatches = function (event) {
|
|
||||||
const dispatchListeners = event._dispatchListeners;
|
const dispatchListeners = event._dispatchListeners;
|
||||||
const dispatchInstances = event._dispatchInstances;
|
const dispatchInstances = event._dispatchInstances;
|
||||||
|
|
||||||
|
|
@ -53,7 +52,7 @@ if (__DEV__) {
|
||||||
if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) {
|
if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) {
|
||||||
console.error('EventPluginUtils: Invalid `event`.');
|
console.error('EventPluginUtils: Invalid `event`.');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ let responderInst = null;
|
||||||
*/
|
*/
|
||||||
let trackedTouchCount = 0;
|
let trackedTouchCount = 0;
|
||||||
|
|
||||||
const changeResponder = function (nextResponderInst, blockHostResponder) {
|
function changeResponder(nextResponderInst, blockHostResponder) {
|
||||||
const oldResponderInst = responderInst;
|
const oldResponderInst = responderInst;
|
||||||
responderInst = nextResponderInst;
|
responderInst = nextResponderInst;
|
||||||
if (ResponderEventPlugin.GlobalResponderHandler !== null) {
|
if (ResponderEventPlugin.GlobalResponderHandler !== null) {
|
||||||
|
|
@ -54,7 +54,7 @@ const changeResponder = function (nextResponderInst, blockHostResponder) {
|
||||||
blockHostResponder,
|
blockHostResponder,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const eventTypes = {
|
const eventTypes = {
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
4
packages/react-reconciler/src/ReactFiber.js
vendored
4
packages/react-reconciler/src/ReactFiber.js
vendored
|
|
@ -224,7 +224,7 @@ function FiberNode(
|
||||||
// is faster.
|
// is faster.
|
||||||
// 5) It should be easy to port this to a C struct and keep a C implementation
|
// 5) It should be easy to port this to a C struct and keep a C implementation
|
||||||
// compatible.
|
// compatible.
|
||||||
const createFiber = function (
|
function createFiber(
|
||||||
tag: WorkTag,
|
tag: WorkTag,
|
||||||
pendingProps: mixed,
|
pendingProps: mixed,
|
||||||
key: null | string,
|
key: null | string,
|
||||||
|
|
@ -232,7 +232,7 @@ const createFiber = function (
|
||||||
): Fiber {
|
): Fiber {
|
||||||
// $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
|
// $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
|
||||||
return new FiberNode(tag, pendingProps, key, mode);
|
return new FiberNode(tag, pendingProps, key, mode);
|
||||||
};
|
}
|
||||||
|
|
||||||
function shouldConstruct(Component: Function) {
|
function shouldConstruct(Component: Function) {
|
||||||
const prototype = Component.prototype;
|
const prototype = Component.prototype;
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,10 @@ let didWarnAboutUninitializedState;
|
||||||
let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
|
let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
|
||||||
let didWarnAboutLegacyLifecyclesAndDerivedState;
|
let didWarnAboutLegacyLifecyclesAndDerivedState;
|
||||||
let didWarnAboutUndefinedDerivedState;
|
let didWarnAboutUndefinedDerivedState;
|
||||||
let warnOnUndefinedDerivedState;
|
|
||||||
let warnOnInvalidCallback;
|
|
||||||
let didWarnAboutDirectlyAssigningPropsToState;
|
let didWarnAboutDirectlyAssigningPropsToState;
|
||||||
let didWarnAboutContextTypeAndContextTypes;
|
let didWarnAboutContextTypeAndContextTypes;
|
||||||
let didWarnAboutInvalidateContextType;
|
let didWarnAboutInvalidateContextType;
|
||||||
|
let didWarnOnInvalidCallback;
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
didWarnAboutStateAssignmentForComponent = new Set<string>();
|
didWarnAboutStateAssignmentForComponent = new Set<string>();
|
||||||
|
|
@ -100,38 +99,7 @@ if (__DEV__) {
|
||||||
didWarnAboutUndefinedDerivedState = new Set<string>();
|
didWarnAboutUndefinedDerivedState = new Set<string>();
|
||||||
didWarnAboutContextTypeAndContextTypes = new Set<string>();
|
didWarnAboutContextTypeAndContextTypes = new Set<string>();
|
||||||
didWarnAboutInvalidateContextType = new Set<string>();
|
didWarnAboutInvalidateContextType = new Set<string>();
|
||||||
|
didWarnOnInvalidCallback = new Set<string>();
|
||||||
const didWarnOnInvalidCallback = new Set<string>();
|
|
||||||
|
|
||||||
warnOnInvalidCallback = function (callback: mixed, callerName: string) {
|
|
||||||
if (callback === null || typeof callback === 'function') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const key = callerName + '_' + (callback: any);
|
|
||||||
if (!didWarnOnInvalidCallback.has(key)) {
|
|
||||||
didWarnOnInvalidCallback.add(key);
|
|
||||||
console.error(
|
|
||||||
'%s(...): Expected the last optional `callback` argument to be a ' +
|
|
||||||
'function. Instead received: %s.',
|
|
||||||
callerName,
|
|
||||||
callback,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
warnOnUndefinedDerivedState = function (type: any, partialState: any) {
|
|
||||||
if (partialState === undefined) {
|
|
||||||
const componentName = getComponentNameFromType(type) || 'Component';
|
|
||||||
if (!didWarnAboutUndefinedDerivedState.has(componentName)) {
|
|
||||||
didWarnAboutUndefinedDerivedState.add(componentName);
|
|
||||||
console.error(
|
|
||||||
'%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' +
|
|
||||||
'You have returned undefined.',
|
|
||||||
componentName,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is so gross but it's at least non-critical and can be removed if
|
// This is so gross but it's at least non-critical and can be removed if
|
||||||
// it causes problems. This is meant to give a nicer error message for
|
// it causes problems. This is meant to give a nicer error message for
|
||||||
|
|
@ -154,6 +122,40 @@ if (__DEV__) {
|
||||||
Object.freeze(fakeInternalInstance);
|
Object.freeze(fakeInternalInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function warnOnInvalidCallback(callback: mixed, callerName: string) {
|
||||||
|
if (__DEV__) {
|
||||||
|
if (callback === null || typeof callback === 'function') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const key = callerName + '_' + (callback: any);
|
||||||
|
if (!didWarnOnInvalidCallback.has(key)) {
|
||||||
|
didWarnOnInvalidCallback.add(key);
|
||||||
|
console.error(
|
||||||
|
'%s(...): Expected the last optional `callback` argument to be a ' +
|
||||||
|
'function. Instead received: %s.',
|
||||||
|
callerName,
|
||||||
|
callback,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function warnOnUndefinedDerivedState(type: any, partialState: any) {
|
||||||
|
if (__DEV__) {
|
||||||
|
if (partialState === undefined) {
|
||||||
|
const componentName = getComponentNameFromType(type) || 'Component';
|
||||||
|
if (!didWarnAboutUndefinedDerivedState.has(componentName)) {
|
||||||
|
didWarnAboutUndefinedDerivedState.add(componentName);
|
||||||
|
console.error(
|
||||||
|
'%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' +
|
||||||
|
'You have returned undefined.',
|
||||||
|
componentName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function applyDerivedStateFromProps(
|
function applyDerivedStateFromProps(
|
||||||
workInProgress: Fiber,
|
workInProgress: Fiber,
|
||||||
ctor: any,
|
ctor: any,
|
||||||
|
|
|
||||||
|
|
@ -253,10 +253,7 @@ export function reportUncaughtErrorInDEV(error: mixed) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const callComponentWillUnmountWithTimer = function (
|
function callComponentWillUnmountWithTimer(current: Fiber, instance: any) {
|
||||||
current: Fiber,
|
|
||||||
instance: any,
|
|
||||||
) {
|
|
||||||
instance.props = current.memoizedProps;
|
instance.props = current.memoizedProps;
|
||||||
instance.state = current.memoizedState;
|
instance.state = current.memoizedState;
|
||||||
if (shouldProfile(current)) {
|
if (shouldProfile(current)) {
|
||||||
|
|
@ -269,7 +266,7 @@ const callComponentWillUnmountWithTimer = function (
|
||||||
} else {
|
} else {
|
||||||
instance.componentWillUnmount();
|
instance.componentWillUnmount();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Capture errors so they don't interrupt unmounting.
|
// Capture errors so they don't interrupt unmounting.
|
||||||
function safelyCallComponentWillUnmount(
|
function safelyCallComponentWillUnmount(
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,10 @@ let didWarnAboutUninitializedState;
|
||||||
let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
|
let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
|
||||||
let didWarnAboutLegacyLifecyclesAndDerivedState;
|
let didWarnAboutLegacyLifecyclesAndDerivedState;
|
||||||
let didWarnAboutUndefinedDerivedState;
|
let didWarnAboutUndefinedDerivedState;
|
||||||
let warnOnUndefinedDerivedState;
|
|
||||||
let warnOnInvalidCallback;
|
|
||||||
let didWarnAboutDirectlyAssigningPropsToState;
|
let didWarnAboutDirectlyAssigningPropsToState;
|
||||||
let didWarnAboutContextTypeAndContextTypes;
|
let didWarnAboutContextTypeAndContextTypes;
|
||||||
let didWarnAboutInvalidateContextType;
|
let didWarnAboutInvalidateContextType;
|
||||||
|
let didWarnOnInvalidCallback;
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
didWarnAboutUninitializedState = new Set<string>();
|
didWarnAboutUninitializedState = new Set<string>();
|
||||||
|
|
@ -38,10 +37,11 @@ if (__DEV__) {
|
||||||
didWarnAboutUndefinedDerivedState = new Set<string>();
|
didWarnAboutUndefinedDerivedState = new Set<string>();
|
||||||
didWarnAboutContextTypeAndContextTypes = new Set<mixed>();
|
didWarnAboutContextTypeAndContextTypes = new Set<mixed>();
|
||||||
didWarnAboutInvalidateContextType = new Set<mixed>();
|
didWarnAboutInvalidateContextType = new Set<mixed>();
|
||||||
|
didWarnOnInvalidCallback = new Set<string>();
|
||||||
|
}
|
||||||
|
|
||||||
const didWarnOnInvalidCallback = new Set<string>();
|
function warnOnInvalidCallback(callback: mixed, callerName: string) {
|
||||||
|
if (__DEV__) {
|
||||||
warnOnInvalidCallback = function (callback: mixed, callerName: string) {
|
|
||||||
if (callback === null || typeof callback === 'function') {
|
if (callback === null || typeof callback === 'function') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -55,9 +55,11 @@ if (__DEV__) {
|
||||||
callback,
|
callback,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
warnOnUndefinedDerivedState = function (type: any, partialState: any) {
|
function warnOnUndefinedDerivedState(type: any, partialState: any) {
|
||||||
|
if (__DEV__) {
|
||||||
if (partialState === undefined) {
|
if (partialState === undefined) {
|
||||||
const componentName = getComponentNameFromType(type) || 'Component';
|
const componentName = getComponentNameFromType(type) || 'Component';
|
||||||
if (!didWarnAboutUndefinedDerivedState.has(componentName)) {
|
if (!didWarnAboutUndefinedDerivedState.has(componentName)) {
|
||||||
|
|
@ -69,7 +71,7 @@ if (__DEV__) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function warnNoop(
|
function warnNoop(
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ function warnIfStringRefCannotBeAutoConverted(config) {
|
||||||
* indicating filename, line number, and/or other information.
|
* indicating filename, line number, and/or other information.
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
const ReactElement = function (type, key, ref, self, source, owner, props) {
|
function ReactElement(type, key, ref, self, source, owner, props) {
|
||||||
const element = {
|
const element = {
|
||||||
// This tag allows us to uniquely identify this as a React Element
|
// This tag allows us to uniquely identify this as a React Element
|
||||||
$$typeof: REACT_ELEMENT_TYPE,
|
$$typeof: REACT_ELEMENT_TYPE,
|
||||||
|
|
@ -199,7 +199,7 @@ const ReactElement = function (type, key, ref, self, source, owner, props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/reactjs/rfcs/pull/107
|
* https://github.com/reactjs/rfcs/pull/107
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ function defineRefPropWarningGetter(props, displayName) {
|
||||||
* indicating filename, line number, and/or other information.
|
* indicating filename, line number, and/or other information.
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
const ReactElement = function (type, key, ref, self, source, owner, props) {
|
function ReactElement(type, key, ref, self, source, owner, props) {
|
||||||
const element = {
|
const element = {
|
||||||
// This tag allows us to uniquely identify this as a React Element
|
// This tag allows us to uniquely identify this as a React Element
|
||||||
$$typeof: REACT_ELEMENT_TYPE,
|
$$typeof: REACT_ELEMENT_TYPE,
|
||||||
|
|
@ -199,7 +199,7 @@ const ReactElement = function (type, key, ref, self, source, owner, props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/reactjs/rfcs/pull/107
|
* https://github.com/reactjs/rfcs/pull/107
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ if (typeof ReactFbErrorUtils.invokeGuardedCallback !== 'function') {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const invokeGuardedCallbackImpl = function <A, B, C, D, E, F, Context>(
|
function invokeGuardedCallbackImpl<A, B, C, D, E, F, Context>(
|
||||||
name: string | null,
|
name: string | null,
|
||||||
func: (a: A, b: B, c: C, d: D, e: E, f: F) => mixed,
|
func: (a: A, b: B, c: C, d: D, e: E, f: F) => mixed,
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|
@ -29,6 +29,6 @@ const invokeGuardedCallbackImpl = function <A, B, C, D, E, F, Context>(
|
||||||
) {
|
) {
|
||||||
// This will call `this.onError(err)` if an error was caught.
|
// This will call `this.onError(err)` if an error was caught.
|
||||||
ReactFbErrorUtils.invokeGuardedCallback.apply(this, arguments);
|
ReactFbErrorUtils.invokeGuardedCallback.apply(this, arguments);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default invokeGuardedCallbackImpl;
|
export default invokeGuardedCallbackImpl;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user