Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support arbitrary attributes on elements with dashes in the tag name. #3067

Merged

Conversation

jimfb
Copy link
Contributor

@jimfb jimfb commented Feb 5, 2015

Support arbitrary attributes on elements with dashes in the tag name.

if (value == null) {
return '';
}
return name + '=' + quoteAttributeValueForBrowser(value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xss?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We call quoteAttributeValueForBrowser, which calls escapeTextContentForBrowser. Is that not good enough?

What are you worried about? Users controlling the property name?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah – even if that's not likely to be idiomatic code, it's surprising if an odd attribute name results in a security hole. You can see that we already check the tag name when generating markup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, cool, I'll add an invariant.

@jimfb jimfb force-pushed the arbitrary-attributes-for-dash-elements branch from 076a97a to c841cf6 Compare February 6, 2015 00:14
@jimfb
Copy link
Contributor Author

jimfb commented Feb 6, 2015

cc @sebmarkbage

@@ -235,7 +235,7 @@ ReactDOMComponent.Mixin = {
propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
}
var markup =
DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
DOMPropertyOperations.createMarkupForProperty(this._tag, propKey, propValue);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is leaking unnecessarily much information to DOMPropertyOperations. All the tag name logic is already in this file.

I'd rather see the switching done in this file where we already have a regexp for tag names. We might as well use that first check to cache if we're a custom element or not. That way you don't have to recheck for every attribute and every update.

@sebmarkbage
Copy link
Collaborator

If you do the branching in DOM component you can just have a separate methods for createMarkupForCustomAttribute and setValueForCustomAttribute so that we have a separate code path for those. Avoids the boolean-as-argument problem.

@jimfb
Copy link
Contributor Author

jimfb commented Feb 10, 2015

@sebmarkbage better?

@syranide
Copy link
Contributor

May not be relevant right now, but does this play nice with SVG's <font-face> etc?

@jimfb
Copy link
Contributor Author

jimfb commented Feb 10, 2015

Yeah, it'll potentially pass additional properties to font-face if they're transferring props, but shouldn't be a huge problem. If anyone is doing that (I think it's relatively rare), SVG should either ignore the additional attributes or give an error message; either way, it sounds like a fine migration story.

I suppose we could special case that tag if anyone really cares. I feel like it's not necessary, but @sebmarkbage tends to prefer being super cautious, so I'll let him have the final say.

@sebmarkbage
Copy link
Collaborator

We might need to special case it when we support more SVG attributes, but for this case we're already using setAttribute so it should be fine. Don't think people are transferring random props to font-face very often and even if they do, it shouldn't hurt.

var markup =
DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
var markup = null;
if(this._tag != null && this._tag.indexOf('-') >= 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a missing space after if

@jimfb
Copy link
Contributor Author

jimfb commented Apr 27, 2015

I don't see a todo item on this PR; am I missing something? Is there a blocking item, or are we just waiting for a CR?

* @return {?string} Markup string, or null if the property was invalid.
*/
createMarkupForCustomAttribute: function(name, value)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{ on previous line

);
validatedAttributeNameCache[attributeName] = true;
}
return attributeName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we keep this we don't need the return value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a style that allows you to add validation while passing a value through, similar to function chaining (where a builder returns its self). Otherwise, the function is just void, so we don't loose anything by returning the value. This pattern is pretty common in other languages, but we can remove it if it isn't common javascript.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the style but if we don't use it like that, there's no need to do it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, fixing now.

var validatedAttributeNameCache = {};

function validateDangerousAttributeName(attributeName) {
if (!hasOwnProperty.call(validatedAttributeNameCache, attributeName)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasOwnProperty doesn't exist here…

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@jimfb jimfb force-pushed the arbitrary-attributes-for-dash-elements branch 2 times, most recently from ad30a5a to 9561a01 Compare April 28, 2015 23:39
@jimfb
Copy link
Contributor Author

jimfb commented Apr 28, 2015

Switched to warn instead of throw for invalid attribute name.

@jimfb
Copy link
Contributor Author

jimfb commented Apr 30, 2015

cc @zpao Anything tasks remaining?

@jimfb jimfb force-pushed the arbitrary-attributes-for-dash-elements branch from 9561a01 to 90ba511 Compare April 30, 2015 20:49
@jimfb
Copy link
Contributor Author

jimfb commented May 8, 2015

@zpao Ping.

@jimfb jimfb force-pushed the arbitrary-attributes-for-dash-elements branch 3 times, most recently from 45e7c20 to 2d2468b Compare June 2, 2015 00:49
@jimfb
Copy link
Contributor Author

jimfb commented Jun 2, 2015

Ping @zpao.

@@ -17,6 +17,30 @@ var DOMProperty = require('DOMProperty');
var quoteAttributeValueForBrowser = require('quoteAttributeValueForBrowser');
var warning = require('warning');

var VALID_ATTRIBUTE_NAME_REGEX = /^[a-zA-Z_][a-zA-Z_\.\-\d]*$/; // Simplified subset
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: move comment to own line above

@jimfb jimfb force-pushed the arbitrary-attributes-for-dash-elements branch from 2d2468b to b1db817 Compare June 2, 2015 19:15
@jimfb
Copy link
Contributor Author

jimfb commented Jun 2, 2015

@zpao updated.

@zpao
Copy link
Member

zpao commented Jun 3, 2015

👍

jimfb added a commit that referenced this pull request Jun 3, 2015
…ments

Support arbitrary attributes on elements with dashes in the tag name.
@jimfb jimfb merged commit 9a02ea2 into facebook:master Jun 3, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants