Skip to content

Commit

Permalink
Strip whitelist. Move casing warnings to dev tools
Browse files Browse the repository at this point in the history
Configures DOMPropertyOperations to allow all attributes to pass
through. It maintains the whitelist only for attributes that need
special behavior.

- Lowercase props during static markup generation
  • Loading branch information
nhunzaker committed Sep 16, 2016
1 parent c78464f commit 1d1b1ec
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 374 deletions.
54 changes: 27 additions & 27 deletions src/renderers/dom/shared/DOMProperty.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@

var invariant = require('invariant');

var RESERVED_PROPS = {
children: true,
dangerouslySetInnerHTML: true,
key: true,
ref: true,

autoFocus: true,
defaultValue: true,
valueLink: true,
defaultChecked: true,
checkedLink: true,
innerHTML: true,
suppressContentEditableWarning: true,
onFocusIn: true,
onFocusOut: true,
};

function checkMask(value, bitmask) {
return (value & bitmask) === bitmask;
}
Expand All @@ -32,11 +49,6 @@ var DOMPropertyInjection = {
* Inject some specialized knowledge about the DOM. This takes a config object
* with the following properties:
*
* isCustomAttribute: function that given an attribute name will return true
* if it can be inserted into the DOM verbatim. Useful for data-* or aria-*
* attributes where it's impossible to enumerate all of the possible
* attribute names,
*
* 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.
Expand Down Expand Up @@ -64,12 +76,6 @@ var DOMPropertyInjection = {
var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};
var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};

if (domPropertyConfig.isCustomAttribute) {
DOMProperty._isCustomAttributeFunctions.push(
domPropertyConfig.isCustomAttribute
);
}

for (var propName in Properties) {
invariant(
!DOMProperty.properties.hasOwnProperty(propName),
Expand Down Expand Up @@ -197,26 +203,20 @@ var DOMProperty = {
*/
getPossibleStandardName: __DEV__ ? {} : null,

/**
* All of the isCustomAttribute() functions that have been injected.
*/
_isCustomAttributeFunctions: [],
injection: DOMPropertyInjection,

/**
* Checks whether a property name is a custom attribute.
* @method
* 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
*/
isCustomAttribute: function(attributeName) {
for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) {
var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];
if (isCustomAttributeFn(attributeName)) {
return true;
}
}
return false;
isReservedProp(name) {
return RESERVED_PROPS.hasOwnProperty(name);
},

injection: DOMPropertyInjection,
};

module.exports = DOMProperty;
9 changes: 5 additions & 4 deletions src/renderers/dom/shared/DOMPropertyOperations.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ var DOMPropertyOperations = {
return attributeName + '=""';
}
return attributeName + '=' + quoteAttributeValueForBrowser(value);
} else if (DOMProperty.isCustomAttribute(name)) {
} else {
if (value == null) {
return '';
}
return name + '=' + quoteAttributeValueForBrowser(value);
return name.toLowerCase() + '=' + quoteAttributeValueForBrowser(value);
}
return null;
},
Expand Down Expand Up @@ -158,7 +158,7 @@ var DOMPropertyOperations = {
node.setAttribute(attributeName, '' + value);
}
}
} else if (DOMProperty.isCustomAttribute(name)) {
} else {
DOMPropertyOperations.setValueForAttribute(node, name, value);
return;
}
Expand All @@ -178,6 +178,7 @@ var DOMPropertyOperations = {
if (!isAttributeNameSafe(name)) {
return;
}

if (value == null) {
node.removeAttribute(name);
} else {
Expand Down Expand Up @@ -235,7 +236,7 @@ var DOMPropertyOperations = {
} else {
node.removeAttribute(propertyInfo.attributeName);
}
} else if (DOMProperty.isCustomAttribute(name)) {
} else {
node.removeAttribute(name);
}

Expand Down
149 changes: 7 additions & 142 deletions src/renderers/dom/shared/HTMLDOMPropertyConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,186 +22,51 @@ var HAS_OVERLOADED_BOOLEAN_VALUE =
DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;

var HTMLDOMPropertyConfig = {
isCustomAttribute: RegExp.prototype.test.bind(
new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')
),
Properties: {
/**
* Standard Properties
*/
accept: 0,
acceptCharset: 0,
accessKey: 0,
action: 0,
allowFullScreen: HAS_BOOLEAN_VALUE,
allowTransparency: 0,
alt: 0,
// specifies target context for links with `preload` type
as: 0,
async: HAS_BOOLEAN_VALUE,
autoComplete: 0,
// autoFocus is polyfilled/normalized by AutoFocusUtils
// autoFocus: HAS_BOOLEAN_VALUE,
autoPlay: HAS_BOOLEAN_VALUE,
capture: HAS_BOOLEAN_VALUE,
cellPadding: 0,
cellSpacing: 0,
charSet: 0,
challenge: 0,
checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
cite: 0,
classID: 0,
className: 0,
cols: HAS_POSITIVE_NUMERIC_VALUE,
colSpan: 0,
content: 0,
contentEditable: 0,
contextMenu: 0,
controls: HAS_BOOLEAN_VALUE,
coords: 0,
crossOrigin: 0,
data: 0, // For `<object />` acts as `src`.
dateTime: 0,
default: HAS_BOOLEAN_VALUE,
defer: HAS_BOOLEAN_VALUE,
dir: 0,
disabled: HAS_BOOLEAN_VALUE,
download: HAS_OVERLOADED_BOOLEAN_VALUE,
draggable: 0,
encType: 0,
form: 0,
formAction: 0,
formEncType: 0,
formMethod: 0,
formNoValidate: HAS_BOOLEAN_VALUE,
formTarget: 0,
frameBorder: 0,
headers: 0,
height: 0,
hidden: HAS_BOOLEAN_VALUE,
high: 0,
href: 0,
hrefLang: 0,
htmlFor: 0,
httpEquiv: 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: 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: 0,
nonce: 0,
noValidate: HAS_BOOLEAN_VALUE,
open: HAS_BOOLEAN_VALUE,
optimum: 0,
pattern: 0,
placeholder: 0,
playsInline: HAS_BOOLEAN_VALUE,
poster: 0,
preload: 0,
profile: 0,
radioGroup: 0,
readOnly: HAS_BOOLEAN_VALUE,
referrerPolicy: 0,
rel: 0,
required: HAS_BOOLEAN_VALUE,
reversed: HAS_BOOLEAN_VALUE,
role: 0,
rows: HAS_POSITIVE_NUMERIC_VALUE,
rowSpan: HAS_NUMERIC_VALUE,
sandbox: 0,
scope: 0,
scoped: HAS_BOOLEAN_VALUE,
scrolling: 0,
seamless: HAS_BOOLEAN_VALUE,
selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
shape: 0,
size: HAS_POSITIVE_NUMERIC_VALUE,
sizes: 0,
span: HAS_POSITIVE_NUMERIC_VALUE,
spellCheck: 0,
src: 0,
srcDoc: 0,
srcLang: 0,
srcSet: 0,
start: HAS_NUMERIC_VALUE,
step: 0,
style: 0,
summary: 0,
tabIndex: 0,
target: 0,
title: 0,
// Setting .type throws on non-<input> tags
type: 0,
useMap: 0,
value: 0,
width: 0,
wmode: 0,
wrap: 0,

/**
* RDFa Properties
*/
about: 0,
datatype: 0,
inlist: 0,
prefix: 0,
// property is also supported for OpenGraph in meta tags.
property: 0,
resource: 0,
typeof: 0,
vocab: 0,

/**
* Non-standard Properties
*/
// autoCapitalize and autoCorrect are supported in Mobile Safari for
// keyboard hints.
autoCapitalize: 0,
autoCorrect: 0,
// autoSave allows WebKit/Blink to persist values of input fields on page reloads
autoSave: 0,
// color is for Safari mask-icon link
color: 0,
// itemProp, itemScope, itemType are for
// Microdata support. See http://schema.org/docs/gs.html
itemProp: 0,
itemScope: HAS_BOOLEAN_VALUE,
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: 0,
itemRef: 0,
// results show looking glass icon and recent searches on input
// search fields in WebKit/Blink
results: 0,
// IE-only attribute that specifies security restrictions on an iframe
// as an alternative to the sandbox attribute on IE<10
security: 0,
// IE-only attribute that controls focus behavior
unselectable: 0,

// These properties are necessary as exceptions for names.
// They should match DOMAttributeNames
acceptCharset: 0,
className: 0,
htmlFor: 0,
httpEquiv: 0,
},
DOMAttributeNames: {
acceptCharset: 'accept-charset',
Expand Down

0 comments on commit 1d1b1ec

Please sign in to comment.