7
* @flow
8
*/
9
10
-import hasOwnProperty from 'shared/hasOwnProperty';
11
-
10
type PropertyType = 0 | 1 | 2 | 3 | 4 | 5 | 6;
11
12
// A simple string attribute.
42
+acceptsBooleans: boolean,
43
+attributeName: string,
44
+attributeNamespace: string | null,
47
- +mustUseProperty: boolean,
48
- +propertyName: string,
45
+type: PropertyType,
46
+sanitizeURL: boolean,
47
+removeEmptyString: boolean,
48
};
49
54
-/* eslint-disable max-len */
55
-export const ATTRIBUTE_NAME_START_CHAR =
56
- ':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';
57
-/* eslint-enable max-len */
58
-export const ATTRIBUTE_NAME_CHAR: string =
59
- ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
60
-
61
-export const VALID_ATTRIBUTE_NAME_REGEX: RegExp = new RegExp(
62
- '^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$',
63
-);
64
-
65
-const illegalAttributeNameCache: {[string]: boolean} = {};
66
-const validatedAttributeNameCache: {[string]: boolean} = {};
67
-
68
-export function isAttributeNameSafe(attributeName: string): boolean {
69
- if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) {
70
- return true;
71
- }
72
- if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) {
73
- return false;
74
- }
75
- if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
76
- validatedAttributeNameCache[attributeName] = true;
77
- return true;
78
- }
79
- illegalAttributeNameCache[attributeName] = true;
80
- if (__DEV__) {
81
- console.error('Invalid attribute name: `%s`', attributeName);
82
- }
83
- return false;
84
-}
85
-
50
export function getPropertyInfo(name: string): PropertyInfo | null {
51
return properties.hasOwnProperty(name) ? properties[name] : null;
52
}
53
54
// $FlowFixMe[missing-this-annot]
55
function PropertyInfoRecord(
92
- name: string,
56
type: PropertyType,
94
- mustUseProperty: boolean,
57
attributeName: string,
58
attributeNamespace: string | null,
59
sanitizeURL: boolean,
65
type === OVERLOADED_BOOLEAN;
66
this.attributeName = attributeName;
67
this.attributeNamespace = attributeNamespace;
106
- this.mustUseProperty = mustUseProperty;
107
- this.propertyName = name;
68
this.type = type;
69
this.sanitizeURL = sanitizeURL;
70
this.removeEmptyString = removeEmptyString;
85
].forEach(([name, attributeName]) => {
86
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
87
properties[name] = new PropertyInfoRecord(
128
- name,
88
STRING,
130
- false, // mustUseProperty
89
attributeName, // attributeName
90
null, // attributeNamespace
91
false, // sanitizeURL
99
['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(name => {
100
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
101
properties[name] = new PropertyInfoRecord(
144
- name,
102
BOOLEANISH_STRING,
146
- false, // mustUseProperty
103
name.toLowerCase(), // attributeName
104
null, // attributeNamespace
105
false, // sanitizeURL
119
].forEach(name => {
120
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
121
properties[name] = new PropertyInfoRecord(
166
- name,
122
BOOLEANISH_STRING,
168
- false, // mustUseProperty
123
name, // attributeName
124
null, // attributeNamespace
125
false, // sanitizeURL
158
].forEach(name => {
159
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
160
properties[name] = new PropertyInfoRecord(
207
- name,
161
BOOLEAN,
209
- false, // mustUseProperty
162
name.toLowerCase(), // attributeName
163
null, // attributeNamespace
164
false, // sanitizeURL
166
);
167
});
168
217
-// These are the few React props that we set as DOM properties
218
-// rather than attributes. These are all booleans.
219
-[
220
- 'checked',
221
- // Note: `option.selected` is not updated if `select.multiple` is
222
- // disabled with `removeAttribute`. We have special logic for handling this.
223
- 'multiple',
224
- 'muted',
225
- 'selected',
226
-
227
- // NOTE: if you add a camelCased prop to this list,
228
- // you'll need to set attributeName to name.toLowerCase()
229
- // instead in the assignment below.
230
-].forEach(name => {
231
- // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
232
- properties[name] = new PropertyInfoRecord(
233
- name,
234
- BOOLEAN,
235
- true, // mustUseProperty
236
- name, // attributeName
237
- null, // attributeNamespace
238
- false, // sanitizeURL
239
- false, // removeEmptyString
240
- );
241
-});
242
-
169
// These are HTML attributes that are "overloaded booleans": they behave like
170
// booleans, but can also accept a string value.
171
[
178
].forEach(name => {
179
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
180
properties[name] = new PropertyInfoRecord(
255
- name,
181
OVERLOADED_BOOLEAN,
257
- false, // mustUseProperty
182
name, // attributeName
183
null, // attributeNamespace
184
false, // sanitizeURL
199
].forEach(name => {
200
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
201
properties[name] = new PropertyInfoRecord(
278
- name,
202
POSITIVE_NUMERIC,
280
- false, // mustUseProperty
203
name, // attributeName
204
null, // attributeNamespace
205
false, // sanitizeURL
211
['rowSpan', 'start'].forEach(name => {
212
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
213
properties[name] = new PropertyInfoRecord(
292
- name,
214
NUMERIC,
294
- false, // mustUseProperty
215
name.toLowerCase(), // attributeName
216
null, // attributeNamespace
217
false, // sanitizeURL
310
const name = attributeName.replace(CAMELIZE, capitalize);
311
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
312
properties[name] = new PropertyInfoRecord(
393
- name,
313
STRING,
395
- false, // mustUseProperty
314
attributeName,
315
null, // attributeNamespace
316
false, // sanitizeURL
334
const name = attributeName.replace(CAMELIZE, capitalize);
335
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
336
properties[name] = new PropertyInfoRecord(
419
- name,
337
STRING,
421
- false, // mustUseProperty
338
attributeName,
339
'http://www.w3.org/1999/xlink',
340
false, // sanitizeURL
355
const name = attributeName.replace(CAMELIZE, capitalize);
356
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
357
properties[name] = new PropertyInfoRecord(
442
- name,
358
STRING,
444
- false, // mustUseProperty
359
attributeName,
360
'http://www.w3.org/XML/1998/namespace',
361
false, // sanitizeURL
369
['tabIndex', 'crossOrigin'].forEach(attributeName => {
370
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
371
properties[attributeName] = new PropertyInfoRecord(
458
- attributeName,
372
STRING,
460
- false, // mustUseProperty
373
attributeName.toLowerCase(), // attributeName
374
null, // attributeNamespace
375
false, // sanitizeURL
382
const xlinkHref = 'xlinkHref';
383
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
384
properties[xlinkHref] = new PropertyInfoRecord(
473
- 'xlinkHref',
385
STRING,
475
- false, // mustUseProperty
386
'xlink:href',
387
'http://www.w3.org/1999/xlink',
388
true, // sanitizeURL
392
const formAction = 'formAction';
393
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
394
properties[formAction] = new PropertyInfoRecord(
485
- 'formAction',
395
STRING,
487
- false, // mustUseProperty
396
'formaction', // attributeName
397
null, // attributeNamespace
398
true, // sanitizeURL
402
['src', 'href', 'action'].forEach(attributeName => {
403
// $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
404
properties[attributeName] = new PropertyInfoRecord(
497
- attributeName,
405
STRING,
499
- false, // mustUseProperty
406
attributeName.toLowerCase(), // attributeName
407
null, // attributeNamespace
408
true, // sanitizeURL