Skip to content

Commit 3f857bb

Browse files
fix(attributes-to-props): handle attr named after Object properties
Since the property config is a POJO (Plain Old JavaScript Object), this means the Object properties/methods are accessible. Thus, use `hasOwnProperty` to check if the attribute name is on the config map rather than on the Object prototype chain. Handle attributes that share the same name as custom attributes.
1 parent 1151cfb commit 3f857bb

File tree

2 files changed

+57
-31
lines changed

2 files changed

+57
-31
lines changed

lib/attributes-to-props.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ var styleToObject = require('style-to-object');
33
var utilities = require('./utilities');
44

55
var camelCase = utilities.camelCase;
6+
67
var HTMLDOMPropertyConfig = reactProperty.HTMLDOMPropertyConfig;
78
var SVGDOMPropertyConfig = reactProperty.SVGDOMPropertyConfig;
89
var isCustomAttribute = reactProperty.isCustomAttribute;
910

11+
var hasOwnProperty = Object.prototype.hasOwnProperty;
12+
1013
/**
1114
* Converts HTML/SVG DOM attributes to React props.
1215
*
@@ -17,6 +20,7 @@ function attributesToProps(attributes) {
1720
attributes = attributes || {};
1821

1922
var attributeName;
23+
var attributeNameLowerCased;
2024
var attributeValue;
2125
var property;
2226
var props = {};
@@ -31,8 +35,9 @@ function attributesToProps(attributes) {
3135
}
3236

3337
// convert HTML attribute to React prop
34-
property = HTMLDOMPropertyConfig[attributeName.toLowerCase()];
35-
if (property) {
38+
attributeNameLowerCased = attributeName.toLowerCase();
39+
if (hasOwnProperty.call(HTMLDOMPropertyConfig, attributeNameLowerCased)) {
40+
property = HTMLDOMPropertyConfig[attributeNameLowerCased];
3641
props[property.propertyName] =
3742
property.hasBooleanValue ||
3843
(property.hasOverloadedBooleanValue && !attributeValue)
@@ -42,8 +47,8 @@ function attributesToProps(attributes) {
4247
}
4348

4449
// convert SVG attribute to React prop
45-
property = SVGDOMPropertyConfig[attributeName];
46-
if (property) {
50+
if (hasOwnProperty.call(SVGDOMPropertyConfig, attributeName)) {
51+
property = SVGDOMPropertyConfig[attributeName];
4752
props[property.propertyName] = attributeValue;
4853
continue;
4954
}

test/attributes-to-props.js

+48-27
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const assert = require('assert');
22
const attributesToProps = require('../lib/attributes-to-props');
33
const utilities = require('../lib/utilities');
44

5-
describe('attributesToProps', () => {
5+
describe('attributes-to-props', () => {
66
describe('HTML', () => {
77
it('converts attributes to React props', () => {
88
assert.deepEqual(
@@ -60,7 +60,7 @@ describe('attributesToProps', () => {
6060
);
6161
});
6262

63-
it('keeps `data-` and `aria-` attributes as is', () => {
63+
it('keeps `data-*` and `aria-*` attributes as is', () => {
6464
assert.deepEqual(
6565
attributesToProps({
6666
'data-foo': 'bar',
@@ -248,35 +248,56 @@ describe('attributesToProps', () => {
248248
});
249249
});
250250

251-
describe('when utilties.PRESERVE_CUSTOM_ATTRIBUTES=false', () => {
252-
const { PRESERVE_CUSTOM_ATTRIBUTES } = utilities;
253-
254-
before(() => {
255-
utilities.PRESERVE_CUSTOM_ATTRIBUTES = false;
251+
describe('custom', () => {
252+
it('converts attributes named after Object properties', () => {
253+
// handled as custom attributes
254+
const attributes = {
255+
__defineGetter__: '',
256+
__defineSetter__: '',
257+
__lookupGetter__: '',
258+
__lookupSetter__: '',
259+
__proto__: '',
260+
constructor: '',
261+
hasOwnProperty: '',
262+
isPrototypeOf: '',
263+
propertyIsEnumerable: '',
264+
toLocaleString: '',
265+
toString: '',
266+
valueOf: ''
267+
};
268+
assert.deepEqual(attributesToProps(attributes), attributes);
256269
});
257270

258-
after(() => {
259-
utilities.PRESERVE_CUSTOM_ATTRIBUTES = PRESERVE_CUSTOM_ATTRIBUTES;
260-
});
271+
describe('when utilties.PRESERVE_CUSTOM_ATTRIBUTES=false', () => {
272+
const { PRESERVE_CUSTOM_ATTRIBUTES } = utilities;
261273

262-
it('omits unknown attributes', () => {
263-
assert.deepEqual(
264-
attributesToProps({
265-
unknownAttribute: 'someValue'
266-
}),
267-
{}
268-
);
269-
});
274+
before(() => {
275+
utilities.PRESERVE_CUSTOM_ATTRIBUTES = false;
276+
});
270277

271-
it('omits incorrectly capitalized attributes', () => {
272-
assert.deepEqual(
273-
attributesToProps({
274-
'XLINK:HREF': '#',
275-
YChannelSelector: 'G',
276-
ZoomAndPan: 'disable'
277-
}),
278-
{}
279-
);
278+
after(() => {
279+
utilities.PRESERVE_CUSTOM_ATTRIBUTES = PRESERVE_CUSTOM_ATTRIBUTES;
280+
});
281+
282+
it('omits unknown attributes', () => {
283+
assert.deepEqual(
284+
attributesToProps({
285+
unknownAttribute: 'someValue'
286+
}),
287+
{}
288+
);
289+
});
290+
291+
it('omits incorrectly capitalized attributes', () => {
292+
assert.deepEqual(
293+
attributesToProps({
294+
'XLINK:HREF': '#',
295+
YChannelSelector: 'G',
296+
ZoomAndPan: 'disable'
297+
}),
298+
{}
299+
);
300+
});
280301
});
281302
});
282303
});

0 commit comments

Comments
 (0)