2017-12-10 21:51:33 +01:00
/ * * @ l i c e n s e R e a c t v 1 6 . 2 . 0
2017-10-14 18:40:54 +02:00
* react - dom - server . browser . development . js
*
* Copyright ( c ) 2013 - present , Facebook , Inc .
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree .
* /
2017-12-10 21:51:33 +01:00
2017-10-14 18:40:54 +02:00
'use strict' ;
2017-12-10 21:51:33 +01:00
if ( process . env . NODE _ENV !== "production" ) {
( function ( ) {
2017-10-14 18:40:54 +02:00
'use strict' ;
var invariant = require ( 'fbjs/lib/invariant' ) ;
2017-12-10 21:51:33 +01:00
var _assign = require ( 'object-assign' ) ;
var React = require ( 'react' ) ;
2017-10-14 18:40:54 +02:00
var emptyFunction = require ( 'fbjs/lib/emptyFunction' ) ;
var emptyObject = require ( 'fbjs/lib/emptyObject' ) ;
var hyphenateStyleName = require ( 'fbjs/lib/hyphenateStyleName' ) ;
var memoizeStringOnly = require ( 'fbjs/lib/memoizeStringOnly' ) ;
2017-12-10 21:51:33 +01:00
var warning = require ( 'fbjs/lib/warning' ) ;
2017-10-14 18:40:54 +02:00
var checkPropTypes = require ( 'prop-types/checkPropTypes' ) ;
var camelizeStyleName = require ( 'fbjs/lib/camelizeStyleName' ) ;
/ * *
2017-12-10 21:51:33 +01:00
* WARNING : DO NOT manually require this module .
* This is a replacement for ` invariant(...) ` used by the error code system
* and will _only _ be required by the corresponding babel pass .
* It always throws .
2017-10-14 18:40:54 +02:00
* /
// These attributes should be all lowercase to allow for
// case insensitive checks
2017-12-10 21:51:33 +01:00
var RESERVED _PROPS = {
2017-10-14 18:40:54 +02:00
children : true ,
dangerouslySetInnerHTML : true ,
defaultValue : true ,
defaultChecked : true ,
innerHTML : true ,
suppressContentEditableWarning : true ,
2017-12-10 21:51:33 +01:00
suppressHydrationWarning : true ,
2017-10-14 18:40:54 +02:00
style : true
} ;
function checkMask ( value , bitmask ) {
return ( value & bitmask ) === bitmask ;
}
var DOMPropertyInjection = {
/ * *
* Mapping from normalized , camelcased property names to a configuration that
* specifies how the associated DOM property should be accessed or rendered .
* /
MUST _USE _PROPERTY : 0x1 ,
HAS _BOOLEAN _VALUE : 0x4 ,
HAS _NUMERIC _VALUE : 0x8 ,
HAS _POSITIVE _NUMERIC _VALUE : 0x10 | 0x8 ,
HAS _OVERLOADED _BOOLEAN _VALUE : 0x20 ,
HAS _STRING _BOOLEAN _VALUE : 0x40 ,
/ * *
* Inject some specialized knowledge about the DOM . This takes a config object
* with the following properties :
*
* Properties : object mapping DOM property name to one of the
* DOMPropertyInjection constants or null . If your attribute isn ' t in here ,
* it won ' t get written to the DOM .
*
* DOMAttributeNames : object mapping React attribute name to the DOM
* attribute name . Attribute names not specified use the * * lowercase * *
* normalized name .
*
* DOMAttributeNamespaces : object mapping React attribute name to the DOM
* attribute namespace URL . ( Attribute names not specified use no namespace . )
*
* DOMPropertyNames : similar to DOMAttributeNames but for DOM properties .
* Property names not specified use the normalized name .
*
* DOMMutationMethods : Properties that require special mutation methods . If
* ` value ` is undefined , the mutation method should unset the property .
*
* @ param { object } domPropertyConfig the config as described above .
* /
injectDOMPropertyConfig : function ( domPropertyConfig ) {
var Injection = DOMPropertyInjection ;
var Properties = domPropertyConfig . Properties || { } ;
var DOMAttributeNamespaces = domPropertyConfig . DOMAttributeNamespaces || { } ;
var DOMAttributeNames = domPropertyConfig . DOMAttributeNames || { } ;
var DOMMutationMethods = domPropertyConfig . DOMMutationMethods || { } ;
for ( var propName in Properties ) {
2017-12-10 21:51:33 +01:00
! ! properties . hasOwnProperty ( propName ) ? invariant ( false , "injectDOMPropertyConfig(...): You're trying to inject DOM property '%s' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names." , propName ) : void 0 ;
2017-10-14 18:40:54 +02:00
var lowerCased = propName . toLowerCase ( ) ;
var propConfig = Properties [ propName ] ;
var propertyInfo = {
attributeName : lowerCased ,
attributeNamespace : null ,
propertyName : propName ,
mutationMethod : null ,
mustUseProperty : checkMask ( propConfig , Injection . MUST _USE _PROPERTY ) ,
hasBooleanValue : checkMask ( propConfig , Injection . HAS _BOOLEAN _VALUE ) ,
hasNumericValue : checkMask ( propConfig , Injection . HAS _NUMERIC _VALUE ) ,
hasPositiveNumericValue : checkMask ( propConfig , Injection . HAS _POSITIVE _NUMERIC _VALUE ) ,
hasOverloadedBooleanValue : checkMask ( propConfig , Injection . HAS _OVERLOADED _BOOLEAN _VALUE ) ,
hasStringBooleanValue : checkMask ( propConfig , Injection . HAS _STRING _BOOLEAN _VALUE )
} ;
2017-12-10 21:51:33 +01:00
! ( propertyInfo . hasBooleanValue + propertyInfo . hasNumericValue + propertyInfo . hasOverloadedBooleanValue <= 1 ) ? invariant ( false , "DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s" , propName ) : void 0 ;
2017-10-14 18:40:54 +02:00
if ( DOMAttributeNames . hasOwnProperty ( propName ) ) {
var attributeName = DOMAttributeNames [ propName ] ;
propertyInfo . attributeName = attributeName ;
}
if ( DOMAttributeNamespaces . hasOwnProperty ( propName ) ) {
propertyInfo . attributeNamespace = DOMAttributeNamespaces [ propName ] ;
}
if ( DOMMutationMethods . hasOwnProperty ( propName ) ) {
propertyInfo . mutationMethod = DOMMutationMethods [ propName ] ;
}
// Downcase references to whitelist properties to check for membership
// without case-sensitivity. This allows the whitelist to pick up
// `allowfullscreen`, which should be written using the property configuration
// for `allowFullscreen`
2017-12-10 21:51:33 +01:00
properties [ propName ] = propertyInfo ;
2017-10-14 18:40:54 +02:00
}
}
} ;
/* eslint-disable max-len */
2017-12-10 21:51:33 +01:00
var ATTRIBUTE _NAME _START _CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD" ;
2017-10-14 18:40:54 +02:00
/* eslint-enable max-len */
2017-12-10 21:51:33 +01:00
var ATTRIBUTE _NAME _CHAR = ATTRIBUTE _NAME _START _CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040" ;
var ROOT _ATTRIBUTE _NAME = 'data-reactroot' ;
2017-10-14 18:40:54 +02:00
/ * *
2017-12-10 21:51:33 +01:00
* Map from property "standard name" to an object with info about how to set
* the property in the DOM . Each object contains :
2017-10-14 18:40:54 +02:00
*
2017-12-10 21:51:33 +01:00
* attributeName :
* Used when rendering markup or with ` *Attribute() ` .
* attributeNamespace
* propertyName :
* Used on DOM node instances . ( This includes properties that mutate due to
* external factors . )
* mutationMethod :
* If non - null , used instead of the property or ` setAttribute() ` after
* initial render .
* mustUseProperty :
* Whether the property must be accessed and mutated as an object property .
* hasBooleanValue :
* Whether the property should be removed when set to a falsey value .
* hasNumericValue :
* Whether the property must be numeric or parse as a numeric and should be
* removed when set to a falsey value .
* hasPositiveNumericValue :
* Whether the property must be positive numeric or parse as a positive
* numeric and should be removed when set to a falsey value .
* hasOverloadedBooleanValue :
* Whether the property can be used as a flag as well as with a value .
* Removed when strictly equal to false ; present without a value when
* strictly equal to true ; present with a value otherwise .
2017-10-14 18:40:54 +02:00
* /
2017-12-10 21:51:33 +01:00
var properties = { } ;
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
/ * *
* Checks whether a property name is a writeable attribute .
* @ method
* /
function shouldSetAttribute ( name , value ) {
if ( isReservedProp ( name ) ) {
return false ;
}
if ( name . length > 2 && ( name [ 0 ] === 'o' || name [ 0 ] === 'O' ) && ( name [ 1 ] === 'n' || name [ 1 ] === 'N' ) ) {
return false ;
}
if ( value === null ) {
return true ;
}
switch ( typeof value ) {
case 'boolean' :
return shouldAttributeAcceptBooleanValue ( name ) ;
case 'undefined' :
case 'number' :
case 'string' :
case 'object' :
return true ;
default :
// function, symbol
return false ;
}
}
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
function getPropertyInfo ( name ) {
return properties . hasOwnProperty ( name ) ? properties [ name ] : null ;
}
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
function shouldAttributeAcceptBooleanValue ( name ) {
if ( isReservedProp ( name ) ) {
return true ;
}
var propertyInfo = getPropertyInfo ( name ) ;
if ( propertyInfo ) {
return propertyInfo . hasBooleanValue || propertyInfo . hasStringBooleanValue || propertyInfo . hasOverloadedBooleanValue ;
}
var prefix = name . toLowerCase ( ) . slice ( 0 , 5 ) ;
return prefix === 'data-' || prefix === 'aria-' ;
}
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
/ * *
* Checks to see if a property name is within the list of properties
* reserved for internal React operations . These properties should
* not be set on an HTML element .
*
* @ private
* @ param { string } name
* @ return { boolean } If the name is within reserved props
* /
function isReservedProp ( name ) {
return RESERVED _PROPS . hasOwnProperty ( name ) ;
}
var injection = DOMPropertyInjection ;
var MUST _USE _PROPERTY = injection . MUST _USE _PROPERTY ;
var HAS _BOOLEAN _VALUE = injection . HAS _BOOLEAN _VALUE ;
var HAS _NUMERIC _VALUE = injection . HAS _NUMERIC _VALUE ;
var HAS _POSITIVE _NUMERIC _VALUE = injection . HAS _POSITIVE _NUMERIC _VALUE ;
var HAS _OVERLOADED _BOOLEAN _VALUE = injection . HAS _OVERLOADED _BOOLEAN _VALUE ;
var HAS _STRING _BOOLEAN _VALUE = injection . HAS _STRING _BOOLEAN _VALUE ;
var HTMLDOMPropertyConfig = {
// When adding attributes to this list, be sure to also add them to
// the `possibleStandardNames` module to ensure casing and incorrect
// name warnings.
Properties : {
allowFullScreen : HAS _BOOLEAN _VALUE ,
// specifies target context for links with `preload` type
async : HAS _BOOLEAN _VALUE ,
// Note: there is a special case that prevents it from being written to the DOM
// on the client side because the browsers are inconsistent. Instead we call focus().
autoFocus : HAS _BOOLEAN _VALUE ,
autoPlay : HAS _BOOLEAN _VALUE ,
capture : HAS _OVERLOADED _BOOLEAN _VALUE ,
checked : MUST _USE _PROPERTY | HAS _BOOLEAN _VALUE ,
cols : HAS _POSITIVE _NUMERIC _VALUE ,
contentEditable : HAS _STRING _BOOLEAN _VALUE ,
controls : HAS _BOOLEAN _VALUE ,
'default' : HAS _BOOLEAN _VALUE ,
defer : HAS _BOOLEAN _VALUE ,
disabled : HAS _BOOLEAN _VALUE ,
download : HAS _OVERLOADED _BOOLEAN _VALUE ,
draggable : HAS _STRING _BOOLEAN _VALUE ,
formNoValidate : HAS _BOOLEAN _VALUE ,
hidden : HAS _BOOLEAN _VALUE ,
loop : HAS _BOOLEAN _VALUE ,
// Caution; `option.selected` is not updated if `select.multiple` is
// disabled with `removeAttribute`.
multiple : MUST _USE _PROPERTY | HAS _BOOLEAN _VALUE ,
muted : MUST _USE _PROPERTY | HAS _BOOLEAN _VALUE ,
noValidate : HAS _BOOLEAN _VALUE ,
open : HAS _BOOLEAN _VALUE ,
playsInline : HAS _BOOLEAN _VALUE ,
readOnly : HAS _BOOLEAN _VALUE ,
required : HAS _BOOLEAN _VALUE ,
reversed : HAS _BOOLEAN _VALUE ,
rows : HAS _POSITIVE _NUMERIC _VALUE ,
rowSpan : HAS _NUMERIC _VALUE ,
scoped : HAS _BOOLEAN _VALUE ,
seamless : HAS _BOOLEAN _VALUE ,
selected : MUST _USE _PROPERTY | HAS _BOOLEAN _VALUE ,
size : HAS _POSITIVE _NUMERIC _VALUE ,
start : HAS _NUMERIC _VALUE ,
// support for projecting regular DOM Elements via V1 named slots ( shadow dom )
span : HAS _POSITIVE _NUMERIC _VALUE ,
spellCheck : HAS _STRING _BOOLEAN _VALUE ,
// Style must be explicitly set in the attribute list. React components
// expect a style object
style : 0 ,
// Keep it in the whitelist because it is case-sensitive for SVG.
tabIndex : 0 ,
// itemScope is for for Microdata support.
// See http://schema.org/docs/gs.html
itemScope : HAS _BOOLEAN _VALUE ,
// These attributes must stay in the white-list because they have
// different attribute names (see DOMAttributeNames below)
acceptCharset : 0 ,
className : 0 ,
htmlFor : 0 ,
httpEquiv : 0 ,
// Attributes with mutation methods must be specified in the whitelist
// Set the string boolean flag to allow the behavior
value : HAS _STRING _BOOLEAN _VALUE
2017-10-14 18:40:54 +02:00
} ,
2017-12-10 21:51:33 +01:00
DOMAttributeNames : {
acceptCharset : 'accept-charset' ,
className : 'class' ,
htmlFor : 'for' ,
httpEquiv : 'http-equiv'
2017-10-14 18:40:54 +02:00
} ,
2017-12-10 21:51:33 +01:00
DOMMutationMethods : {
value : function ( node , value ) {
if ( value == null ) {
return node . removeAttribute ( 'value' ) ;
}
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
// Number inputs get special treatment due to some edge cases in
// Chrome. Let everything else assign the value attribute as normal.
// https://github.com/facebook/react/issues/7253#issuecomment-236074326
if ( node . type !== 'number' || node . hasAttribute ( 'value' ) === false ) {
node . setAttribute ( 'value' , '' + value ) ;
} else if ( node . validity && ! node . validity . badInput && node . ownerDocument . activeElement !== node ) {
// Don't assign an attribute if validation reports bad
// input. Chrome will clear the value. Additionally, don't
// operate on inputs that have focus, otherwise Chrome might
// strip off trailing decimal places and cause the user's
// cursor position to jump to the beginning of the input.
//
// In ReactDOMInput, we have an onBlur event that will trigger
// this function again when focus is lost.
node . setAttribute ( 'value' , '' + value ) ;
}
}
}
} ;
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
var HAS _STRING _BOOLEAN _VALUE$1 = injection . HAS _STRING _BOOLEAN _VALUE ;
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
var NS = {
xlink : 'http://www.w3.org/1999/xlink' ,
xml : 'http://www.w3.org/XML/1998/namespace'
2017-10-14 18:40:54 +02:00
} ;
/ * *
2017-12-10 21:51:33 +01:00
* This is a list of all SVG attributes that need special casing ,
* namespacing , or boolean value assignment .
2017-10-14 18:40:54 +02:00
*
2017-12-10 21:51:33 +01:00
* When adding attributes to this list , be sure to also add them to
* the ` possibleStandardNames ` module to ensure casing and incorrect
* name warnings .
2017-10-14 18:40:54 +02:00
*
2017-12-10 21:51:33 +01:00
* SVG Attributes List :
* https : //www.w3.org/TR/SVG/attindex.html
* SMIL Spec :
* https : //www.w3.org/TR/smil
2017-10-14 18:40:54 +02:00
* /
2017-12-10 21:51:33 +01:00
var ATTRS = [ 'accent-height' , 'alignment-baseline' , 'arabic-form' , 'baseline-shift' , 'cap-height' , 'clip-path' , 'clip-rule' , 'color-interpolation' , 'color-interpolation-filters' , 'color-profile' , 'color-rendering' , 'dominant-baseline' , 'enable-background' , 'fill-opacity' , 'fill-rule' , 'flood-color' , 'flood-opacity' , 'font-family' , 'font-size' , 'font-size-adjust' , 'font-stretch' , 'font-style' , 'font-variant' , 'font-weight' , 'glyph-name' , 'glyph-orientation-horizontal' , 'glyph-orientation-vertical' , 'horiz-adv-x' , 'horiz-origin-x' , 'image-rendering' , 'letter-spacing' , 'lighting-color' , 'marker-end' , 'marker-mid' , 'marker-start' , 'overline-position' , 'overline-thickness' , 'paint-order' , 'panose-1' , 'pointer-events' , 'rendering-intent' , 'shape-rendering' , 'stop-color' , 'stop-opacity' , 'strikethrough-position' , 'strikethrough-thickness' , 'stroke-dasharray' , 'stroke-dashoffset' , 'stroke-linecap' , 'stroke-linejoin' , 'stroke-miterlimit' , 'stroke-opacity' , 'stroke-width' , 'text-anchor' , 'text-decoration' , 'text-rendering' , 'underline-position' , 'underline-thickness' , 'unicode-bidi' , 'unicode-range' , 'units-per-em' , 'v-alphabetic' , 'v-hanging' , 'v-ideographic' , 'v-mathematical' , 'vector-effect' , 'vert-adv-y' , 'vert-origin-x' , 'vert-origin-y' , 'word-spacing' , 'writing-mode' , 'x-height' , 'xlink:actuate' , 'xlink:arcrole' , 'xlink:href' , 'xlink:role' , 'xlink:show' , 'xlink:title' , 'xlink:type' , 'xml:base' , 'xmlns:xlink' , 'xml:lang' , 'xml:space' ] ;
var SVGDOMPropertyConfig = {
Properties : {
autoReverse : HAS _STRING _BOOLEAN _VALUE$1 ,
externalResourcesRequired : HAS _STRING _BOOLEAN _VALUE$1 ,
preserveAlpha : HAS _STRING _BOOLEAN _VALUE$1
} ,
DOMAttributeNames : {
autoReverse : 'autoReverse' ,
externalResourcesRequired : 'externalResourcesRequired' ,
preserveAlpha : 'preserveAlpha'
} ,
DOMAttributeNamespaces : {
xlinkActuate : NS . xlink ,
xlinkArcrole : NS . xlink ,
xlinkHref : NS . xlink ,
xlinkRole : NS . xlink ,
xlinkShow : NS . xlink ,
xlinkTitle : NS . xlink ,
xlinkType : NS . xlink ,
xmlBase : NS . xml ,
xmlLang : NS . xml ,
xmlSpace : NS . xml
}
} ;
var CAMELIZE = /[\-\:]([a-z])/g ;
var capitalize = function ( token ) {
return token [ 1 ] . toUpperCase ( ) ;
} ;
ATTRS . forEach ( function ( original ) {
var reactName = original . replace ( CAMELIZE , capitalize ) ;
SVGDOMPropertyConfig . Properties [ reactName ] = 0 ;
SVGDOMPropertyConfig . DOMAttributeNames [ reactName ] = original ;
} ) ;
injection . injectDOMPropertyConfig ( HTMLDOMPropertyConfig ) ;
injection . injectDOMPropertyConfig ( SVGDOMPropertyConfig ) ;
// TODO: this is special because it gets imported during build.
var ReactVersion = '16.2.0' ;
var describeComponentFrame = function ( name , source , ownerName ) {
return '\n in ' + ( name || 'Unknown' ) + ( source ? ' (at ' + source . fileName . replace ( /^.*[\\\/]/ , '' ) + ':' + source . lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '' ) ;
} ;
var ReactInternals = React . _ _SECRET _INTERNALS _DO _NOT _USE _OR _YOU _WILL _BE _FIRED ;
var ReactCurrentOwner = ReactInternals . ReactCurrentOwner ;
var ReactDebugCurrentFrame = ReactInternals . ReactDebugCurrentFrame ;
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
// nor polyfill, then a plain number is used for performance.
var hasSymbol = typeof Symbol === 'function' && Symbol [ 'for' ] ;
var REACT _FRAGMENT _TYPE = hasSymbol ? Symbol [ 'for' ] ( 'react.fragment' ) : 0xeacb ;
2017-10-14 18:40:54 +02:00
// code copied and modified from escape-html
/ * *
* Module variables .
* @ private
* /
var matchHtmlRegExp = /["'&<>]/ ;
/ * *
2017-12-10 21:51:33 +01:00
* Escapes special characters and HTML entities in a given html string .
2017-10-14 18:40:54 +02:00
*
2017-12-10 21:51:33 +01:00
* @ param { string } string HTML string to escape for later insertion
2017-10-14 18:40:54 +02:00
* @ return { string }
* @ public
* /
function escapeHtml ( string ) {
var str = '' + string ;
var match = matchHtmlRegExp . exec ( str ) ;
if ( ! match ) {
return str ;
}
var escape ;
var html = '' ;
var index = 0 ;
var lastIndex = 0 ;
for ( index = match . index ; index < str . length ; index ++ ) {
switch ( str . charCodeAt ( index ) ) {
case 34 :
// "
escape = '"' ;
break ;
case 38 :
// &
escape = '&' ;
break ;
case 39 :
// '
escape = ''' ; // modified from escape-html; used to be '''
break ;
case 60 :
// <
escape = '<' ;
break ;
case 62 :
// >
escape = '>' ;
break ;
default :
continue ;
}
if ( lastIndex !== index ) {
html += str . substring ( lastIndex , index ) ;
}
lastIndex = index + 1 ;
html += escape ;
}
return lastIndex !== index ? html + str . substring ( lastIndex , index ) : html ;
}
// end code copied and modified from escape-html
/ * *
* Escapes text to prevent scripting attacks .
*
* @ param { * } text Text value to escape .
* @ return { string } An escaped string .
* /
2017-12-10 21:51:33 +01:00
function escapeTextForBrowser ( text ) {
2017-10-14 18:40:54 +02:00
if ( typeof text === 'boolean' || typeof text === 'number' ) {
// this shortcircuit helps perf for types that we know will never have
// special characters, especially given that this function is used often
// for numeric dom ids.
return '' + text ;
}
return escapeHtml ( text ) ;
}
/ * *
* Escapes attribute value to prevent scripting attacks .
*
* @ param { * } value Value to escape .
* @ return { string } An escaped string .
* /
function quoteAttributeValueForBrowser ( value ) {
2017-12-10 21:51:33 +01:00
return '"' + escapeTextForBrowser ( value ) + '"' ;
2017-10-14 18:40:54 +02:00
}
// isAttributeNameSafe() is currently duplicated in DOMPropertyOperations.
// TODO: Find a better place for this.
2017-12-10 21:51:33 +01:00
var VALID _ATTRIBUTE _NAME _REGEX = new RegExp ( '^[' + ATTRIBUTE _NAME _START _CHAR + '][' + ATTRIBUTE _NAME _CHAR + ']*$' ) ;
2017-10-14 18:40:54 +02:00
var illegalAttributeNameCache = { } ;
var validatedAttributeNameCache = { } ;
function isAttributeNameSafe ( attributeName ) {
if ( validatedAttributeNameCache . hasOwnProperty ( attributeName ) ) {
return true ;
}
if ( illegalAttributeNameCache . hasOwnProperty ( attributeName ) ) {
return false ;
}
if ( VALID _ATTRIBUTE _NAME _REGEX . test ( attributeName ) ) {
validatedAttributeNameCache [ attributeName ] = true ;
return true ;
}
illegalAttributeNameCache [ attributeName ] = true ;
{
2017-12-10 21:51:33 +01:00
warning ( false , 'Invalid attribute name: `%s`' , attributeName ) ;
2017-10-14 18:40:54 +02:00
}
return false ;
}
// shouldIgnoreValue() is currently duplicated in DOMPropertyOperations.
// TODO: Find a better place for this.
function shouldIgnoreValue ( propertyInfo , value ) {
return value == null || propertyInfo . hasBooleanValue && ! value || propertyInfo . hasNumericValue && isNaN ( value ) || propertyInfo . hasPositiveNumericValue && value < 1 || propertyInfo . hasOverloadedBooleanValue && value === false ;
}
/ * *
* Operations for dealing with DOM properties .
* /
2017-12-10 21:51:33 +01:00
/ * *
* Creates markup for the ID property .
*
* @ param { string } id Unescaped ID .
* @ return { string } Markup string .
* /
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
function createMarkupForRoot ( ) {
return ROOT _ATTRIBUTE _NAME + '=""' ;
}
/ * *
* Creates markup for a property .
*
* @ param { string } name
* @ param { * } value
* @ return { ? string } Markup string , or null if the property was invalid .
* /
function createMarkupForProperty ( name , value ) {
var propertyInfo = getPropertyInfo ( name ) ;
if ( propertyInfo ) {
if ( shouldIgnoreValue ( propertyInfo , value ) ) {
2017-10-14 18:40:54 +02:00
return '' ;
}
2017-12-10 21:51:33 +01:00
var attributeName = propertyInfo . attributeName ;
if ( propertyInfo . hasBooleanValue || propertyInfo . hasOverloadedBooleanValue && value === true ) {
return attributeName + '=""' ;
} else if ( typeof value !== 'boolean' || shouldAttributeAcceptBooleanValue ( name ) ) {
return attributeName + '=' + quoteAttributeValueForBrowser ( value ) ;
}
} else if ( shouldSetAttribute ( name , value ) ) {
if ( value == null ) {
return '' ;
}
return name + '=' + quoteAttributeValueForBrowser ( value ) ;
}
return null ;
}
/ * *
* Creates markup for a custom property .
*
* @ param { string } name
* @ param { * } value
* @ return { string } Markup string , or empty string if the property was invalid .
* /
function createMarkupForCustomAttribute ( name , value ) {
if ( ! isAttributeNameSafe ( name ) || value == null ) {
return '' ;
2017-10-14 18:40:54 +02:00
}
2017-12-10 21:51:33 +01:00
return name + '=' + quoteAttributeValueForBrowser ( value ) ;
}
var HTML _NAMESPACE = 'http://www.w3.org/1999/xhtml' ;
var MATH _NAMESPACE = 'http://www.w3.org/1998/Math/MathML' ;
var SVG _NAMESPACE = 'http://www.w3.org/2000/svg' ;
var Namespaces = {
html : HTML _NAMESPACE ,
mathml : MATH _NAMESPACE ,
svg : SVG _NAMESPACE
2017-10-14 18:40:54 +02:00
} ;
2017-12-10 21:51:33 +01:00
// Assumes there is no parent namespace.
function getIntrinsicNamespace ( type ) {
switch ( type ) {
case 'svg' :
return SVG _NAMESPACE ;
case 'math' :
return MATH _NAMESPACE ;
default :
return HTML _NAMESPACE ;
}
}
function getChildNamespace ( parentNamespace , type ) {
if ( parentNamespace == null || parentNamespace === HTML _NAMESPACE ) {
// No (or default) parent namespace: potential entry point.
return getIntrinsicNamespace ( type ) ;
}
if ( parentNamespace === SVG _NAMESPACE && type === 'foreignObject' ) {
// We're leaving SVG.
return HTML _NAMESPACE ;
}
// By default, pass namespace below.
return parentNamespace ;
}
2017-10-14 18:40:54 +02:00
var ReactControlledValuePropTypes = {
checkPropTypes : null
} ;
{
var hasReadOnlyValue = {
button : true ,
checkbox : true ,
image : true ,
hidden : true ,
radio : true ,
reset : true ,
submit : true
} ;
2017-12-10 21:51:33 +01:00
var propTypes = {
2017-10-14 18:40:54 +02:00
value : function ( props , propName , componentName ) {
if ( ! props [ propName ] || hasReadOnlyValue [ props . type ] || props . onChange || props . readOnly || props . disabled ) {
return null ;
}
return new Error ( 'You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.' ) ;
} ,
checked : function ( props , propName , componentName ) {
if ( ! props [ propName ] || props . onChange || props . readOnly || props . disabled ) {
return null ;
}
return new Error ( 'You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.' ) ;
2017-12-10 21:51:33 +01:00
}
2017-10-14 18:40:54 +02:00
} ;
/ * *
* Provide a linked ` value ` attribute for controlled forms . You should not use
* this outside of the ReactDOM controlled form components .
* /
ReactControlledValuePropTypes . checkPropTypes = function ( tagName , props , getStack ) {
2017-12-10 21:51:33 +01:00
checkPropTypes ( propTypes , props , 'prop' , tagName , getStack ) ;
} ;
}
2017-10-14 18:40:54 +02:00
// For HTML, certain tags should omit their close tag. We keep a whitelist for
// those special-case tags.
var omittedCloseTags = {
area : true ,
base : true ,
br : true ,
col : true ,
embed : true ,
hr : true ,
img : true ,
input : true ,
keygen : true ,
link : true ,
meta : true ,
param : true ,
source : true ,
track : true ,
wbr : true
} ;
// For HTML, certain tags cannot have children. This has the same purpose as
// `omittedCloseTags` except that `menuitem` should still have its closing tag.
2017-12-10 21:51:33 +01:00
var voidElementTags = _assign ( {
2017-10-14 18:40:54 +02:00
menuitem : true
2017-12-10 21:51:33 +01:00
} , omittedCloseTags ) ;
2017-10-14 18:40:54 +02:00
var HTML = '__html' ;
2017-12-10 21:51:33 +01:00
function assertValidProps ( tag , props , getStack ) {
2017-10-14 18:40:54 +02:00
if ( ! props ) {
return ;
}
// Note the use of `==` which checks for null or undefined.
2017-12-10 21:51:33 +01:00
if ( voidElementTags [ tag ] ) {
! ( props . children == null && props . dangerouslySetInnerHTML == null ) ? invariant ( false , '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s' , tag , getStack ( ) ) : void 0 ;
2017-10-14 18:40:54 +02:00
}
if ( props . dangerouslySetInnerHTML != null ) {
! ( props . children == null ) ? invariant ( false , 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' ) : void 0 ;
! ( typeof props . dangerouslySetInnerHTML === 'object' && HTML in props . dangerouslySetInnerHTML ) ? invariant ( false , '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.' ) : void 0 ;
}
{
2017-12-10 21:51:33 +01:00
warning ( props . suppressContentEditableWarning || ! props . contentEditable || props . children == null , 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.%s' , getStack ( ) ) ;
2017-10-14 18:40:54 +02:00
}
2017-12-10 21:51:33 +01:00
! ( props . style == null || typeof props . style === 'object' ) ? invariant ( false , 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \'em\'}} when using JSX.%s' , getStack ( ) ) : void 0 ;
2017-10-14 18:40:54 +02:00
}
/ * *
* CSS properties which accept numbers but are not in units of "px" .
* /
2017-12-10 21:51:33 +01:00
var isUnitlessNumber = {
2017-10-14 18:40:54 +02:00
animationIterationCount : true ,
borderImageOutset : true ,
borderImageSlice : true ,
borderImageWidth : true ,
boxFlex : true ,
boxFlexGroup : true ,
boxOrdinalGroup : true ,
columnCount : true ,
columns : true ,
flex : true ,
flexGrow : true ,
flexPositive : true ,
flexShrink : true ,
flexNegative : true ,
flexOrder : true ,
gridRow : true ,
gridRowEnd : true ,
gridRowSpan : true ,
gridRowStart : true ,
gridColumn : true ,
gridColumnEnd : true ,
gridColumnSpan : true ,
gridColumnStart : true ,
fontWeight : true ,
lineClamp : true ,
lineHeight : true ,
opacity : true ,
order : true ,
orphans : true ,
tabSize : true ,
widows : true ,
zIndex : true ,
zoom : true ,
// SVG-related properties
fillOpacity : true ,
floodOpacity : true ,
stopOpacity : true ,
strokeDasharray : true ,
strokeDashoffset : true ,
strokeMiterlimit : true ,
strokeOpacity : true ,
strokeWidth : true
} ;
/ * *
* @ param { string } prefix vendor - specific prefix , eg : Webkit
* @ param { string } key style name , eg : transitionDuration
* @ return { string } style name prefixed with ` prefix ` , properly camelCased , eg :
* WebkitTransitionDuration
* /
function prefixKey ( prefix , key ) {
return prefix + key . charAt ( 0 ) . toUpperCase ( ) + key . substring ( 1 ) ;
}
/ * *
* Support style names that may come passed in prefixed by adding permutations
* of vendor prefixes .
* /
var prefixes = [ 'Webkit' , 'ms' , 'Moz' , 'O' ] ;
// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
// infinite loop, because it iterates over the newly added props too.
2017-12-10 21:51:33 +01:00
Object . keys ( isUnitlessNumber ) . forEach ( function ( prop ) {
2017-10-14 18:40:54 +02:00
prefixes . forEach ( function ( prefix ) {
2017-12-10 21:51:33 +01:00
isUnitlessNumber [ prefixKey ( prefix , prop ) ] = isUnitlessNumber [ prop ] ;
2017-10-14 18:40:54 +02:00
} ) ;
} ) ;
/ * *
* Convert a value into the proper css writable value . The style name ` name `
* should be logical ( no hyphens ) , as specified
* in ` CSSProperty.isUnitlessNumber ` .
*
* @ param { string } name CSS property name such as ` topMargin ` .
* @ param { * } value CSS property value such as ` 10px ` .
* @ return { string } Normalized style value with dimensions applied .
* /
function dangerousStyleValue ( name , value , isCustomProperty ) {
// Note that we've removed escapeTextForBrowser() calls here since the
// whole string will be escaped when the attribute is injected into
// the markup. If you provide unsafe user data here they can inject
// arbitrary CSS which may be problematic (I couldn't repro this):
// https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
// http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
// This is not an XSS hole but instead a potential CSS injection issue
// which has lead to a greater discussion about how we're going to
// trust URLs moving forward. See #2115901
var isEmpty = value == null || typeof value === 'boolean' || value === '' ;
if ( isEmpty ) {
return '' ;
}
if ( ! isCustomProperty && typeof value === 'number' && value !== 0 && ! ( isUnitlessNumber . hasOwnProperty ( name ) && isUnitlessNumber [ name ] ) ) {
return value + 'px' ; // Presumes implicit 'px' suffix for unitless numbers
}
return ( '' + value ) . trim ( ) ;
}
function isCustomComponent ( tagName , props ) {
if ( tagName . indexOf ( '-' ) === - 1 ) {
return typeof props . is === 'string' ;
}
switch ( tagName ) {
// These are reserved SVG and MathML elements.
// We don't mind this whitelist too much because we expect it to never grow.
// The alternative is to track the namespace in a few places which is convoluted.
// https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
case 'annotation-xml' :
case 'color-profile' :
case 'font-face' :
case 'font-face-src' :
case 'font-face-uri' :
case 'font-face-format' :
case 'font-face-name' :
case 'missing-glyph' :
return false ;
default :
return true ;
}
}
2017-12-10 21:51:33 +01:00
var warnValidStyle = emptyFunction ;
2017-10-14 18:40:54 +02:00
{
// 'msTransform' is correct, but the other prefixes should be capitalized
var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/ ;
// style values shouldn't contain a semicolon
var badStyleValueWithSemicolonPattern = /;\s*$/ ;
var warnedStyleNames = { } ;
var warnedStyleValues = { } ;
var warnedForNaNValue = false ;
var warnedForInfinityValue = false ;
2017-12-10 21:51:33 +01:00
var warnHyphenatedStyleName = function ( name , getStack ) {
2017-10-14 18:40:54 +02:00
if ( warnedStyleNames . hasOwnProperty ( name ) && warnedStyleNames [ name ] ) {
return ;
}
warnedStyleNames [ name ] = true ;
2017-12-10 21:51:33 +01:00
warning ( false , 'Unsupported style property %s. Did you mean %s?%s' , name , camelizeStyleName ( name ) , getStack ( ) ) ;
2017-10-14 18:40:54 +02:00
} ;
2017-12-10 21:51:33 +01:00
var warnBadVendoredStyleName = function ( name , getStack ) {
2017-10-14 18:40:54 +02:00
if ( warnedStyleNames . hasOwnProperty ( name ) && warnedStyleNames [ name ] ) {
return ;
}
warnedStyleNames [ name ] = true ;
2017-12-10 21:51:33 +01:00
warning ( false , 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s' , name , name . charAt ( 0 ) . toUpperCase ( ) + name . slice ( 1 ) , getStack ( ) ) ;
2017-10-14 18:40:54 +02:00
} ;
2017-12-10 21:51:33 +01:00
var warnStyleValueWithSemicolon = function ( name , value , getStack ) {
2017-10-14 18:40:54 +02:00
if ( warnedStyleValues . hasOwnProperty ( value ) && warnedStyleValues [ value ] ) {
return ;
}
warnedStyleValues [ value ] = true ;
2017-12-10 21:51:33 +01:00
warning ( false , "Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.%s' , name , value . replace ( badStyleValueWithSemicolonPattern , '' ) , getStack ( ) ) ;
2017-10-14 18:40:54 +02:00
} ;
2017-12-10 21:51:33 +01:00
var warnStyleValueIsNaN = function ( name , value , getStack ) {
2017-10-14 18:40:54 +02:00
if ( warnedForNaNValue ) {
return ;
}
warnedForNaNValue = true ;
2017-12-10 21:51:33 +01:00
warning ( false , '`NaN` is an invalid value for the `%s` css style property.%s' , name , getStack ( ) ) ;
2017-10-14 18:40:54 +02:00
} ;
2017-12-10 21:51:33 +01:00
var warnStyleValueIsInfinity = function ( name , value , getStack ) {
2017-10-14 18:40:54 +02:00
if ( warnedForInfinityValue ) {
return ;
}
warnedForInfinityValue = true ;
2017-12-10 21:51:33 +01:00
warning ( false , '`Infinity` is an invalid value for the `%s` css style property.%s' , name , getStack ( ) ) ;
2017-10-14 18:40:54 +02:00
} ;
2017-12-10 21:51:33 +01:00
warnValidStyle = function ( name , value , getStack ) {
2017-10-14 18:40:54 +02:00
if ( name . indexOf ( '-' ) > - 1 ) {
2017-12-10 21:51:33 +01:00
warnHyphenatedStyleName ( name , getStack ) ;
2017-10-14 18:40:54 +02:00
} else if ( badVendoredStyleNamePattern . test ( name ) ) {
2017-12-10 21:51:33 +01:00
warnBadVendoredStyleName ( name , getStack ) ;
2017-10-14 18:40:54 +02:00
} else if ( badStyleValueWithSemicolonPattern . test ( value ) ) {
2017-12-10 21:51:33 +01:00
warnStyleValueWithSemicolon ( name , value , getStack ) ;
2017-10-14 18:40:54 +02:00
}
if ( typeof value === 'number' ) {
if ( isNaN ( value ) ) {
2017-12-10 21:51:33 +01:00
warnStyleValueIsNaN ( name , value , getStack ) ;
2017-10-14 18:40:54 +02:00
} else if ( ! isFinite ( value ) ) {
2017-12-10 21:51:33 +01:00
warnStyleValueIsInfinity ( name , value , getStack ) ;
2017-10-14 18:40:54 +02:00
}
}
} ;
}
2017-12-10 21:51:33 +01:00
var warnValidStyle$1 = warnValidStyle ;
2017-10-14 18:40:54 +02:00
var ariaProperties = {
'aria-current' : 0 , // state
'aria-details' : 0 ,
'aria-disabled' : 0 , // state
'aria-hidden' : 0 , // state
'aria-invalid' : 0 , // state
'aria-keyshortcuts' : 0 ,
'aria-label' : 0 ,
'aria-roledescription' : 0 ,
// Widget Attributes
'aria-autocomplete' : 0 ,
'aria-checked' : 0 ,
'aria-expanded' : 0 ,
'aria-haspopup' : 0 ,
'aria-level' : 0 ,
'aria-modal' : 0 ,
'aria-multiline' : 0 ,
'aria-multiselectable' : 0 ,
'aria-orientation' : 0 ,
'aria-placeholder' : 0 ,
'aria-pressed' : 0 ,
'aria-readonly' : 0 ,
'aria-required' : 0 ,
'aria-selected' : 0 ,
'aria-sort' : 0 ,
'aria-valuemax' : 0 ,
'aria-valuemin' : 0 ,
'aria-valuenow' : 0 ,
'aria-valuetext' : 0 ,
// Live Region Attributes
'aria-atomic' : 0 ,
'aria-busy' : 0 ,
'aria-live' : 0 ,
'aria-relevant' : 0 ,
// Drag-and-Drop Attributes
'aria-dropeffect' : 0 ,
'aria-grabbed' : 0 ,
// Relationship Attributes
'aria-activedescendant' : 0 ,
'aria-colcount' : 0 ,
'aria-colindex' : 0 ,
'aria-colspan' : 0 ,
'aria-controls' : 0 ,
'aria-describedby' : 0 ,
'aria-errormessage' : 0 ,
'aria-flowto' : 0 ,
'aria-labelledby' : 0 ,
'aria-owns' : 0 ,
'aria-posinset' : 0 ,
'aria-rowcount' : 0 ,
'aria-rowindex' : 0 ,
'aria-rowspan' : 0 ,
'aria-setsize' : 0
} ;
var warnedProperties = { } ;
2017-12-10 21:51:33 +01:00
var rARIA = new RegExp ( '^(aria)-[' + ATTRIBUTE _NAME _CHAR + ']*$' ) ;
var rARIACamel = new RegExp ( '^(aria)[A-Z][' + ATTRIBUTE _NAME _CHAR + ']*$' ) ;
2017-10-14 18:40:54 +02:00
var hasOwnProperty = Object . prototype . hasOwnProperty ;
2017-12-10 21:51:33 +01:00
function getStackAddendum$1 ( ) {
var stack = ReactDebugCurrentFrame . getStackAddendum ( ) ;
return stack != null ? stack : '' ;
2017-10-14 18:40:54 +02:00
}
2017-12-10 21:51:33 +01:00
function validateProperty ( tagName , name ) {
2017-10-14 18:40:54 +02:00
if ( hasOwnProperty . call ( warnedProperties , name ) && warnedProperties [ name ] ) {
return true ;
}
if ( rARIACamel . test ( name ) ) {
var ariaName = 'aria-' + name . slice ( 4 ) . toLowerCase ( ) ;
2017-12-10 21:51:33 +01:00
var correctName = ariaProperties . hasOwnProperty ( ariaName ) ? ariaName : null ;
2017-10-14 18:40:54 +02:00
// If this is an aria-* attribute, but is not listed in the known DOM
// DOM properties, then it is an invalid aria-* attribute.
if ( correctName == null ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.%s' , name , getStackAddendum$1 ( ) ) ;
2017-10-14 18:40:54 +02:00
warnedProperties [ name ] = true ;
return true ;
}
// aria-* attributes should be lowercase; suggest the lowercase version.
if ( name !== correctName ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Invalid ARIA attribute `%s`. Did you mean `%s`?%s' , name , correctName , getStackAddendum$1 ( ) ) ;
2017-10-14 18:40:54 +02:00
warnedProperties [ name ] = true ;
return true ;
}
}
if ( rARIA . test ( name ) ) {
var lowerCasedName = name . toLowerCase ( ) ;
2017-12-10 21:51:33 +01:00
var standardName = ariaProperties . hasOwnProperty ( lowerCasedName ) ? lowerCasedName : null ;
2017-10-14 18:40:54 +02:00
// If this is an aria-* attribute, but is not listed in the known DOM
// DOM properties, then it is an invalid aria-* attribute.
if ( standardName == null ) {
warnedProperties [ name ] = true ;
return false ;
}
// aria-* attributes should be lowercase; suggest the lowercase version.
if ( name !== standardName ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Unknown ARIA attribute `%s`. Did you mean `%s`?%s' , name , standardName , getStackAddendum$1 ( ) ) ;
2017-10-14 18:40:54 +02:00
warnedProperties [ name ] = true ;
return true ;
}
}
return true ;
}
2017-12-10 21:51:33 +01:00
function warnInvalidARIAProps ( type , props ) {
2017-10-14 18:40:54 +02:00
var invalidProps = [ ] ;
for ( var key in props ) {
2017-12-10 21:51:33 +01:00
var isValid = validateProperty ( type , key ) ;
2017-10-14 18:40:54 +02:00
if ( ! isValid ) {
invalidProps . push ( key ) ;
}
}
var unknownPropString = invalidProps . map ( function ( prop ) {
return '`' + prop + '`' ;
} ) . join ( ', ' ) ;
if ( invalidProps . length === 1 ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Invalid aria prop %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s' , unknownPropString , type , getStackAddendum$1 ( ) ) ;
2017-10-14 18:40:54 +02:00
} else if ( invalidProps . length > 1 ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Invalid aria props %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s' , unknownPropString , type , getStackAddendum$1 ( ) ) ;
2017-10-14 18:40:54 +02:00
}
}
2017-12-10 21:51:33 +01:00
function validateProperties ( type , props ) {
if ( isCustomComponent ( type , props ) ) {
2017-10-14 18:40:54 +02:00
return ;
}
2017-12-10 21:51:33 +01:00
warnInvalidARIAProps ( type , props ) ;
2017-10-14 18:40:54 +02:00
}
var didWarnValueNull = false ;
2017-12-10 21:51:33 +01:00
function getStackAddendum$2 ( ) {
var stack = ReactDebugCurrentFrame . getStackAddendum ( ) ;
return stack != null ? stack : '' ;
2017-10-14 18:40:54 +02:00
}
2017-12-10 21:51:33 +01:00
function validateProperties$1 ( type , props ) {
2017-10-14 18:40:54 +02:00
if ( type !== 'input' && type !== 'textarea' && type !== 'select' ) {
return ;
}
2017-12-10 21:51:33 +01:00
if ( props != null && props . value === null && ! didWarnValueNull ) {
2017-10-14 18:40:54 +02:00
didWarnValueNull = true ;
2017-12-10 21:51:33 +01:00
if ( type === 'select' && props . multiple ) {
warning ( false , '`value` prop on `%s` should not be null. ' + 'Consider using an empty array when `multiple` is set to `true` ' + 'to clear the component or `undefined` for uncontrolled components.%s' , type , getStackAddendum$2 ( ) ) ;
} else {
warning ( false , '`value` prop on `%s` should not be null. ' + 'Consider using an empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s' , type , getStackAddendum$2 ( ) ) ;
2017-10-14 18:40:54 +02:00
}
}
2017-12-10 21:51:33 +01:00
}
2017-10-14 18:40:54 +02:00
/ * *
2017-12-10 21:51:33 +01:00
* Registers plugins so that they can extract and dispatch events .
*
* @ see { EventPluginHub }
2017-10-14 18:40:54 +02:00
* /
/ * *
2017-12-10 21:51:33 +01:00
* Ordered list of injected plugins .
2017-10-14 18:40:54 +02:00
* /
2017-12-10 21:51:33 +01:00
2017-10-14 18:40:54 +02:00
/ * *
2017-12-10 21:51:33 +01:00
* Mapping from event name to dispatch config
2017-10-14 18:40:54 +02:00
* /
2017-12-10 21:51:33 +01:00
2017-10-14 18:40:54 +02:00
/ * *
2017-12-10 21:51:33 +01:00
* Mapping from registration name to plugin module
2017-10-14 18:40:54 +02:00
* /
2017-12-10 21:51:33 +01:00
var registrationNameModules = { } ;
2017-10-14 18:40:54 +02:00
/ * *
2017-12-10 21:51:33 +01:00
* Mapping from registration name to event name
2017-10-14 18:40:54 +02:00
* /
2017-12-10 21:51:33 +01:00
/ * *
* Mapping from lowercase registration names to the properly cased version ,
* used to warn in the case of missing event handlers . Available
* only in true .
* @ type { Object }
* /
var possibleRegistrationNames = { } ;
// Trust the developer to only use possibleRegistrationNames in true
2017-10-14 18:40:54 +02:00
/ * *
2017-12-10 21:51:33 +01:00
* Injects an ordering of plugins ( by plugin name ) . This allows the ordering
* to be decoupled from injection of the actual plugins so that ordering is
* always deterministic regardless of packaging , on - the - fly injection , etc .
2017-10-14 18:40:54 +02:00
*
2017-12-10 21:51:33 +01:00
* @ param { array } InjectedEventPluginOrder
* @ internal
* @ see { EventPluginHub . injection . injectEventPluginOrder }
2017-10-14 18:40:54 +02:00
* /
/ * *
2017-12-10 21:51:33 +01:00
* Injects plugins to be used by ` EventPluginHub ` . The plugin names must be
* in the ordering injected by ` injectEventPluginOrder ` .
2017-10-14 18:40:54 +02:00
*
2017-12-10 21:51:33 +01:00
* Plugins can be injected as part of page initialization or on - the - fly .
2017-10-14 18:40:54 +02:00
*
2017-12-10 21:51:33 +01:00
* @ param { object } injectedNamesToPlugins Map from names to plugin modules .
* @ internal
* @ see { EventPluginHub . injection . injectEventPluginsByName }
2017-10-14 18:40:54 +02:00
* /
// When adding attributes to the HTML or SVG whitelist, be sure to
// also add them to this module to ensure casing and incorrect name
// warnings.
2017-12-10 21:51:33 +01:00
var possibleStandardNames = {
2017-10-14 18:40:54 +02:00
// HTML
accept : 'accept' ,
acceptcharset : 'acceptCharset' ,
'accept-charset' : 'acceptCharset' ,
accesskey : 'accessKey' ,
action : 'action' ,
allowfullscreen : 'allowFullScreen' ,
alt : 'alt' ,
as : 'as' ,
async : 'async' ,
autocapitalize : 'autoCapitalize' ,
autocomplete : 'autoComplete' ,
autocorrect : 'autoCorrect' ,
autofocus : 'autoFocus' ,
autoplay : 'autoPlay' ,
autosave : 'autoSave' ,
capture : 'capture' ,
cellpadding : 'cellPadding' ,
cellspacing : 'cellSpacing' ,
challenge : 'challenge' ,
charset : 'charSet' ,
checked : 'checked' ,
children : 'children' ,
cite : 'cite' ,
'class' : 'className' ,
classid : 'classID' ,
classname : 'className' ,
cols : 'cols' ,
colspan : 'colSpan' ,
content : 'content' ,
contenteditable : 'contentEditable' ,
contextmenu : 'contextMenu' ,
controls : 'controls' ,
controlslist : 'controlsList' ,
coords : 'coords' ,
crossorigin : 'crossOrigin' ,
dangerouslysetinnerhtml : 'dangerouslySetInnerHTML' ,
data : 'data' ,
datetime : 'dateTime' ,
'default' : 'default' ,
defaultchecked : 'defaultChecked' ,
defaultvalue : 'defaultValue' ,
defer : 'defer' ,
dir : 'dir' ,
disabled : 'disabled' ,
download : 'download' ,
draggable : 'draggable' ,
enctype : 'encType' ,
'for' : 'htmlFor' ,
form : 'form' ,
formmethod : 'formMethod' ,
formaction : 'formAction' ,
formenctype : 'formEncType' ,
formnovalidate : 'formNoValidate' ,
formtarget : 'formTarget' ,
frameborder : 'frameBorder' ,
headers : 'headers' ,
height : 'height' ,
hidden : 'hidden' ,
high : 'high' ,
href : 'href' ,
hreflang : 'hrefLang' ,
htmlfor : 'htmlFor' ,
httpequiv : 'httpEquiv' ,
'http-equiv' : 'httpEquiv' ,
icon : 'icon' ,
id : 'id' ,
innerhtml : 'innerHTML' ,
inputmode : 'inputMode' ,
integrity : 'integrity' ,
is : 'is' ,
itemid : 'itemID' ,
itemprop : 'itemProp' ,
itemref : 'itemRef' ,
itemscope : 'itemScope' ,
itemtype : 'itemType' ,
keyparams : 'keyParams' ,
keytype : 'keyType' ,
kind : 'kind' ,
label : 'label' ,
lang : 'lang' ,
list : 'list' ,
loop : 'loop' ,
low : 'low' ,
manifest : 'manifest' ,
marginwidth : 'marginWidth' ,
marginheight : 'marginHeight' ,
max : 'max' ,
maxlength : 'maxLength' ,
media : 'media' ,
mediagroup : 'mediaGroup' ,
method : 'method' ,
min : 'min' ,
minlength : 'minLength' ,
multiple : 'multiple' ,
muted : 'muted' ,
name : 'name' ,
nonce : 'nonce' ,
novalidate : 'noValidate' ,
open : 'open' ,
optimum : 'optimum' ,
pattern : 'pattern' ,
placeholder : 'placeholder' ,
playsinline : 'playsInline' ,
poster : 'poster' ,
preload : 'preload' ,
profile : 'profile' ,
radiogroup : 'radioGroup' ,
readonly : 'readOnly' ,
referrerpolicy : 'referrerPolicy' ,
rel : 'rel' ,
required : 'required' ,
reversed : 'reversed' ,
role : 'role' ,
rows : 'rows' ,
rowspan : 'rowSpan' ,
sandbox : 'sandbox' ,
scope : 'scope' ,
scoped : 'scoped' ,
scrolling : 'scrolling' ,
seamless : 'seamless' ,
selected : 'selected' ,
shape : 'shape' ,
size : 'size' ,
sizes : 'sizes' ,
span : 'span' ,
spellcheck : 'spellCheck' ,
src : 'src' ,
srcdoc : 'srcDoc' ,
srclang : 'srcLang' ,
srcset : 'srcSet' ,
start : 'start' ,
step : 'step' ,
style : 'style' ,
summary : 'summary' ,
tabindex : 'tabIndex' ,
target : 'target' ,
title : 'title' ,
type : 'type' ,
usemap : 'useMap' ,
value : 'value' ,
width : 'width' ,
wmode : 'wmode' ,
wrap : 'wrap' ,
// SVG
about : 'about' ,
accentheight : 'accentHeight' ,
'accent-height' : 'accentHeight' ,
accumulate : 'accumulate' ,
additive : 'additive' ,
alignmentbaseline : 'alignmentBaseline' ,
'alignment-baseline' : 'alignmentBaseline' ,
allowreorder : 'allowReorder' ,
alphabetic : 'alphabetic' ,
amplitude : 'amplitude' ,
arabicform : 'arabicForm' ,
'arabic-form' : 'arabicForm' ,
ascent : 'ascent' ,
attributename : 'attributeName' ,
attributetype : 'attributeType' ,
autoreverse : 'autoReverse' ,
azimuth : 'azimuth' ,
basefrequency : 'baseFrequency' ,
baselineshift : 'baselineShift' ,
'baseline-shift' : 'baselineShift' ,
baseprofile : 'baseProfile' ,
bbox : 'bbox' ,
begin : 'begin' ,
bias : 'bias' ,
by : 'by' ,
calcmode : 'calcMode' ,
capheight : 'capHeight' ,
'cap-height' : 'capHeight' ,
clip : 'clip' ,
clippath : 'clipPath' ,
'clip-path' : 'clipPath' ,
clippathunits : 'clipPathUnits' ,
cliprule : 'clipRule' ,
'clip-rule' : 'clipRule' ,
color : 'color' ,
colorinterpolation : 'colorInterpolation' ,
'color-interpolation' : 'colorInterpolation' ,
colorinterpolationfilters : 'colorInterpolationFilters' ,
'color-interpolation-filters' : 'colorInterpolationFilters' ,
colorprofile : 'colorProfile' ,
'color-profile' : 'colorProfile' ,
colorrendering : 'colorRendering' ,
'color-rendering' : 'colorRendering' ,
contentscripttype : 'contentScriptType' ,
contentstyletype : 'contentStyleType' ,
cursor : 'cursor' ,
cx : 'cx' ,
cy : 'cy' ,
d : 'd' ,
datatype : 'datatype' ,
decelerate : 'decelerate' ,
descent : 'descent' ,
diffuseconstant : 'diffuseConstant' ,
direction : 'direction' ,
display : 'display' ,
divisor : 'divisor' ,
dominantbaseline : 'dominantBaseline' ,
'dominant-baseline' : 'dominantBaseline' ,
dur : 'dur' ,
dx : 'dx' ,
dy : 'dy' ,
edgemode : 'edgeMode' ,
elevation : 'elevation' ,
enablebackground : 'enableBackground' ,
'enable-background' : 'enableBackground' ,
end : 'end' ,
exponent : 'exponent' ,
externalresourcesrequired : 'externalResourcesRequired' ,
fill : 'fill' ,
fillopacity : 'fillOpacity' ,
'fill-opacity' : 'fillOpacity' ,
fillrule : 'fillRule' ,
'fill-rule' : 'fillRule' ,
filter : 'filter' ,
filterres : 'filterRes' ,
filterunits : 'filterUnits' ,
floodopacity : 'floodOpacity' ,
'flood-opacity' : 'floodOpacity' ,
floodcolor : 'floodColor' ,
'flood-color' : 'floodColor' ,
focusable : 'focusable' ,
fontfamily : 'fontFamily' ,
'font-family' : 'fontFamily' ,
fontsize : 'fontSize' ,
'font-size' : 'fontSize' ,
fontsizeadjust : 'fontSizeAdjust' ,
'font-size-adjust' : 'fontSizeAdjust' ,
fontstretch : 'fontStretch' ,
'font-stretch' : 'fontStretch' ,
fontstyle : 'fontStyle' ,
'font-style' : 'fontStyle' ,
fontvariant : 'fontVariant' ,
'font-variant' : 'fontVariant' ,
fontweight : 'fontWeight' ,
'font-weight' : 'fontWeight' ,
format : 'format' ,
from : 'from' ,
fx : 'fx' ,
fy : 'fy' ,
g1 : 'g1' ,
g2 : 'g2' ,
glyphname : 'glyphName' ,
'glyph-name' : 'glyphName' ,
glyphorientationhorizontal : 'glyphOrientationHorizontal' ,
'glyph-orientation-horizontal' : 'glyphOrientationHorizontal' ,
glyphorientationvertical : 'glyphOrientationVertical' ,
'glyph-orientation-vertical' : 'glyphOrientationVertical' ,
glyphref : 'glyphRef' ,
gradienttransform : 'gradientTransform' ,
gradientunits : 'gradientUnits' ,
hanging : 'hanging' ,
horizadvx : 'horizAdvX' ,
'horiz-adv-x' : 'horizAdvX' ,
horizoriginx : 'horizOriginX' ,
'horiz-origin-x' : 'horizOriginX' ,
ideographic : 'ideographic' ,
imagerendering : 'imageRendering' ,
'image-rendering' : 'imageRendering' ,
in2 : 'in2' ,
'in' : 'in' ,
inlist : 'inlist' ,
intercept : 'intercept' ,
k1 : 'k1' ,
k2 : 'k2' ,
k3 : 'k3' ,
k4 : 'k4' ,
k : 'k' ,
kernelmatrix : 'kernelMatrix' ,
kernelunitlength : 'kernelUnitLength' ,
kerning : 'kerning' ,
keypoints : 'keyPoints' ,
keysplines : 'keySplines' ,
keytimes : 'keyTimes' ,
lengthadjust : 'lengthAdjust' ,
letterspacing : 'letterSpacing' ,
'letter-spacing' : 'letterSpacing' ,
lightingcolor : 'lightingColor' ,
'lighting-color' : 'lightingColor' ,
limitingconeangle : 'limitingConeAngle' ,
local : 'local' ,
markerend : 'markerEnd' ,
'marker-end' : 'markerEnd' ,
markerheight : 'markerHeight' ,
markermid : 'markerMid' ,
'marker-mid' : 'markerMid' ,
markerstart : 'markerStart' ,
'marker-start' : 'markerStart' ,
markerunits : 'markerUnits' ,
markerwidth : 'markerWidth' ,
mask : 'mask' ,
maskcontentunits : 'maskContentUnits' ,
maskunits : 'maskUnits' ,
mathematical : 'mathematical' ,
mode : 'mode' ,
numoctaves : 'numOctaves' ,
offset : 'offset' ,
opacity : 'opacity' ,
operator : 'operator' ,
order : 'order' ,
orient : 'orient' ,
orientation : 'orientation' ,
origin : 'origin' ,
overflow : 'overflow' ,
overlineposition : 'overlinePosition' ,
'overline-position' : 'overlinePosition' ,
overlinethickness : 'overlineThickness' ,
'overline-thickness' : 'overlineThickness' ,
paintorder : 'paintOrder' ,
'paint-order' : 'paintOrder' ,
panose1 : 'panose1' ,
'panose-1' : 'panose1' ,
pathlength : 'pathLength' ,
patterncontentunits : 'patternContentUnits' ,
patterntransform : 'patternTransform' ,
patternunits : 'patternUnits' ,
pointerevents : 'pointerEvents' ,
'pointer-events' : 'pointerEvents' ,
points : 'points' ,
pointsatx : 'pointsAtX' ,
pointsaty : 'pointsAtY' ,
pointsatz : 'pointsAtZ' ,
prefix : 'prefix' ,
preservealpha : 'preserveAlpha' ,
preserveaspectratio : 'preserveAspectRatio' ,
primitiveunits : 'primitiveUnits' ,
property : 'property' ,
r : 'r' ,
radius : 'radius' ,
refx : 'refX' ,
refy : 'refY' ,
renderingintent : 'renderingIntent' ,
'rendering-intent' : 'renderingIntent' ,
repeatcount : 'repeatCount' ,
repeatdur : 'repeatDur' ,
requiredextensions : 'requiredExtensions' ,
requiredfeatures : 'requiredFeatures' ,
resource : 'resource' ,
restart : 'restart' ,
result : 'result' ,
results : 'results' ,
rotate : 'rotate' ,
rx : 'rx' ,
ry : 'ry' ,
scale : 'scale' ,
security : 'security' ,
seed : 'seed' ,
shaperendering : 'shapeRendering' ,
'shape-rendering' : 'shapeRendering' ,
slope : 'slope' ,
spacing : 'spacing' ,
specularconstant : 'specularConstant' ,
specularexponent : 'specularExponent' ,
speed : 'speed' ,
spreadmethod : 'spreadMethod' ,
startoffset : 'startOffset' ,
stddeviation : 'stdDeviation' ,
stemh : 'stemh' ,
stemv : 'stemv' ,
stitchtiles : 'stitchTiles' ,
stopcolor : 'stopColor' ,
'stop-color' : 'stopColor' ,
stopopacity : 'stopOpacity' ,
'stop-opacity' : 'stopOpacity' ,
strikethroughposition : 'strikethroughPosition' ,
'strikethrough-position' : 'strikethroughPosition' ,
strikethroughthickness : 'strikethroughThickness' ,
'strikethrough-thickness' : 'strikethroughThickness' ,
string : 'string' ,
stroke : 'stroke' ,
strokedasharray : 'strokeDasharray' ,
'stroke-dasharray' : 'strokeDasharray' ,
strokedashoffset : 'strokeDashoffset' ,
'stroke-dashoffset' : 'strokeDashoffset' ,
strokelinecap : 'strokeLinecap' ,
'stroke-linecap' : 'strokeLinecap' ,
strokelinejoin : 'strokeLinejoin' ,
'stroke-linejoin' : 'strokeLinejoin' ,
strokemiterlimit : 'strokeMiterlimit' ,
'stroke-miterlimit' : 'strokeMiterlimit' ,
strokewidth : 'strokeWidth' ,
'stroke-width' : 'strokeWidth' ,
strokeopacity : 'strokeOpacity' ,
'stroke-opacity' : 'strokeOpacity' ,
suppresscontenteditablewarning : 'suppressContentEditableWarning' ,
2017-12-10 21:51:33 +01:00
suppresshydrationwarning : 'suppressHydrationWarning' ,
2017-10-14 18:40:54 +02:00
surfacescale : 'surfaceScale' ,
systemlanguage : 'systemLanguage' ,
tablevalues : 'tableValues' ,
targetx : 'targetX' ,
targety : 'targetY' ,
textanchor : 'textAnchor' ,
'text-anchor' : 'textAnchor' ,
textdecoration : 'textDecoration' ,
'text-decoration' : 'textDecoration' ,
textlength : 'textLength' ,
textrendering : 'textRendering' ,
'text-rendering' : 'textRendering' ,
to : 'to' ,
transform : 'transform' ,
'typeof' : 'typeof' ,
u1 : 'u1' ,
u2 : 'u2' ,
underlineposition : 'underlinePosition' ,
'underline-position' : 'underlinePosition' ,
underlinethickness : 'underlineThickness' ,
'underline-thickness' : 'underlineThickness' ,
unicode : 'unicode' ,
unicodebidi : 'unicodeBidi' ,
'unicode-bidi' : 'unicodeBidi' ,
unicoderange : 'unicodeRange' ,
'unicode-range' : 'unicodeRange' ,
unitsperem : 'unitsPerEm' ,
'units-per-em' : 'unitsPerEm' ,
unselectable : 'unselectable' ,
valphabetic : 'vAlphabetic' ,
'v-alphabetic' : 'vAlphabetic' ,
values : 'values' ,
vectoreffect : 'vectorEffect' ,
'vector-effect' : 'vectorEffect' ,
version : 'version' ,
vertadvy : 'vertAdvY' ,
'vert-adv-y' : 'vertAdvY' ,
vertoriginx : 'vertOriginX' ,
'vert-origin-x' : 'vertOriginX' ,
vertoriginy : 'vertOriginY' ,
'vert-origin-y' : 'vertOriginY' ,
vhanging : 'vHanging' ,
'v-hanging' : 'vHanging' ,
videographic : 'vIdeographic' ,
'v-ideographic' : 'vIdeographic' ,
viewbox : 'viewBox' ,
viewtarget : 'viewTarget' ,
visibility : 'visibility' ,
vmathematical : 'vMathematical' ,
'v-mathematical' : 'vMathematical' ,
vocab : 'vocab' ,
widths : 'widths' ,
wordspacing : 'wordSpacing' ,
'word-spacing' : 'wordSpacing' ,
writingmode : 'writingMode' ,
'writing-mode' : 'writingMode' ,
x1 : 'x1' ,
x2 : 'x2' ,
x : 'x' ,
xchannelselector : 'xChannelSelector' ,
xheight : 'xHeight' ,
'x-height' : 'xHeight' ,
xlinkactuate : 'xlinkActuate' ,
'xlink:actuate' : 'xlinkActuate' ,
xlinkarcrole : 'xlinkArcrole' ,
'xlink:arcrole' : 'xlinkArcrole' ,
xlinkhref : 'xlinkHref' ,
'xlink:href' : 'xlinkHref' ,
xlinkrole : 'xlinkRole' ,
'xlink:role' : 'xlinkRole' ,
xlinkshow : 'xlinkShow' ,
'xlink:show' : 'xlinkShow' ,
xlinktitle : 'xlinkTitle' ,
'xlink:title' : 'xlinkTitle' ,
xlinktype : 'xlinkType' ,
'xlink:type' : 'xlinkType' ,
xmlbase : 'xmlBase' ,
'xml:base' : 'xmlBase' ,
xmllang : 'xmlLang' ,
'xml:lang' : 'xmlLang' ,
xmlns : 'xmlns' ,
'xml:space' : 'xmlSpace' ,
xmlnsxlink : 'xmlnsXlink' ,
'xmlns:xlink' : 'xmlnsXlink' ,
xmlspace : 'xmlSpace' ,
y1 : 'y1' ,
y2 : 'y2' ,
y : 'y' ,
ychannelselector : 'yChannelSelector' ,
z : 'z' ,
zoomandpan : 'zoomAndPan'
} ;
2017-12-10 21:51:33 +01:00
function getStackAddendum$3 ( ) {
var stack = ReactDebugCurrentFrame . getStackAddendum ( ) ;
return stack != null ? stack : '' ;
2017-10-14 18:40:54 +02:00
}
{
var warnedProperties$1 = { } ;
var hasOwnProperty$1 = Object . prototype . hasOwnProperty ;
2017-12-10 21:51:33 +01:00
var EVENT _NAME _REGEX = /^on./ ;
var INVALID _EVENT _NAME _REGEX = /^on[^A-Z]/ ;
var rARIA$1 = new RegExp ( '^(aria)-[' + ATTRIBUTE _NAME _CHAR + ']*$' ) ;
var rARIACamel$1 = new RegExp ( '^(aria)[A-Z][' + ATTRIBUTE _NAME _CHAR + ']*$' ) ;
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
var validateProperty$1 = function ( tagName , name , value , canUseEventSystem ) {
2017-10-14 18:40:54 +02:00
if ( hasOwnProperty$1 . call ( warnedProperties$1 , name ) && warnedProperties$1 [ name ] ) {
return true ;
}
var lowerCasedName = name . toLowerCase ( ) ;
2017-12-10 21:51:33 +01:00
if ( lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout' ) {
warning ( false , 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.' ) ;
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
2017-12-10 21:51:33 +01:00
// We can't rely on the event system being injected on the server.
if ( canUseEventSystem ) {
if ( registrationNameModules . hasOwnProperty ( name ) ) {
return true ;
}
var registrationName = possibleRegistrationNames . hasOwnProperty ( lowerCasedName ) ? possibleRegistrationNames [ lowerCasedName ] : null ;
if ( registrationName != null ) {
warning ( false , 'Invalid event handler property `%s`. Did you mean `%s`?%s' , name , registrationName , getStackAddendum$3 ( ) ) ;
warnedProperties$1 [ name ] = true ;
return true ;
}
if ( EVENT _NAME _REGEX . test ( name ) ) {
warning ( false , 'Unknown event handler property `%s`. It will be ignored.%s' , name , getStackAddendum$3 ( ) ) ;
warnedProperties$1 [ name ] = true ;
return true ;
}
} else if ( EVENT _NAME _REGEX . test ( name ) ) {
// If no event plugins have been injected, we are in a server environment.
// So we can't tell if the event name is correct for sure, but we can filter
// out known bad ones like `onclick`. We can't suggest a specific replacement though.
if ( INVALID _EVENT _NAME _REGEX . test ( name ) ) {
warning ( false , 'Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.%s' , name , getStackAddendum$3 ( ) ) ;
}
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
// Let the ARIA attribute hook validate ARIA attributes
if ( rARIA$1 . test ( name ) || rARIACamel$1 . test ( name ) ) {
return true ;
}
if ( lowerCasedName === 'innerhtml' ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.' ) ;
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
if ( lowerCasedName === 'aria' ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.' ) ;
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
if ( lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string' ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Received a `%s` for a string attribute `is`. If this is expected, cast ' + 'the value to a string.%s' , typeof value , getStackAddendum$3 ( ) ) ;
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
if ( typeof value === 'number' && isNaN ( value ) ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.%s' , name , getStackAddendum$3 ( ) ) ;
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
2017-12-10 21:51:33 +01:00
var isReserved = isReservedProp ( name ) ;
2017-10-14 18:40:54 +02:00
// Known attributes should match the casing specified in the property config.
if ( possibleStandardNames . hasOwnProperty ( lowerCasedName ) ) {
var standardName = possibleStandardNames [ lowerCasedName ] ;
if ( standardName !== name ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Invalid DOM property `%s`. Did you mean `%s`?%s' , name , standardName , getStackAddendum$3 ( ) ) ;
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
} else if ( ! isReserved && name !== lowerCasedName ) {
// Unknown attributes should have lowercase casing since that's how they
// will be cased anyway with server rendering.
2017-12-10 21:51:33 +01:00
warning ( false , 'React does not recognize the `%s` prop on a DOM element. If you ' + 'intentionally want it to appear in the DOM as a custom ' + 'attribute, spell it as lowercase `%s` instead. ' + 'If you accidentally passed it from a parent component, remove ' + 'it from the DOM element.%s' , name , lowerCasedName , getStackAddendum$3 ( ) ) ;
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
2017-12-10 21:51:33 +01:00
if ( typeof value === 'boolean' && ! shouldAttributeAcceptBooleanValue ( name ) ) {
if ( value ) {
warning ( false , 'Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.%s' , value , name , name , value , name , getStackAddendum$3 ( ) ) ;
} else {
warning ( false , 'Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.%s' , value , name , name , value , name , name , name , getStackAddendum$3 ( ) ) ;
}
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return true ;
}
// Now that we've validated casing, do not validate
// data types for reserved props
if ( isReserved ) {
return true ;
}
// Warn when a known attribute is a bad type
2017-12-10 21:51:33 +01:00
if ( ! shouldSetAttribute ( name , value ) ) {
2017-10-14 18:40:54 +02:00
warnedProperties$1 [ name ] = true ;
return false ;
}
return true ;
} ;
}
2017-12-10 21:51:33 +01:00
var warnUnknownProperties = function ( type , props , canUseEventSystem ) {
2017-10-14 18:40:54 +02:00
var unknownProps = [ ] ;
for ( var key in props ) {
2017-12-10 21:51:33 +01:00
var isValid = validateProperty$1 ( type , key , props [ key ] , canUseEventSystem ) ;
2017-10-14 18:40:54 +02:00
if ( ! isValid ) {
unknownProps . push ( key ) ;
}
}
var unknownPropString = unknownProps . map ( function ( prop ) {
return '`' + prop + '`' ;
} ) . join ( ', ' ) ;
if ( unknownProps . length === 1 ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Invalid value for prop %s on <%s> tag. Either remove it from the element, ' + 'or pass a string or number value to keep it in the DOM. ' + 'For details, see https://fb.me/react-attribute-behavior%s' , unknownPropString , type , getStackAddendum$3 ( ) ) ;
2017-10-14 18:40:54 +02:00
} else if ( unknownProps . length > 1 ) {
2017-12-10 21:51:33 +01:00
warning ( false , 'Invalid values for props %s on <%s> tag. Either remove them from the element, ' + 'or pass a string or number value to keep them in the DOM. ' + 'For details, see https://fb.me/react-attribute-behavior%s' , unknownPropString , type , getStackAddendum$3 ( ) ) ;
2017-10-14 18:40:54 +02:00
}
} ;
2017-12-10 21:51:33 +01:00
function validateProperties$2 ( type , props , canUseEventSystem ) {
if ( isCustomComponent ( type , props ) ) {
2017-10-14 18:40:54 +02:00
return ;
}
2017-12-10 21:51:33 +01:00
warnUnknownProperties ( type , props , canUseEventSystem ) ;
2017-10-14 18:40:54 +02:00
}
function _classCallCheck ( instance , Constructor ) { if ( ! ( instance instanceof Constructor ) ) { throw new TypeError ( "Cannot call a class as a function" ) ; } }
2017-12-10 21:51:33 +01:00
// Based on reading the React.Children implementation. TODO: type this somewhere?
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
var toArray = React . Children . toArray ;
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
var getStackAddendum = emptyFunction . thatReturns ( '' ) ;
2017-10-14 18:40:54 +02:00
{
var validatePropertiesInDevelopment = function ( type , props ) {
2017-12-10 21:51:33 +01:00
validateProperties ( type , props ) ;
validateProperties$1 ( type , props ) ;
validateProperties$2 ( type , props , /* canUseEventSystem */ false ) ;
2017-10-14 18:40:54 +02:00
} ;
var describeStackFrame = function ( element ) {
var source = element . _source ;
var type = element . type ;
var name = getComponentName ( type ) ;
var ownerName = null ;
return describeComponentFrame ( name , source , ownerName ) ;
} ;
var currentDebugStack = null ;
var currentDebugElementStack = null ;
var setCurrentDebugStack = function ( stack ) {
2017-12-10 21:51:33 +01:00
var frame = stack [ stack . length - 1 ] ;
currentDebugElementStack = frame . debugElementStack ;
2017-10-14 18:40:54 +02:00
// We are about to enter a new composite stack, reset the array.
currentDebugElementStack . length = 0 ;
currentDebugStack = stack ;
ReactDebugCurrentFrame . getCurrentStack = getStackAddendum ;
} ;
var pushElementToDebugStack = function ( element ) {
if ( currentDebugElementStack !== null ) {
currentDebugElementStack . push ( element ) ;
}
} ;
var resetCurrentDebugStack = function ( ) {
currentDebugElementStack = null ;
currentDebugStack = null ;
ReactDebugCurrentFrame . getCurrentStack = null ;
} ;
2017-12-10 21:51:33 +01:00
getStackAddendum = function ( ) {
2017-10-14 18:40:54 +02:00
if ( currentDebugStack === null ) {
2017-12-10 21:51:33 +01:00
return '' ;
2017-10-14 18:40:54 +02:00
}
var stack = '' ;
var debugStack = currentDebugStack ;
for ( var i = debugStack . length - 1 ; i >= 0 ; i -- ) {
2017-12-10 21:51:33 +01:00
var frame = debugStack [ i ] ;
var _debugElementStack = frame . debugElementStack ;
for ( var ii = _debugElementStack . length - 1 ; ii >= 0 ; ii -- ) {
stack += describeStackFrame ( _debugElementStack [ ii ] ) ;
2017-10-14 18:40:54 +02:00
}
}
return stack ;
} ;
}
var didWarnDefaultInputValue = false ;
var didWarnDefaultChecked = false ;
var didWarnDefaultSelectValue = false ;
var didWarnDefaultTextareaValue = false ;
var didWarnInvalidOptionChildren = false ;
2017-12-10 21:51:33 +01:00
var didWarnAboutNoopUpdateForComponent = { } ;
2017-10-14 18:40:54 +02:00
var valuePropNames = [ 'value' , 'defaultValue' ] ;
var newlineEatingTags = {
listing : true ,
pre : true ,
textarea : true
} ;
function getComponentName ( type ) {
return typeof type === 'string' ? type : typeof type === 'function' ? type . displayName || type . name : null ;
}
// We accept any tag to be rendered but since this gets injected into arbitrary
// HTML, we want to make sure that it's a safe tag.
// http://www.w3.org/TR/REC-xml/#NT-Name
var VALID _TAG _REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/ ; // Simplified subset
var validatedTagCache = { } ;
function validateDangerousTag ( tag ) {
if ( ! validatedTagCache . hasOwnProperty ( tag ) ) {
! VALID _TAG _REGEX . test ( tag ) ? invariant ( false , 'Invalid tag: %s' , tag ) : void 0 ;
validatedTagCache [ tag ] = true ;
}
}
var processStyleName = memoizeStringOnly ( function ( styleName ) {
return hyphenateStyleName ( styleName ) ;
} ) ;
2017-12-10 21:51:33 +01:00
function createMarkupForStyles ( styles ) {
2017-10-14 18:40:54 +02:00
var serialized = '' ;
var delimiter = '' ;
for ( var styleName in styles ) {
if ( ! styles . hasOwnProperty ( styleName ) ) {
continue ;
}
var isCustomProperty = styleName . indexOf ( '--' ) === 0 ;
var styleValue = styles [ styleName ] ;
{
if ( ! isCustomProperty ) {
2017-12-10 21:51:33 +01:00
warnValidStyle$1 ( styleName , styleValue , getStackAddendum ) ;
2017-10-14 18:40:54 +02:00
}
}
if ( styleValue != null ) {
serialized += delimiter + processStyleName ( styleName ) + ':' ;
2017-12-10 21:51:33 +01:00
serialized += dangerousStyleValue ( styleName , styleValue , isCustomProperty ) ;
2017-10-14 18:40:54 +02:00
delimiter = ';' ;
}
}
return serialized || null ;
}
function warnNoop ( publicInstance , callerName ) {
{
var constructor = publicInstance . constructor ;
2017-12-10 21:51:33 +01:00
var componentName = constructor && getComponentName ( constructor ) || 'ReactClass' ;
var warningKey = componentName + '.' + callerName ;
if ( didWarnAboutNoopUpdateForComponent [ warningKey ] ) {
return ;
}
warning ( false , '%s(...): Can only update a mounting component. ' + 'This usually means you called %s() outside componentWillMount() on the server. ' + 'This is a no-op.\n\nPlease check the code for the %s component.' , callerName , callerName , componentName ) ;
didWarnAboutNoopUpdateForComponent [ warningKey ] = true ;
2017-10-14 18:40:54 +02:00
}
}
function shouldConstruct ( Component ) {
return Component . prototype && Component . prototype . isReactComponent ;
}
function getNonChildrenInnerMarkup ( props ) {
var innerHTML = props . dangerouslySetInnerHTML ;
if ( innerHTML != null ) {
if ( innerHTML . _ _html != null ) {
return innerHTML . _ _html ;
}
} else {
var content = props . children ;
if ( typeof content === 'string' || typeof content === 'number' ) {
2017-12-10 21:51:33 +01:00
return escapeTextForBrowser ( content ) ;
2017-10-14 18:40:54 +02:00
}
}
return null ;
}
2017-12-10 21:51:33 +01:00
function flattenTopLevelChildren ( children ) {
if ( ! React . isValidElement ( children ) ) {
return toArray ( children ) ;
}
var element = children ;
if ( element . type !== REACT _FRAGMENT _TYPE ) {
return [ element ] ;
}
var fragmentChildren = element . props . children ;
if ( ! React . isValidElement ( fragmentChildren ) ) {
return toArray ( fragmentChildren ) ;
}
var fragmentChildElement = fragmentChildren ;
return [ fragmentChildElement ] ;
}
2017-10-14 18:40:54 +02:00
function flattenOptionChildren ( children ) {
var content = '' ;
// Flatten children and warn if they aren't strings or numbers;
// invalid types are ignored.
2017-12-10 21:51:33 +01:00
React . Children . forEach ( children , function ( child ) {
2017-10-14 18:40:54 +02:00
if ( child == null ) {
return ;
}
if ( typeof child === 'string' || typeof child === 'number' ) {
content += child ;
} else {
{
if ( ! didWarnInvalidOptionChildren ) {
didWarnInvalidOptionChildren = true ;
warning ( false , 'Only strings and numbers are supported as <option> children.' ) ;
}
}
}
} ) ;
return content ;
}
function maskContext ( type , context ) {
var contextTypes = type . contextTypes ;
if ( ! contextTypes ) {
return emptyObject ;
}
var maskedContext = { } ;
for ( var contextName in contextTypes ) {
maskedContext [ contextName ] = context [ contextName ] ;
}
return maskedContext ;
}
function checkContextTypes ( typeSpecs , values , location ) {
{
2017-12-10 21:51:33 +01:00
checkPropTypes ( typeSpecs , values , location , 'Component' , getStackAddendum ) ;
2017-10-14 18:40:54 +02:00
}
}
function processContext ( type , context ) {
var maskedContext = maskContext ( type , context ) ;
{
if ( type . contextTypes ) {
checkContextTypes ( type . contextTypes , maskedContext , 'context' ) ;
}
}
return maskedContext ;
}
var STYLE = 'style' ;
2017-12-10 21:51:33 +01:00
var RESERVED _PROPS$1 = {
2017-10-14 18:40:54 +02:00
children : null ,
dangerouslySetInnerHTML : null ,
2017-12-10 21:51:33 +01:00
suppressContentEditableWarning : null ,
suppressHydrationWarning : null
2017-10-14 18:40:54 +02:00
} ;
2017-12-10 21:51:33 +01:00
function createOpenTagMarkup ( tagVerbatim , tagLowercase , props , namespace , makeStaticMarkup , isRootElement ) {
2017-10-14 18:40:54 +02:00
var ret = '<' + tagVerbatim ;
for ( var propKey in props ) {
if ( ! props . hasOwnProperty ( propKey ) ) {
continue ;
}
var propValue = props [ propKey ] ;
if ( propValue == null ) {
continue ;
}
if ( propKey === STYLE ) {
2017-12-10 21:51:33 +01:00
propValue = createMarkupForStyles ( propValue ) ;
2017-10-14 18:40:54 +02:00
}
var markup = null ;
2017-12-10 21:51:33 +01:00
if ( isCustomComponent ( tagLowercase , props ) ) {
if ( ! RESERVED _PROPS$1 . hasOwnProperty ( propKey ) ) {
markup = createMarkupForCustomAttribute ( propKey , propValue ) ;
2017-10-14 18:40:54 +02:00
}
} else {
2017-12-10 21:51:33 +01:00
markup = createMarkupForProperty ( propKey , propValue ) ;
2017-10-14 18:40:54 +02:00
}
if ( markup ) {
ret += ' ' + markup ;
}
}
// For static pages, no need to put React ID and checksum. Saves lots of
// bytes.
if ( makeStaticMarkup ) {
return ret ;
}
if ( isRootElement ) {
2017-12-10 21:51:33 +01:00
ret += ' ' + createMarkupForRoot ( ) ;
2017-10-14 18:40:54 +02:00
}
return ret ;
}
function validateRenderResult ( child , type ) {
if ( child === undefined ) {
invariant ( false , '%s(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.' , getComponentName ( type ) || 'Component' ) ;
}
}
function resolve ( child , context ) {
2017-12-10 21:51:33 +01:00
while ( React . isValidElement ( child ) ) {
// Safe because we just checked it's an element.
var element = child ;
2017-10-14 18:40:54 +02:00
{
2017-12-10 21:51:33 +01:00
pushElementToDebugStack ( element ) ;
2017-10-14 18:40:54 +02:00
}
2017-12-10 21:51:33 +01:00
var Component = element . type ;
2017-10-14 18:40:54 +02:00
if ( typeof Component !== 'function' ) {
break ;
}
var publicContext = processContext ( Component , context ) ;
var inst ;
var queue = [ ] ;
var replace = false ;
var updater = {
isMounted : function ( publicInstance ) {
return false ;
} ,
enqueueForceUpdate : function ( publicInstance ) {
if ( queue === null ) {
warnNoop ( publicInstance , 'forceUpdate' ) ;
return null ;
}
} ,
enqueueReplaceState : function ( publicInstance , completeState ) {
replace = true ;
queue = [ completeState ] ;
} ,
enqueueSetState : function ( publicInstance , partialState ) {
if ( queue === null ) {
warnNoop ( publicInstance , 'setState' ) ;
return null ;
}
queue . push ( partialState ) ;
}
} ;
if ( shouldConstruct ( Component ) ) {
2017-12-10 21:51:33 +01:00
inst = new Component ( element . props , publicContext , updater ) ;
2017-10-14 18:40:54 +02:00
} else {
2017-12-10 21:51:33 +01:00
inst = Component ( element . props , publicContext , updater ) ;
2017-10-14 18:40:54 +02:00
if ( inst == null || inst . render == null ) {
child = inst ;
validateRenderResult ( child , Component ) ;
continue ;
}
}
2017-12-10 21:51:33 +01:00
inst . props = element . props ;
2017-10-14 18:40:54 +02:00
inst . context = publicContext ;
inst . updater = updater ;
var initialState = inst . state ;
if ( initialState === undefined ) {
inst . state = initialState = null ;
}
if ( inst . componentWillMount ) {
inst . componentWillMount ( ) ;
if ( queue . length ) {
var oldQueue = queue ;
var oldReplace = replace ;
queue = null ;
replace = false ;
if ( oldReplace && oldQueue . length === 1 ) {
inst . state = oldQueue [ 0 ] ;
} else {
var nextState = oldReplace ? oldQueue [ 0 ] : inst . state ;
var dontMutate = true ;
for ( var i = oldReplace ? 1 : 0 ; i < oldQueue . length ; i ++ ) {
var partial = oldQueue [ i ] ;
2017-12-10 21:51:33 +01:00
var partialState = typeof partial === 'function' ? partial . call ( inst , nextState , element . props , publicContext ) : partial ;
2017-10-14 18:40:54 +02:00
if ( partialState ) {
if ( dontMutate ) {
dontMutate = false ;
2017-12-10 21:51:33 +01:00
nextState = _assign ( { } , nextState , partialState ) ;
2017-10-14 18:40:54 +02:00
} else {
2017-12-10 21:51:33 +01:00
_assign ( nextState , partialState ) ;
2017-10-14 18:40:54 +02:00
}
}
}
inst . state = nextState ;
}
} else {
queue = null ;
}
}
child = inst . render ( ) ;
{
if ( child === undefined && inst . render . _isMockFunction ) {
// This is probably bad practice. Consider warning here and
// deprecating this convenience.
child = null ;
}
}
validateRenderResult ( child , Component ) ;
var childContext ;
if ( typeof inst . getChildContext === 'function' ) {
var childContextTypes = Component . childContextTypes ;
2017-12-10 21:51:33 +01:00
if ( typeof childContextTypes === 'object' ) {
childContext = inst . getChildContext ( ) ;
for ( var contextKey in childContext ) {
! ( contextKey in childContextTypes ) ? invariant ( false , '%s.getChildContext(): key "%s" is not defined in childContextTypes.' , getComponentName ( Component ) || 'Unknown' , contextKey ) : void 0 ;
}
} else {
warning ( false , '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().' , getComponentName ( Component ) || 'Unknown' ) ;
2017-10-14 18:40:54 +02:00
}
}
if ( childContext ) {
2017-12-10 21:51:33 +01:00
context = _assign ( { } , context , childContext ) ;
2017-10-14 18:40:54 +02:00
}
}
return { child : child , context : context } ;
}
var ReactDOMServerRenderer = function ( ) {
2017-12-10 21:51:33 +01:00
function ReactDOMServerRenderer ( children , makeStaticMarkup ) {
2017-10-14 18:40:54 +02:00
_classCallCheck ( this , ReactDOMServerRenderer ) ;
2017-12-10 21:51:33 +01:00
var flatChildren = flattenTopLevelChildren ( children ) ;
2017-10-14 18:40:54 +02:00
var topFrame = {
// Assume all trees start in the HTML namespace (not totally true, but
// this is what we did historically)
domNamespace : Namespaces . html ,
2017-12-10 21:51:33 +01:00
children : flatChildren ,
2017-10-14 18:40:54 +02:00
childIndex : 0 ,
context : emptyObject ,
footer : ''
} ;
{
topFrame . debugElementStack = [ ] ;
}
this . stack = [ topFrame ] ;
this . exhausted = false ;
this . currentSelectValue = null ;
this . previousWasTextNode = false ;
this . makeStaticMarkup = makeStaticMarkup ;
}
2017-12-10 21:51:33 +01:00
// TODO: type this more strictly:
2017-10-14 18:40:54 +02:00
ReactDOMServerRenderer . prototype . read = function read ( bytes ) {
if ( this . exhausted ) {
return null ;
}
var out = '' ;
while ( out . length < bytes ) {
if ( this . stack . length === 0 ) {
this . exhausted = true ;
break ;
}
var frame = this . stack [ this . stack . length - 1 ] ;
if ( frame . childIndex >= frame . children . length ) {
2017-12-10 21:51:33 +01:00
var footer = frame . footer ;
out += footer ;
if ( footer !== '' ) {
this . previousWasTextNode = false ;
}
2017-10-14 18:40:54 +02:00
this . stack . pop ( ) ;
if ( frame . tag === 'select' ) {
this . currentSelectValue = null ;
}
continue ;
}
var child = frame . children [ frame . childIndex ++ ] ;
{
setCurrentDebugStack ( this . stack ) ;
}
out += this . render ( child , frame . context , frame . domNamespace ) ;
{
// TODO: Handle reentrant server render calls. This doesn't.
resetCurrentDebugStack ( ) ;
}
}
return out ;
} ;
ReactDOMServerRenderer . prototype . render = function render ( child , context , parentNamespace ) {
if ( typeof child === 'string' || typeof child === 'number' ) {
var text = '' + child ;
if ( text === '' ) {
return '' ;
}
if ( this . makeStaticMarkup ) {
2017-12-10 21:51:33 +01:00
return escapeTextForBrowser ( text ) ;
2017-10-14 18:40:54 +02:00
}
if ( this . previousWasTextNode ) {
2017-12-10 21:51:33 +01:00
return '<!-- -->' + escapeTextForBrowser ( text ) ;
2017-10-14 18:40:54 +02:00
}
this . previousWasTextNode = true ;
2017-12-10 21:51:33 +01:00
return escapeTextForBrowser ( text ) ;
2017-10-14 18:40:54 +02:00
} else {
2017-12-10 21:51:33 +01:00
var nextChild ;
2017-10-14 18:40:54 +02:00
var _resolve = resolve ( child , context ) ;
2017-12-10 21:51:33 +01:00
nextChild = _resolve . child ;
2017-10-14 18:40:54 +02:00
context = _resolve . context ;
2017-12-10 21:51:33 +01:00
if ( nextChild === null || nextChild === false ) {
2017-10-14 18:40:54 +02:00
return '' ;
2017-12-10 21:51:33 +01:00
} else if ( ! React . isValidElement ( nextChild ) ) {
var nextChildren = toArray ( nextChild ) ;
var frame = {
domNamespace : parentNamespace ,
children : nextChildren ,
childIndex : 0 ,
context : context ,
footer : ''
} ;
{
frame . debugElementStack = [ ] ;
2017-10-14 18:40:54 +02:00
}
2017-12-10 21:51:33 +01:00
this . stack . push ( frame ) ;
return '' ;
} else if ( nextChild . type === REACT _FRAGMENT _TYPE ) {
var _nextChildren = toArray ( nextChild . props . children ) ;
var _frame = {
domNamespace : parentNamespace ,
children : _nextChildren ,
childIndex : 0 ,
context : context ,
footer : ''
} ;
{
_frame . debugElementStack = [ ] ;
}
this . stack . push ( _frame ) ;
return '' ;
} else {
// Safe because we just checked it's an element.
var nextElement = nextChild ;
return this . renderDOM ( nextElement , context , parentNamespace ) ;
2017-10-14 18:40:54 +02:00
}
}
} ;
ReactDOMServerRenderer . prototype . renderDOM = function renderDOM ( element , context , parentNamespace ) {
var tag = element . type . toLowerCase ( ) ;
var namespace = parentNamespace ;
if ( parentNamespace === Namespaces . html ) {
namespace = getIntrinsicNamespace ( tag ) ;
}
{
if ( namespace === Namespaces . html ) {
// Should this check be gated by parent namespace? Not sure we want to
// allow <SVG> or <mATH>.
warning ( tag === element . type , '<%s /> is using uppercase HTML. Always use lowercase HTML tags ' + 'in React.' , element . type ) ;
}
}
validateDangerousTag ( tag ) ;
var props = element . props ;
if ( tag === 'input' ) {
{
2017-12-10 21:51:33 +01:00
ReactControlledValuePropTypes . checkPropTypes ( 'input' , props , getStackAddendum ) ;
2017-10-14 18:40:54 +02:00
if ( props . checked !== undefined && props . defaultChecked !== undefined && ! didWarnDefaultChecked ) {
warning ( false , '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components' , 'A component' , props . type ) ;
didWarnDefaultChecked = true ;
}
if ( props . value !== undefined && props . defaultValue !== undefined && ! didWarnDefaultInputValue ) {
warning ( false , '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components' , 'A component' , props . type ) ;
didWarnDefaultInputValue = true ;
}
}
2017-12-10 21:51:33 +01:00
props = _assign ( {
2017-10-14 18:40:54 +02:00
type : undefined
} , props , {
defaultChecked : undefined ,
defaultValue : undefined ,
value : props . value != null ? props . value : props . defaultValue ,
checked : props . checked != null ? props . checked : props . defaultChecked
} ) ;
} else if ( tag === 'textarea' ) {
{
2017-12-10 21:51:33 +01:00
ReactControlledValuePropTypes . checkPropTypes ( 'textarea' , props , getStackAddendum ) ;
2017-10-14 18:40:54 +02:00
if ( props . value !== undefined && props . defaultValue !== undefined && ! didWarnDefaultTextareaValue ) {
warning ( false , 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components' ) ;
didWarnDefaultTextareaValue = true ;
}
}
var initialValue = props . value ;
if ( initialValue == null ) {
var defaultValue = props . defaultValue ;
// TODO (yungsters): Remove support for children content in <textarea>.
var textareaChildren = props . children ;
if ( textareaChildren != null ) {
{
warning ( false , 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.' ) ;
}
! ( defaultValue == null ) ? invariant ( false , 'If you supply `defaultValue` on a <textarea>, do not pass children.' ) : void 0 ;
if ( Array . isArray ( textareaChildren ) ) {
! ( textareaChildren . length <= 1 ) ? invariant ( false , '<textarea> can only have at most one child.' ) : void 0 ;
textareaChildren = textareaChildren [ 0 ] ;
}
defaultValue = '' + textareaChildren ;
}
if ( defaultValue == null ) {
defaultValue = '' ;
}
initialValue = defaultValue ;
}
2017-12-10 21:51:33 +01:00
props = _assign ( { } , props , {
2017-10-14 18:40:54 +02:00
value : undefined ,
children : '' + initialValue
} ) ;
} else if ( tag === 'select' ) {
{
2017-12-10 21:51:33 +01:00
ReactControlledValuePropTypes . checkPropTypes ( 'select' , props , getStackAddendum ) ;
2017-10-14 18:40:54 +02:00
for ( var i = 0 ; i < valuePropNames . length ; i ++ ) {
var propName = valuePropNames [ i ] ;
if ( props [ propName ] == null ) {
continue ;
}
var isArray = Array . isArray ( props [ propName ] ) ;
if ( props . multiple && ! isArray ) {
warning ( false , 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s' , propName , '' ) ;
} else if ( ! props . multiple && isArray ) {
warning ( false , 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s' , propName , '' ) ;
}
}
if ( props . value !== undefined && props . defaultValue !== undefined && ! didWarnDefaultSelectValue ) {
warning ( false , 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components' ) ;
didWarnDefaultSelectValue = true ;
}
}
this . currentSelectValue = props . value != null ? props . value : props . defaultValue ;
2017-12-10 21:51:33 +01:00
props = _assign ( { } , props , {
2017-10-14 18:40:54 +02:00
value : undefined
} ) ;
} else if ( tag === 'option' ) {
var selected = null ;
var selectValue = this . currentSelectValue ;
var optionChildren = flattenOptionChildren ( props . children ) ;
if ( selectValue != null ) {
var value ;
if ( props . value != null ) {
value = props . value + '' ;
} else {
value = optionChildren ;
}
selected = false ;
if ( Array . isArray ( selectValue ) ) {
// multiple
for ( var j = 0 ; j < selectValue . length ; j ++ ) {
if ( '' + selectValue [ j ] === value ) {
selected = true ;
break ;
}
}
} else {
selected = '' + selectValue === value ;
}
2017-12-10 21:51:33 +01:00
props = _assign ( {
2017-10-14 18:40:54 +02:00
selected : undefined ,
children : undefined
} , props , {
selected : selected ,
children : optionChildren
} ) ;
}
}
{
validatePropertiesInDevelopment ( tag , props ) ;
}
2017-12-10 21:51:33 +01:00
assertValidProps ( tag , props , getStackAddendum ) ;
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
var out = createOpenTagMarkup ( element . type , tag , props , namespace , this . makeStaticMarkup , this . stack . length === 1 ) ;
2017-10-14 18:40:54 +02:00
var footer = '' ;
2017-12-10 21:51:33 +01:00
if ( omittedCloseTags . hasOwnProperty ( tag ) ) {
2017-10-14 18:40:54 +02:00
out += '/>' ;
} else {
out += '>' ;
footer = '</' + element . type + '>' ;
}
var children ;
var innerMarkup = getNonChildrenInnerMarkup ( props ) ;
if ( innerMarkup != null ) {
children = [ ] ;
if ( newlineEatingTags [ tag ] && innerMarkup . charAt ( 0 ) === '\n' ) {
// text/html ignores the first character in these tags if it's a newline
// Prefer to break application/xml over text/html (for now) by adding
// a newline specifically to get eaten by the parser. (Alternately for
// textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
// \r is normalized out by HTMLTextAreaElement#value.)
// See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
// See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
// See: <http://www.w3.org/TR/html5/syntax.html#newlines>
// See: Parsing of "textarea" "listing" and "pre" elements
// from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
out += '\n' ;
}
out += innerMarkup ;
} else {
children = toArray ( props . children ) ;
}
var frame = {
domNamespace : getChildNamespace ( parentNamespace , element . type ) ,
tag : tag ,
children : children ,
childIndex : 0 ,
context : context ,
footer : footer
} ;
{
frame . debugElementStack = [ ] ;
}
this . stack . push ( frame ) ;
2017-12-10 21:51:33 +01:00
this . previousWasTextNode = false ;
2017-10-14 18:40:54 +02:00
return out ;
} ;
return ReactDOMServerRenderer ;
} ( ) ;
/ * *
* Render a ReactElement to its initial HTML . This should only be used on the
* server .
2017-12-10 21:51:33 +01:00
* See https : //reactjs.org/docs/react-dom-server.html#rendertostring
2017-10-14 18:40:54 +02:00
* /
function renderToString ( element ) {
2017-12-10 21:51:33 +01:00
var renderer = new ReactDOMServerRenderer ( element , false ) ;
2017-10-14 18:40:54 +02:00
var markup = renderer . read ( Infinity ) ;
return markup ;
}
/ * *
* Similar to renderToString , except this doesn ' t create extra DOM attributes
* such as data - react - id that React uses internally .
2017-12-10 21:51:33 +01:00
* See https : //reactjs.org/docs/react-dom-server.html#rendertostaticmarkup
2017-10-14 18:40:54 +02:00
* /
function renderToStaticMarkup ( element ) {
2017-12-10 21:51:33 +01:00
var renderer = new ReactDOMServerRenderer ( element , true ) ;
2017-10-14 18:40:54 +02:00
var markup = renderer . read ( Infinity ) ;
return markup ;
}
2017-12-10 21:51:33 +01:00
function renderToNodeStream ( ) {
invariant ( false , 'ReactDOMServer.renderToNodeStream(): The streaming API is not available in the browser. Use ReactDOMServer.renderToString() instead.' ) ;
}
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
function renderToStaticNodeStream ( ) {
invariant ( false , 'ReactDOMServer.renderToStaticNodeStream(): The streaming API is not available in the browser. Use ReactDOMServer.renderToStaticMarkup() instead.' ) ;
}
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
// Note: when changing this, also consider https://github.com/facebook/react/issues/11526
var ReactDOMServerBrowser = {
renderToString : renderToString ,
renderToStaticMarkup : renderToStaticMarkup ,
renderToNodeStream : renderToNodeStream ,
renderToStaticNodeStream : renderToStaticNodeStream ,
version : ReactVersion
2017-10-14 18:40:54 +02:00
} ;
2017-12-10 21:51:33 +01:00
var ReactDOMServerBrowser$1 = Object . freeze ( {
default : ReactDOMServerBrowser
2017-10-14 18:40:54 +02:00
} ) ;
2017-12-10 21:51:33 +01:00
var ReactDOMServer = ( ReactDOMServerBrowser$1 && ReactDOMServerBrowser ) || ReactDOMServerBrowser$1 ;
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest
var server _browser = ReactDOMServer [ 'default' ] ? ReactDOMServer [ 'default' ] : ReactDOMServer ;
2017-10-14 18:40:54 +02:00
2017-12-10 21:51:33 +01:00
module . exports = server _browser ;
} ) ( ) ;
2017-10-14 18:40:54 +02:00
}