-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix($compile): support merging special attribute names in replace
d…
#13318
Conversation
@@ -1221,6 +1228,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { | |||
} | |||
}; | |||
|
|||
function setSpecialAttr(element, attrName, value) { | |||
specialAttrHolder.innerHTML = "<span " + attrName + "='" + (value || '').replace(QUOTE_REGEX, '"') + "'>"; | |||
var attribute = specialAttrHolder.firstChild.attributes[0].cloneNode(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to MDN, cloneNode()
is supposed to be deprecated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, trouble is I can't find any other way of achieving the desired solution. Any other ideas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahah how about this:
specialAttrHolder.innerHTML = "<span " + attrName + "='" + (value || '').replace(QUOTE_REGEX, '"') + "'>"
var span = specialAttrHolder.firstChild;
var attribute = span.attributes[0];
span.removeAttribute(attrName);
element.attributes.setNamedItem(attribute);
This avoids any deprecated API and could possibly be a lot quicker as we are not cloning anything.
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317 Closes angular#13318
so this performance hit will only happen in certain scenarios? It will not happen for everything using ng-forward special attributes correct? |
@@ -989,6 +989,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { | |||
function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, | |||
$controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { | |||
|
|||
var SIMPLE_ATTR_NAME = /^\w/; | |||
var QUOTE_REGEX = /'/g; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks unused...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes. That was from a previous commit in this pr
@jbedard yes. It has no impact for almost all circumstances |
That wasn't me asking, but good to know :) Using |
Sorry @jbedard - difficult to keep track on a phone. I spent ages digging through the DOM API and hacking in different browsers. The final solution we have here is about as fast as I can get and doesn't use any deprecated APIs. But if anyone has time to find a faster solution that would be great. I'm afraid that we are stuck with |
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317 Closes angular#13318
@petebacondarwin I wonder if we really have to support this. Would it be possible that if someone needs this, then they have to use the extended notation? My rational is that building html by concatenating strings enlarge the surface for mXSS. |
@lgalfaso I see where you are coming from about security. I think that in this case we are safe though (please do check the accuracy of this):
|
@petebacondarwin this solution still has issues with attributes with special names (tried this with Chrome) http://plnkr.co/edit/0GjwipSakMskljc7X3Bl?p=preview Just run it and check the console |
@lgalfaso - thanks for spotting that. We have to use the |
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317 Closes angular#13318
Added a test and a fix for the problem that @lgalfaso noted |
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317 Closes angular#13318
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317 Closes angular#13318
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317 Closes angular#13318
78eb562
to
c93d5cf
Compare
@petebacondarwin can you please remove all the |
The console log are there because there was a failure on Firefox bit I couldn't reproduce it locally. Try pulling the previous commit for the proper solution |
Well this is interesting... Given <h1 Ω="omega">Hello Plunker!</h1> the following fails only with JQuery on Firefox var h1 = $('h1');
expect(h1.attr('Ω')).toEqual('omega'); http://plnkr.co/edit/qrmsTZsW78CYxJSi7Pyv?p=preview compared to with jqLite: http://plnkr.co/edit/h9Zfji8HtgcFnGKF49My?p=preview Is that a bug in JQuery @mzgol? |
Hmm, interesting, native |
@petebacondarwin Seems like a bug, I reported it to the jQuery bug tracker: jquery/jquery#2730 |
OK, please read jquery/jquery#2730 (comment). So, jQuery is using |
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317 Closes angular#13318
…irectives When compiling a `replace` directive, the compiler merges the attributes from the replaced element onto the template element. Unfortunately, `setAttribute` and other related DOM methods do not allow certain attribute names - in particular Angular 2 style names such as `(click)` and `[value]`. This is relevant when using ngForward with Angular Material, since the `mgButton` directive uses `replace` and in the former you often use `(click)`. This fixes the problem but for those special attributes the speed is considerably slow. Closes angular#13317 Closes angular#13318
…irectives
When compiling a
replace
directive, the compiler merges the attributes fromthe replaced element onto the template element.
Unfortunately,
setAttribute
and other related DOM methods do not allow certainattribute names - in particular Angular 2 style names such as
(click)
and[value]
.This is relevant when using ngForward with Angular Material, since the
mgButton
directive uses
replace
and in the former you often use(click)
.This fixes the problem but for those special attributes the speed is considerably
slow.
Closes #13317