diff --git a/docs/docs/ref-04-tags-and-attributes.md b/docs/docs/ref-04-tags-and-attributes.md
index 8481c75b1c430..6cb7207239a2d 100644
--- a/docs/docs/ref-04-tags-and-attributes.md
+++ b/docs/docs/ref-04-tags-and-attributes.md
@@ -86,6 +86,13 @@ There is also the React-specific attribute `dangerouslySetInnerHTML` ([more here
### SVG Attributes
-Any attributes passed to SVG tags are passed through without changes.
-
-React used to support special camelCase aliases for certain SVG attributes, such as `clipPath`. If you use them now you'll see a deprecation warning. These aliases will be removed in the next version in favor of their real names from the SVG specification, such as `clip-path`. Attributes that have a camelCase name in the spec, such as `gradientTransform`, will keep their names.
+```
+clipPath cx cy d dx dy fill fillOpacity fontFamily
+fontSize fx fy gradientTransform gradientUnits markerEnd
+markerMid markerStart offset opacity patternContentUnits
+patternUnits points preserveAspectRatio r rx ry spreadMethod
+stopColor stopOpacity stroke strokeDasharray strokeLinecap
+strokeOpacity strokeWidth textAnchor transform version
+viewBox x1 x2 x xlinkActuate xlinkArcrole xlinkHref xlinkRole
+xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace y1 y2 y
+```
diff --git a/src/renderers/dom/client/__tests__/ReactDOMSVG-test.js b/src/renderers/dom/client/__tests__/ReactDOMSVG-test.js
index ed24ad4acaec5..84fb2711f42ab 100644
--- a/src/renderers/dom/client/__tests__/ReactDOMSVG-test.js
+++ b/src/renderers/dom/client/__tests__/ReactDOMSVG-test.js
@@ -21,45 +21,6 @@ describe('ReactDOMSVG', function() {
ReactDOMServer = require('ReactDOMServer');
});
- it('creates initial markup for known hyphenated attributes', function() {
- var markup = ReactDOMServer.renderToString(
-
- );
- expect(markup).toContain('clip-path="url(#starlet)"');
- });
-
- it('creates initial markup for camel case attributes', function() {
- var markup = ReactDOMServer.renderToString(
-
- );
- expect(markup).toContain('viewBox="0 0 100 100"');
- });
-
- it('deprecates camel casing of hyphenated attributes', function() {
- spyOn(console, 'error');
- var markup = ReactDOMServer.renderToString(
-
- );
- expect(markup).toContain('clip-path="url(#starlet)"');
- expect(console.error.argsForCall.length).toBe(1);
- expect(console.error.argsForCall[0][0]).toContain('clipPath');
- expect(console.error.argsForCall[0][0]).toContain('clip-path');
- });
-
- it('creates initial markup for unknown hyphenated attributes', function() {
- var markup = ReactDOMServer.renderToString(
-
- );
- expect(markup).toContain('the-word="the-bird"');
- });
-
- it('creates initial markup for unknown camel case attributes', function() {
- var markup = ReactDOMServer.renderToString(
-
- );
- expect(markup).toContain('theWord="theBird"');
- });
-
it('creates initial namespaced markup', function() {
var markup = ReactDOMServer.renderToString(
diff --git a/src/renderers/dom/shared/DOMPropertyOperations.js b/src/renderers/dom/shared/DOMPropertyOperations.js
index dc0c3fb7f9eee..1ce9e29b753fb 100644
--- a/src/renderers/dom/shared/DOMPropertyOperations.js
+++ b/src/renderers/dom/shared/DOMPropertyOperations.js
@@ -126,31 +126,6 @@ var DOMPropertyOperations = {
return name + '=' + quoteAttributeValueForBrowser(value);
},
- /**
- * Creates markup for an SVG property.
- *
- * @param {string} name
- * @param {*} value
- * @return {string} Markup string, or empty string if the property was invalid.
- */
- createMarkupForSVGAttribute: function(name, value) {
- if (__DEV__) {
- ReactDOMInstrumentation.debugTool.onCreateMarkupForSVGAttribute(name, value);
- }
- if (!isAttributeNameSafe(name) || value == null) {
- return '';
- }
- var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ?
- DOMProperty.properties[name] : null;
- if (propertyInfo) {
- // Migration path for deprecated camelCase aliases for SVG attributes
- var { attributeName } = propertyInfo;
- return attributeName + '=' + quoteAttributeValueForBrowser(value);
- } else {
- return name + '=' + quoteAttributeValueForBrowser(value);
- }
- },
-
/**
* Sets the value for a property on a node.
*
@@ -210,18 +185,6 @@ var DOMPropertyOperations = {
}
},
- setValueForSVGAttribute: function(node, name, value) {
- if (__DEV__) {
- ReactDOMInstrumentation.debugTool.onSetValueForSVGAttribute(node, name, value);
- }
- if (DOMProperty.properties.hasOwnProperty(name)) {
- // Migration path for deprecated camelCase aliases for SVG attributes
- DOMPropertyOperations.setValueForProperty(node, name, value);
- } else {
- DOMPropertyOperations.setValueForAttribute(node, name, value);
- }
- },
-
/**
* Deletes the value for a property on a node.
*
@@ -257,16 +220,6 @@ var DOMPropertyOperations = {
}
},
- deleteValueForSVGAttribute: function(node, name) {
- var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ?
- DOMProperty.properties[name] : null;
- if (propertyInfo) {
- DOMPropertyOperations.deleteValueForProperty(node, name);
- } else {
- node.removeAttribute(name);
- }
- },
-
};
ReactPerf.measureMethods(DOMPropertyOperations, 'DOMPropertyOperations', {
diff --git a/src/renderers/dom/shared/HTMLDOMPropertyConfig.js b/src/renderers/dom/shared/HTMLDOMPropertyConfig.js
index b71aafc78a337..ce5e93cea6e1a 100644
--- a/src/renderers/dom/shared/HTMLDOMPropertyConfig.js
+++ b/src/renderers/dom/shared/HTMLDOMPropertyConfig.js
@@ -30,176 +30,176 @@ var HTMLDOMPropertyConfig = {
/**
* Standard Properties
*/
- accept: null,
- acceptCharset: null,
- accessKey: null,
- action: null,
+ accept: 0,
+ acceptCharset: 0,
+ accessKey: 0,
+ action: 0,
allowFullScreen: HAS_BOOLEAN_VALUE,
- allowTransparency: null,
- alt: null,
+ allowTransparency: 0,
+ alt: 0,
async: HAS_BOOLEAN_VALUE,
- autoComplete: null,
+ autoComplete: 0,
// autoFocus is polyfilled/normalized by AutoFocusUtils
// autoFocus: HAS_BOOLEAN_VALUE,
autoPlay: HAS_BOOLEAN_VALUE,
capture: HAS_BOOLEAN_VALUE,
- cellPadding: null,
- cellSpacing: null,
- charSet: null,
- challenge: null,
+ cellPadding: 0,
+ cellSpacing: 0,
+ charSet: 0,
+ challenge: 0,
checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- cite: null,
- classID: null,
- className: null,
+ cite: 0,
+ classID: 0,
+ className: 0,
cols: HAS_POSITIVE_NUMERIC_VALUE,
- colSpan: null,
- content: null,
- contentEditable: null,
- contextMenu: null,
+ colSpan: 0,
+ content: 0,
+ contentEditable: 0,
+ contextMenu: 0,
controls: HAS_BOOLEAN_VALUE,
- coords: null,
- crossOrigin: null,
- data: null, // For ` ` acts as `src`.
- dateTime: null,
+ coords: 0,
+ crossOrigin: 0,
+ data: 0, // For ` ` acts as `src`.
+ dateTime: 0,
default: HAS_BOOLEAN_VALUE,
defer: HAS_BOOLEAN_VALUE,
- dir: null,
+ dir: 0,
disabled: HAS_BOOLEAN_VALUE,
download: HAS_OVERLOADED_BOOLEAN_VALUE,
- draggable: null,
- encType: null,
- form: null,
- formAction: null,
- formEncType: null,
- formMethod: null,
+ draggable: 0,
+ encType: 0,
+ form: 0,
+ formAction: 0,
+ formEncType: 0,
+ formMethod: 0,
formNoValidate: HAS_BOOLEAN_VALUE,
- formTarget: null,
- frameBorder: null,
- headers: null,
- height: null,
+ formTarget: 0,
+ frameBorder: 0,
+ headers: 0,
+ height: 0,
hidden: HAS_BOOLEAN_VALUE,
- high: null,
- href: null,
- hrefLang: null,
- htmlFor: null,
- httpEquiv: null,
- icon: null,
- id: null,
- inputMode: null,
- integrity: null,
- is: null,
- keyParams: null,
- keyType: null,
- kind: null,
- label: null,
- lang: null,
- list: null,
+ high: 0,
+ href: 0,
+ hrefLang: 0,
+ htmlFor: 0,
+ httpEquiv: 0,
+ icon: 0,
+ id: 0,
+ inputMode: 0,
+ integrity: 0,
+ is: 0,
+ keyParams: 0,
+ keyType: 0,
+ kind: 0,
+ label: 0,
+ lang: 0,
+ list: 0,
loop: HAS_BOOLEAN_VALUE,
- low: null,
- manifest: null,
- marginHeight: null,
- marginWidth: null,
- max: null,
- maxLength: null,
- media: null,
- mediaGroup: null,
- method: null,
- min: null,
- minLength: null,
+ low: 0,
+ manifest: 0,
+ marginHeight: 0,
+ marginWidth: 0,
+ max: 0,
+ maxLength: 0,
+ media: 0,
+ mediaGroup: 0,
+ method: 0,
+ min: 0,
+ minLength: 0,
// 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,
- name: null,
- nonce: null,
+ name: 0,
+ nonce: 0,
noValidate: HAS_BOOLEAN_VALUE,
open: HAS_BOOLEAN_VALUE,
- optimum: null,
- pattern: null,
- placeholder: null,
- poster: null,
- preload: null,
- profile: null,
- radioGroup: null,
+ optimum: 0,
+ pattern: 0,
+ placeholder: 0,
+ poster: 0,
+ preload: 0,
+ profile: 0,
+ radioGroup: 0,
readOnly: HAS_BOOLEAN_VALUE,
- rel: null,
+ rel: 0,
required: HAS_BOOLEAN_VALUE,
reversed: HAS_BOOLEAN_VALUE,
- role: null,
+ role: 0,
rows: HAS_POSITIVE_NUMERIC_VALUE,
rowSpan: HAS_NUMERIC_VALUE,
- sandbox: null,
- scope: null,
+ sandbox: 0,
+ scope: 0,
scoped: HAS_BOOLEAN_VALUE,
- scrolling: null,
+ scrolling: 0,
seamless: HAS_BOOLEAN_VALUE,
selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- shape: null,
+ shape: 0,
size: HAS_POSITIVE_NUMERIC_VALUE,
- sizes: null,
+ sizes: 0,
span: HAS_POSITIVE_NUMERIC_VALUE,
- spellCheck: null,
- src: null,
- srcDoc: null,
- srcLang: null,
- srcSet: null,
+ spellCheck: 0,
+ src: 0,
+ srcDoc: 0,
+ srcLang: 0,
+ srcSet: 0,
start: HAS_NUMERIC_VALUE,
- step: null,
- style: null,
- summary: null,
- tabIndex: null,
- target: null,
- title: null,
+ step: 0,
+ style: 0,
+ summary: 0,
+ tabIndex: 0,
+ target: 0,
+ title: 0,
// Setting .type throws on non- tags
- type: null,
- useMap: null,
+ type: 0,
+ useMap: 0,
value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS,
- width: null,
- wmode: null,
- wrap: null,
+ width: 0,
+ wmode: 0,
+ wrap: 0,
/**
* RDFa Properties
*/
- about: null,
- datatype: null,
- inlist: null,
- prefix: null,
+ about: 0,
+ datatype: 0,
+ inlist: 0,
+ prefix: 0,
// property is also supported for OpenGraph in meta tags.
- property: null,
- resource: null,
- typeof: null,
- vocab: null,
+ property: 0,
+ resource: 0,
+ typeof: 0,
+ vocab: 0,
/**
* Non-standard Properties
*/
// autoCapitalize and autoCorrect are supported in Mobile Safari for
// keyboard hints.
- autoCapitalize: null,
- autoCorrect: null,
+ autoCapitalize: 0,
+ autoCorrect: 0,
// autoSave allows WebKit/Blink to persist values of input fields on page reloads
- autoSave: null,
+ autoSave: 0,
// color is for Safari mask-icon link
- color: null,
+ color: 0,
// itemProp, itemScope, itemType are for
// Microdata support. See http://schema.org/docs/gs.html
- itemProp: null,
+ itemProp: 0,
itemScope: HAS_BOOLEAN_VALUE,
- itemType: null,
+ itemType: 0,
// itemID and itemRef are for Microdata support as well but
// only specified in the WHATWG spec document. See
// https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api
- itemID: null,
- itemRef: null,
+ itemID: 0,
+ itemRef: 0,
// results show looking glass icon and recent searches on input
// search fields in WebKit/Blink
- results: null,
+ results: 0,
// IE-only attribute that specifies security restrictions on an iframe
// as an alternative to the sandbox attribute on IE<10
- security: null,
+ security: 0,
// IE-only attribute that controls focus behavior
- unselectable: null,
+ unselectable: 0,
},
DOMAttributeNames: {
acceptCharset: 'accept-charset',
diff --git a/src/renderers/dom/shared/ReactDOMComponent.js b/src/renderers/dom/shared/ReactDOMComponent.js
index 244d80b94fa35..21a43102300b4 100644
--- a/src/renderers/dom/shared/ReactDOMComponent.js
+++ b/src/renderers/dom/shared/ReactDOMComponent.js
@@ -53,13 +53,9 @@ var registrationNameModules = EventPluginRegistry.registrationNameModules;
// For quickly matching children type, to test if can be treated as content.
var CONTENT_TYPES = {'string': true, 'number': true};
+var CHILDREN = keyOf({children: null});
var STYLE = keyOf({style: null});
var HTML = keyOf({__html: null});
-var RESERVED_PROPS = {
- children: null,
- dangerouslySetInnerHTML: null,
- suppressContentEditableWarning: null,
-};
function getDeclarationErrorAddendum(internalInstance) {
if (internalInstance) {
@@ -639,13 +635,9 @@ ReactDOMComponent.Mixin = {
}
var markup = null;
if (this._tag != null && isCustomComponent(this._tag, props)) {
- if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
+ if (propKey !== CHILDREN) {
markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
}
- } else if (this._namespaceURI === DOMNamespaces.svg) {
- if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
- markup = DOMPropertyOperations.createMarkupForSVGAttribute(propKey, propValue);
- }
} else {
markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
}
@@ -857,11 +849,6 @@ ReactDOMComponent.Mixin = {
// listener (e.g., onClick={null})
deleteListener(this, propKey);
}
- } else if (this._namespaceURI === DOMNamespaces.svg) {
- DOMPropertyOperations.deleteValueForSVGAttribute(
- getNode(this),
- propKey
- );
} else if (
DOMProperty.properties[propKey] ||
DOMProperty.isCustomAttribute(propKey)) {
@@ -920,21 +907,14 @@ ReactDOMComponent.Mixin = {
deleteListener(this, propKey);
}
} else if (isCustomComponent(this._tag, nextProps)) {
- if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
- DOMPropertyOperations.setValueForAttribute(
- getNode(this),
- propKey,
- nextProp
- );
- }
- } else if (this._namespaceURI === DOMNamespaces.svg) {
- if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
- DOMPropertyOperations.setValueForSVGAttribute(
- getNode(this),
- propKey,
- nextProp
- );
+ if (propKey === CHILDREN) {
+ nextProp = null;
}
+ DOMPropertyOperations.setValueForAttribute(
+ getNode(this),
+ propKey,
+ nextProp
+ );
} else if (
DOMProperty.properties[propKey] ||
DOMProperty.isCustomAttribute(propKey)) {
diff --git a/src/renderers/dom/shared/ReactDOMDebugTool.js b/src/renderers/dom/shared/ReactDOMDebugTool.js
index 6933080298ba4..9fcc3763fadb1 100644
--- a/src/renderers/dom/shared/ReactDOMDebugTool.js
+++ b/src/renderers/dom/shared/ReactDOMDebugTool.js
@@ -12,8 +12,6 @@
'use strict';
var ReactDOMUnknownPropertyDevtool = require('ReactDOMUnknownPropertyDevtool');
-var ReactDOMSVGDeprecatedAttributeDevtool =
- require('ReactDOMSVGDeprecatedAttributeDevtool');
var warning = require('warning');
@@ -55,21 +53,14 @@ var ReactDOMDebugTool = {
onCreateMarkupForProperty(name, value) {
emitEvent('onCreateMarkupForProperty', name, value);
},
- onCreateMarkupForSVGAttribute(name, value) {
- emitEvent('onCreateMarkupForSVGAttribute', name, value);
- },
onSetValueForProperty(node, name, value) {
emitEvent('onSetValueForProperty', node, name, value);
},
- onSetValueForSVGAttribute(node, name, value) {
- emitEvent('onSetValueForSVGAttribute', node, name, value);
- },
onDeleteValueForProperty(node, name) {
emitEvent('onDeleteValueForProperty', node, name);
},
};
ReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool);
-ReactDOMDebugTool.addDevtool(ReactDOMSVGDeprecatedAttributeDevtool);
module.exports = ReactDOMDebugTool;
diff --git a/src/renderers/dom/shared/SVGDOMPropertyConfig.js b/src/renderers/dom/shared/SVGDOMPropertyConfig.js
index effa92f76959c..bd90451c0926d 100644
--- a/src/renderers/dom/shared/SVGDOMPropertyConfig.js
+++ b/src/renderers/dom/shared/SVGDOMPropertyConfig.js
@@ -16,33 +16,263 @@ var NS = {
xml: 'http://www.w3.org/XML/1998/namespace',
};
+// We use attributes for everything SVG so let's avoid some duplication and run
+// code instead.
+// The following are all specified in the HTML config already so we exclude here.
+// - class (as className)
+// - color
+// - height
+// - id
+// - lang
+// - max
+// - media
+// - method
+// - min
+// - name
+// - style
+// - target
+// - type
+// - width
+var ATTRS = {
+ accentHeight: 'accent-height',
+ accumulate: 0,
+ additive: 0,
+ alignmentBaseline: 'alignment-baseline',
+ allowReorder: 'allowReorder',
+ alphabetic: 0,
+ amplitude: 0,
+ arabicForm: 'arabic-form',
+ ascent: 0,
+ attributeName: 'attributeName',
+ attributeType: 'attributeType',
+ autoReverse: 'autoReverse',
+ azimuth: 0,
+ baseFrequency: 'baseFrequency',
+ baseProfile: 'baseProfile',
+ baselineShift: 'baseline-shift',
+ bbox: 0,
+ begin: 0,
+ bias: 0,
+ by: 0,
+ calcMode: 'calcMode',
+ capHeight: 'cap-height',
+ clip: 0,
+ clipPath: 'clip-path',
+ clipRule: 'clip-rule',
+ clipPathUnits: 'clipPathUnits',
+ colorInterpolation: 'color-interpolation',
+ colorInterpolationFilters: 'color-interpolation-filters',
+ colorProfile: 'color-profile',
+ colorRendering: 'color-rendering',
+ contentScriptType: 'contentScriptType',
+ contentStyleType: 'contentStyleType',
+ cursor: 0,
+ cx: 0,
+ cy: 0,
+ d: 0,
+ decelerate: 0,
+ descent: 0,
+ diffuseConstant: 'diffuseConstant',
+ direction: 0,
+ display: 0,
+ divisor: 0,
+ dominantBaseline: 'dominant-baseline',
+ dur: 0,
+ dx: 0,
+ dy: 0,
+ edgeMode: 'edgeMode',
+ elevation: 0,
+ enableBackground: 'enable-background',
+ end: 0,
+ exponent: 0,
+ externalResourcesRequired: 'externalResourcesRequired',
+ fill: 0,
+ fillOpacity: 'fill-opacity',
+ fillRule: 'fill-rule',
+ filter: 0,
+ filterRes: 'filterRes',
+ filterUnits: 'filterUnits',
+ floodColor: 'flood-color',
+ floodOpacity: 'flood-opacity',
+ fontFamily: 'font-family',
+ fontSize: 'font-size',
+ fontSizeAdjust: 'font-size-adjust',
+ fontStretch: 'font-stretch',
+ fontStyle: 'font-style',
+ fontVariant: 'font-variant',
+ fontWeight: 'font-weight',
+ format: 0,
+ from: 0,
+ fx: 0,
+ fy: 0,
+ g1: 0,
+ g2: 0,
+ glyphName: 'glyph-name',
+ glyphOrientationHorizontal: 'glyph-orientation-horizontal',
+ glyphOrientationVertical: 'glyph-orientation-vertical',
+ glyphRef: 'glyphRef',
+ gradientTransform: 'gradientTransform',
+ gradientUnits: 'gradientUnits',
+ hanging: 0,
+ horizAdvX: 'horiz-adv-x',
+ horizOriginX: 'horiz-origin-x',
+ ideographic: 0,
+ imageRendering: 'image-rendering',
+ in: 0,
+ in2: 0,
+ intercept: 0,
+ k: 0,
+ k1: 0,
+ k2: 0,
+ k3: 0,
+ k4: 0,
+ kernelMatrix: 'kernelMatrix',
+ kernelUnitLength: 'kernelUnitLength',
+ kerning: 0,
+ keyPoints: 'keyPoints',
+ keySplines: 'keySplines',
+ keyTimes: 'keyTimes',
+ lengthAdjust: 'lengthAdjust',
+ letterSpacing: 'letter-spacing',
+ lightingColor: 'lighting-color',
+ limitingConeAngle: 'limitingConeAngle',
+ local: 0,
+ markerEnd: 'marker-end',
+ markerMid: 'marker-mid',
+ markerStart: 'marker-start',
+ markerHeight: 'markerHeight',
+ markerUnits: 'markerUnits',
+ markerWidth: 'markerWidth',
+ mask: 0,
+ maskContentUnits: 'maskContentUnits',
+ maskUnits: 'maskUnits',
+ mathematical: 0,
+ mode: 0,
+ numOctaves: 'numOctaves',
+ offset: 0,
+ opacity: 0,
+ operator: 0,
+ order: 0,
+ orient: 0,
+ orientation: 0,
+ origin: 0,
+ overflow: 0,
+ overlinePosition: 'overline-position',
+ overlineThickness: 'overline-thickness',
+ paintOrder: 'paint-order',
+ panose1: 'panose-1',
+ pathLength: 'pathLength',
+ patternContentUnits: 'patternContentUnits',
+ patternTransform: 'patternTransform',
+ patternUnits: 'patternUnits',
+ pointerEvents: 'pointer-events',
+ points: 0,
+ pointsAtX: 'pointsAtX',
+ pointsAtY: 'pointsAtY',
+ pointsAtZ: 'pointsAtZ',
+ preserveAlpha: 'preserveAlpha',
+ preserveAspectRatio: 'preserveAspectRatio',
+ primitiveUnits: 'primitiveUnits',
+ r: 0,
+ radius: 0,
+ refX: 'refX',
+ refY: 'refY',
+ renderingIntent: 'rendering-intent',
+ repeatCount: 'repeatCount',
+ repeatDur: 'repeatDur',
+ requiredExtensions: 'requiredExtensions',
+ requiredFeatures: 'requiredFeatures',
+ restart: 0,
+ result: 0,
+ rotate: 0,
+ rx: 0,
+ ry: 0,
+ scale: 0,
+ seed: 0,
+ shapeRendering: 'shape-rendering',
+ slope: 0,
+ spacing: 0,
+ specularConstant: 'specularConstant',
+ specularExponent: 'specularExponent',
+ speed: 0,
+ spreadMethod: 'spreadMethod',
+ startOffset: 'startOffset',
+ stdDeviation: 'stdDeviation',
+ stemh: 0,
+ stemv: 0,
+ stitchTiles: 'stitchTiles',
+ stopColor: 'stop-color',
+ stopOpacity: 'stop-opacity',
+ strikethroughPosition: 'strikethrough-position',
+ strikethroughThickness: 'strikethrough-thickness',
+ string: 0,
+ stroke: 0,
+ strokeDasharray: 'stroke-dasharray',
+ strokeDashoffset: 'stroke-dashoffset',
+ strokeLinecap: 'stroke-linecap',
+ strokeLinejoin: 'stroke-linejoin',
+ strokeMiterlimit: 'stroke-miterlimit',
+ strokeOpacity: 'stroke-opacity',
+ strokeWidth: 'stroke-width',
+ surfaceScale: 'surfaceScale',
+ systemLanguage: 'systemLanguage',
+ tableValues: 'tableValues',
+ targetX: 'targetX',
+ targetY: 'targetY',
+ textAnchor: 'text-anchor',
+ textDecoration: 'text-decoration',
+ textRendering: 'text-rendering',
+ textLength: 'textLength',
+ to: 0,
+ transform: 0,
+ u1: 0,
+ u2: 0,
+ underlinePosition: 'underline-position',
+ underlineThickness: 'underline-thickness',
+ unicode: 0,
+ unicodeBidi: 'unicode-bidi',
+ unicodeRange: 'unicode-range',
+ unitsPerEm: 'units-per-em',
+ vAlphabetic: 'v-alphabetic',
+ vHanging: 'v-hanging',
+ vIdeographic: 'v-ideographic',
+ vMathematical: 'v-mathematical',
+ values: 0,
+ version: 0,
+ vertAdvY: 'vert-adv-y',
+ vertOriginX: 'vert-origin-x',
+ vertOriginY: 'vert-origin-y',
+ viewBox: 'viewBox',
+ viewTarget: 'viewTarget',
+ visibility: 0,
+ widths: 0,
+ wordSpacing: 'word-spacing',
+ writingMode: 'writing-mode',
+ x: 0,
+ xHeight: 'x-height',
+ x1: 0,
+ x2: 0,
+ xChannelSelector: 'xChannelSelector',
+ xlinkActuate: 'xlink:actuate',
+ xlinkArcrole: 'xlink:arcrole',
+ xlinkHref: 'xlink:href',
+ xlinkRole: 'xlink:role',
+ xlinkShow: 'xlink:show',
+ xlinkTitle: 'xlink:title',
+ xlinkType: 'xlink:type',
+ xmlBase: 'xml:base',
+ xmlLang: 'xml:lang',
+ xmlSpace: 'xml:space',
+ y: 0,
+ y1: 0,
+ y2: 0,
+ yChannelSelector: 'yChannelSelector',
+ z: 0,
+ zoomAndPan: 'zoomAndPan',
+};
+
var SVGDOMPropertyConfig = {
- Properties: {
- clipPath: null,
- fillOpacity: null,
- fontFamily: null,
- fontSize: null,
- markerEnd: null,
- markerMid: null,
- markerStart: null,
- stopColor: null,
- stopOpacity: null,
- strokeDasharray: null,
- strokeLinecap: null,
- strokeOpacity: null,
- strokeWidth: null,
- textAnchor: null,
- xlinkActuate: null,
- xlinkArcrole: null,
- xlinkHref: null,
- xlinkRole: null,
- xlinkShow: null,
- xlinkTitle: null,
- xlinkType: null,
- xmlBase: null,
- xmlLang: null,
- xmlSpace: null,
- },
+ Properties: {},
DOMAttributeNamespaces: {
xlinkActuate: NS.xlink,
xlinkArcrole: NS.xlink,
@@ -55,32 +285,14 @@ var SVGDOMPropertyConfig = {
xmlLang: NS.xml,
xmlSpace: NS.xml,
},
- DOMAttributeNames: {
- clipPath: 'clip-path',
- fillOpacity: 'fill-opacity',
- fontFamily: 'font-family',
- fontSize: 'font-size',
- markerEnd: 'marker-end',
- markerMid: 'marker-mid',
- markerStart: 'marker-start',
- stopColor: 'stop-color',
- stopOpacity: 'stop-opacity',
- strokeDasharray: 'stroke-dasharray',
- strokeLinecap: 'stroke-linecap',
- strokeOpacity: 'stroke-opacity',
- strokeWidth: 'stroke-width',
- textAnchor: 'text-anchor',
- xlinkActuate: 'xlink:actuate',
- xlinkArcrole: 'xlink:arcrole',
- xlinkHref: 'xlink:href',
- xlinkRole: 'xlink:role',
- xlinkShow: 'xlink:show',
- xlinkTitle: 'xlink:title',
- xlinkType: 'xlink:type',
- xmlBase: 'xml:base',
- xmlLang: 'xml:lang',
- xmlSpace: 'xml:space',
- },
+ DOMAttributeNames: {},
};
+Object.keys(ATTRS).map((key) => {
+ SVGDOMPropertyConfig.Properties[key] = 0;
+ if (ATTRS[key]) {
+ SVGDOMPropertyConfig.DOMAttributeNames[key] = ATTRS[key];
+ }
+});
+
module.exports = SVGDOMPropertyConfig;
diff --git a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
index 1e07d5a4c2086..d349620b4711f 100644
--- a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
+++ b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
@@ -17,14 +17,12 @@ describe('ReactDOMComponent', function() {
var React;
var ReactDOM;
- var ReactDOMFeatureFlags;
var ReactDOMServer;
beforeEach(function() {
jest.resetModuleRegistry();
React = require('React');
ReactDOM = require('ReactDOM');
- ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
ReactDOMServer = require('ReactDOMServer');
});
@@ -238,100 +236,16 @@ describe('ReactDOMComponent', function() {
expect(stubStyle.display).toEqual('');
});
- it('should skip reserved props on web components', function() {
+ it('should skip child object attribute on web components', function() {
var container = document.createElement('div');
- ReactDOM.render(
- ,
- container
- );
+ // Test initial render to null
+ ReactDOM.render( , container);
expect(container.firstChild.hasAttribute('children')).toBe(false);
- expect(
- container.firstChild.hasAttribute('suppressContentEditableWarning')
- ).toBe(false);
- ReactDOM.render(
- ,
- container
- );
+ // Test updates to null
+ ReactDOM.render( , container);
expect(container.firstChild.hasAttribute('children')).toBe(false);
- expect(
- container.firstChild.hasAttribute('suppressContentEditableWarning')
- ).toBe(false);
- });
-
- it('should skip dangerouslySetInnerHTML on web components', function() {
- var container = document.createElement('div');
-
- ReactDOM.render(
- ,
- container
- );
- expect(
- container.firstChild.hasAttribute('dangerouslySetInnerHTML')
- ).toBe(false);
-
- ReactDOM.render(
- ,
- container
- );
- expect(
- container.firstChild.hasAttribute('dangerouslySetInnerHTML')
- ).toBe(false);
- });
-
- it('should skip reserved props on SVG components', function() {
- var container = document.createElement('div');
-
- ReactDOM.render(
- ,
- container
- );
- expect(container.firstChild.hasAttribute('children')).toBe(false);
- expect(
- container.firstChild.hasAttribute('suppressContentEditableWarning')
- ).toBe(false);
-
- ReactDOM.render(
- ,
- container
- );
- expect(container.firstChild.hasAttribute('children')).toBe(false);
- expect(
- container.firstChild.hasAttribute('suppressContentEditableWarning')
- ).toBe(false);
- });
-
- it('should skip dangerouslySetInnerHTML on SVG components', function() {
- var container = document.createElement('div');
-
- ReactDOM.render(
- ,
- container
- );
- expect(
- container.firstChild.hasAttribute('dangerouslySetInnerHTML')
- ).toBe(false);
-
- ReactDOM.render(
- ,
- container
- );
- expect(
- container.firstChild.hasAttribute('dangerouslySetInnerHTML')
- ).toBe(false);
});
it('should remove attributes', function() {
@@ -343,79 +257,6 @@ describe('ReactDOMComponent', function() {
expect(container.firstChild.hasAttribute('height')).toBe(false);
});
- it('should remove known SVG camel case attributes', function() {
- var container = document.createElement('div');
- ReactDOM.render( , container);
-
- expect(container.firstChild.hasAttribute('viewBox')).toBe(true);
- ReactDOM.render( , container);
- expect(container.firstChild.hasAttribute('viewBox')).toBe(false);
- });
-
- it('should remove known SVG hyphenated attributes', function() {
- var container = document.createElement('div');
- ReactDOM.render( , container);
-
- expect(container.firstChild.hasAttribute('clip-path')).toBe(true);
- ReactDOM.render( , container);
- expect(container.firstChild.hasAttribute('clip-path')).toBe(false);
- });
-
- it('should remove arbitrary SVG hyphenated attributes', function() {
- var container = document.createElement('div');
- ReactDOM.render( , container);
-
- expect(container.firstChild.hasAttribute('the-word')).toBe(true);
- ReactDOM.render( , container);
- expect(container.firstChild.hasAttribute('the-word')).toBe(false);
- });
-
- it('should remove arbitrary SVG camel case attributes', function() {
- var container = document.createElement('div');
- ReactDOM.render( , container);
-
- if (ReactDOMFeatureFlags.useCreateElement) {
- // jsdom's svg parsing makes attributes lowercase, so only assert this
- // in createElement mode...
- expect(container.firstChild.hasAttribute('theWord')).toBe(true);
- }
- ReactDOM.render( , container);
- expect(container.firstChild.hasAttribute('theWord')).toBe(false);
- });
-
- it('should remove SVG attributes that should have been hyphenated', function() {
- spyOn(console, 'error');
- var container = document.createElement('div');
- ReactDOM.render( , container);
- expect(console.error.argsForCall.length).toBe(1);
- expect(console.error.argsForCall[0][0]).toContain('clipPath');
- expect(console.error.argsForCall[0][0]).toContain('clip-path');
-
- expect(container.firstChild.hasAttribute('clip-path')).toBe(true);
- ReactDOM.render( , container);
- expect(container.firstChild.hasAttribute('clip-path')).toBe(false);
- });
-
- it('should remove namespaced SVG attributes', function() {
- var container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container
- );
-
- expect(container.firstChild.firstChild.hasAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'href'
- )).toBe(true);
- ReactDOM.render( , container);
- expect(container.firstChild.firstChild.hasAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'href'
- )).toBe(false);
- });
-
it('should remove properties', function() {
var container = document.createElement('div');
ReactDOM.render(
, container);
@@ -487,132 +328,6 @@ describe('ReactDOMComponent', function() {
expect(container.childNodes[0].getAttribute('myattr')).toBe('myval');
});
- it('should update known hyphenated attributes for SVG tags', function() {
- var container = document.createElement('div');
-
- var beforeUpdate = ;
- ReactDOM.render(beforeUpdate, container);
-
- var afterUpdate = ;
- ReactDOM.render(afterUpdate, container);
-
- expect(container.childNodes[0].getAttribute('clip-path')).toBe(
- 'url(#starlet)'
- );
- });
-
- it('should update camel case attributes for SVG tags', function() {
- var container = document.createElement('div');
-
- var beforeUpdate = ;
- ReactDOM.render(beforeUpdate, container);
-
- var afterUpdate = ;
- ReactDOM.render(afterUpdate, container);
-
- expect(container.childNodes[0].getAttribute('viewBox')).toBe(
- '0 0 100 100'
- );
- });
-
- it('should warn camel casing hyphenated attributes for SVG tags', function() {
- spyOn(console, 'error');
- var container = document.createElement('div');
-
- var beforeUpdate = ;
- ReactDOM.render(beforeUpdate, container);
-
- var afterUpdate = ;
- ReactDOM.render(afterUpdate, container);
-
- expect(container.childNodes[0].getAttribute('clip-path')).toBe(
- 'url(#starlet)'
- );
- expect(console.error.argsForCall.length).toBe(1);
- expect(console.error.argsForCall[0][0]).toContain('clipPath');
- expect(console.error.argsForCall[0][0]).toContain('clip-path');
- });
-
- it('should only warn once about deprecated SVG attributes', function() {
- spyOn(console, 'error');
- var container = document.createElement('div');
- ReactDOM.render(
-
-
-
- ,
- container
- );
- expect(console.error.argsForCall.length).toBe(2);
- expect(console.error.argsForCall[0][0]).toContain('clipPath');
- expect(console.error.argsForCall[0][0]).toContain('clip-path');
- expect(console.error.argsForCall[1][0]).toContain('strokeWidth');
- expect(console.error.argsForCall[1][0]).toContain('stroke-width');
-
- ReactDOM.render(
-
-
-
-
- ,
- container
- );
- expect(console.error.argsForCall.length).toBe(3);
- expect(console.error.argsForCall[0][0]).toContain('clipPath');
- expect(console.error.argsForCall[0][0]).toContain('clip-path');
- expect(console.error.argsForCall[1][0]).toContain('strokeWidth');
- expect(console.error.argsForCall[1][0]).toContain('stroke-width');
- expect(console.error.argsForCall[2][0]).toContain('strokeOpacity');
- expect(console.error.argsForCall[2][0]).toContain('stroke-opacity');
- });
-
- it('should update arbitrary hyphenated attributes for SVG tags', function() {
- var container = document.createElement('div');
-
- var beforeUpdate = ;
- ReactDOM.render(beforeUpdate, container);
-
- var afterUpdate = ;
- ReactDOM.render(afterUpdate, container);
-
- expect(container.childNodes[0].getAttribute('the-word')).toBe('the-bird');
- });
-
- it('should update arbitrary camel case attributes for SVG tags', function() {
- var container = document.createElement('div');
-
- var beforeUpdate = ;
- ReactDOM.render(beforeUpdate, container);
-
- var afterUpdate = ;
- ReactDOM.render(afterUpdate, container);
-
- expect(container.childNodes[0].getAttribute('theWord')).toBe('theBird');
- });
-
- it('should update namespaced SVG attributes', function() {
- var container = document.createElement('div');
-
- var beforeUpdate = (
-
-
-
- );
- ReactDOM.render(beforeUpdate, container);
-
- var afterUpdate = (
-
-
-
- );
- ReactDOM.render(afterUpdate, container);
-
- expect(container.firstChild.firstChild.getAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'href'
- )).toBe('http://i.imgur.com/JvqCM2p.png');
- });
-
it('should clear all the styles when removing `style`', function() {
var styles = {display: 'none', color: 'red'};
var container = document.createElement('div');
diff --git a/src/renderers/dom/shared/devtools/ReactDOMSVGDeprecatedAttributeDevtool.js b/src/renderers/dom/shared/devtools/ReactDOMSVGDeprecatedAttributeDevtool.js
deleted file mode 100644
index 164340c7a7022..0000000000000
--- a/src/renderers/dom/shared/devtools/ReactDOMSVGDeprecatedAttributeDevtool.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Copyright 2013-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule ReactDOMSVGDeprecatedAttributeDevtool
- */
-
-'use strict';
-
-var DOMProperty = require('DOMProperty');
-
-var warning = require('warning');
-
-if (__DEV__) {
- var reactProps = {
- children: true,
- dangerouslySetInnerHTML: true,
- key: true,
- ref: true,
- };
- var warnedSVGAttributes = {};
-
- var warnDeprecatedSVGAttribute = function(name) {
- if (reactProps.hasOwnProperty(name) && reactProps[name]) {
- return;
- }
-
- if (!DOMProperty.properties.hasOwnProperty(name)) {
- return;
- }
- var { attributeName, attributeNamespace } = DOMProperty.properties[name];
- if (attributeNamespace || name === attributeName) {
- return;
- }
-
- if (warnedSVGAttributes.hasOwnProperty(name) && warnedSVGAttributes[name]) {
- return;
- }
- warnedSVGAttributes[name] = true;
-
- warning(
- false,
- 'SVG property %s is deprecated. Use the original attribute name ' +
- '%s for SVG tags instead.',
- name,
- attributeName
- );
- };
-}
-
-var ReactDOMSVGDeprecatedAttributeDevtool = {
- onCreateMarkupForSVGAttribute(name, value) {
- warnDeprecatedSVGAttribute(name);
- },
- onSetValueForSVGAttribute(node, name, value) {
- warnDeprecatedSVGAttribute(name);
- },
-};
-
-module.exports = ReactDOMSVGDeprecatedAttributeDevtool;