aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Gołębiowski2013-11-24 21:13:51 +0100
committerTobias Bosch2013-12-03 14:45:30 -0800
commitbf1972dc1e8ffbeaddfa53df1d49bc5a2177f09c (patch)
treec9bc7c1886871b38d2fcf78df568fb62a5b839ff
parent689dfb167924a61aef444ce7587fb987d8080990 (diff)
downloadangular.js-bf1972dc1e8ffbeaddfa53df1d49bc5a2177f09c.tar.bz2
fix(ngSanitize): prefer textContent to innerText to avoid layout trashing
innerText depends on styling as it doesn't display hidden elements. Therefore, it's better to use textContent not to cause unnecessary reflows. However, IE<9 don't support textContent so the innerText fallback is necessary.
-rw-r--r--src/ngSanitize/sanitize.js7
-rw-r--r--test/ngSanitize/sanitizeSpec.js52
2 files changed, 58 insertions, 1 deletions
diff --git a/src/ngSanitize/sanitize.js b/src/ngSanitize/sanitize.js
index e669e77a..1e424d69 100644
--- a/src/ngSanitize/sanitize.js
+++ b/src/ngSanitize/sanitize.js
@@ -378,7 +378,12 @@ function decodeEntities(value) {
var content = parts[2];
if (content) {
hiddenPre.innerHTML=content.replace(/</g,"&lt;");
- content = hiddenPre.innerText || hiddenPre.textContent;
+ // innerText depends on styling as it doesn't display hidden elements.
+ // Therefore, it's better to use textContent not to cause unnecessary
+ // reflows. However, IE<9 don't support textContent so the innerText
+ // fallback is necessary.
+ content = 'textContent' in hiddenPre ?
+ hiddenPre.textContent : hiddenPre.innerText;
}
return spaceBefore + content + spaceAfter;
}
diff --git a/test/ngSanitize/sanitizeSpec.js b/test/ngSanitize/sanitizeSpec.js
index 1958ec0f..fbffbba5 100644
--- a/test/ngSanitize/sanitizeSpec.js
+++ b/test/ngSanitize/sanitizeSpec.js
@@ -411,3 +411,55 @@ describe('HTML', function() {
});
});
});
+
+describe('decodeEntities', function() {
+ var handler, text,
+ origHiddenPre = window.hiddenPre;
+
+ beforeEach(function() {
+ text = '';
+ handler = {
+ start: function() {},
+ chars: function(text_){
+ text = text_;
+ },
+ end: function() {},
+ comment: function() {}
+ };
+ module('ngSanitize');
+ });
+
+ afterEach(function() {
+ window.hiddenPre = origHiddenPre;
+ });
+
+ it('should use innerText if textContent is not available (IE<9)', function() {
+ window.hiddenPre = {
+ innerText: 'INNER_TEXT'
+ };
+ inject(function($sanitize) {
+ htmlParser('<tag>text</tag>', handler);
+ expect(text).toEqual('INNER_TEXT');
+ });
+ });
+ it('should use textContent if available', function() {
+ window.hiddenPre = {
+ textContent: 'TEXT_CONTENT',
+ innerText: 'INNER_TEXT'
+ };
+ inject(function($sanitize) {
+ htmlParser('<tag>text</tag>', handler);
+ expect(text).toEqual('TEXT_CONTENT');
+ });
+ });
+ it('should use textContent even if empty', function() {
+ window.hiddenPre = {
+ textContent: '',
+ innerText: 'INNER_TEXT'
+ };
+ inject(function($sanitize) {
+ htmlParser('<tag>text</tag>', handler);
+ expect(text).toEqual('');
+ });
+ });
+});