Skip to content

Commit aac58d6

Browse files
committed
Remove unnecessary encoding step for attrs
Test: attributes - Attributes (file: jquery.html) cheerio x 7,999 ops/sec ±4.13% (72 runs sampled) old x 4,423 ops/sec ±1.05% (98 runs sampled) jsdom x 65.22 ops/sec ±5.70% (69 runs sampled) Test: attributes - Single Attribute (file: jquery.html) cheerio x 838,986 ops/sec ±5.47% (71 runs sampled) old x 328,370 ops/sec ±3.00% (90 runs sampled) jsdom x 11,593 ops/sec ±3.69% (88 runs sampled) Test: attributes - Data (file: jquery.html) cheerio x 188,847 ops/sec ±3.71% (79 runs sampled) old x 6,894 ops/sec ±3.14% (89 runs sampled) jsdom x 3,963 ops/sec ±2.68% (89 runs sampled)
1 parent 11d032b commit aac58d6

File tree

4 files changed

+21
-30
lines changed

4 files changed

+21
-30
lines changed

lib/api/attributes.js

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
var _ = require('underscore'),
22
utils = require('../utils'),
33
isTag = utils.isTag,
4-
decode = utils.decode,
5-
encode = utils.encode,
64
domEach = utils.domEach,
75
hasOwn = Object.prototype.hasOwnProperty,
86
rspace = /\s+/,
@@ -30,28 +28,22 @@ var getAttr = function(elem, name) {
3028

3129
// Return the entire attribs object if no attribute specified
3230
if (!name) {
33-
for (var a in elem.attribs) {
34-
elem.attribs[a] = decode(elem.attribs[a]);
35-
}
3631
return elem.attribs;
3732
}
3833

3934
if (hasOwn.call(elem.attribs, name)) {
4035
// Get the (decoded) attribute
41-
return decode(elem.attribs[name]);
36+
return elem.attribs[name];
4237
}
4338
};
4439

4540
var setAttr = function(el, name, value) {
46-
if (typeof name === 'object') return _.extend(el.attribs, name);
4741

4842
if (value === null) {
4943
removeAttribute(el, name);
5044
} else {
51-
el.attribs[name] = encode(value);
45+
el.attribs[name] = value+'';
5246
}
53-
54-
return el.attribs;
5547
};
5648

5749
var attr = exports.attr = function(name, value) {
@@ -63,7 +55,13 @@ var attr = exports.attr = function(name, value) {
6355
});
6456
}
6557
return domEach(this, function(i, el) {
66-
el.attribs = setAttr(el, name, value);
58+
if (typeof name === 'object') {
59+
_.each(name, function(name, key) {
60+
el.attribs[key] = name+'';
61+
});
62+
} else {
63+
setAttr(el, name, value);
64+
}
6765
});
6866
}
6967

@@ -73,15 +71,10 @@ var attr = exports.attr = function(name, value) {
7371
var setData = function(el, name, value) {
7472
if (typeof name === 'object') return _.extend(el.data, name);
7573
if (typeof name === 'string' && value !== undefined) {
76-
el.data[name] = encode(value);
74+
el.data[name] = value;
7775
} else if (typeof name === 'object') {
78-
// If its an object, loop through it
79-
_.each(name, function(value, key) {
80-
el.data[key] = encode(value);
81-
});
76+
_.exend(el.data, name);
8277
}
83-
84-
return el.data;
8578
};
8679

8780
var data = exports.data = function(name, value) {
@@ -95,23 +88,18 @@ var data = exports.data = function(name, value) {
9588

9689
// Return the entire data object if no data specified
9790
if (!name) {
98-
99-
_.each(elem.data, function(value, key) {
100-
elem.data[key] = decode(value);
101-
});
102-
10391
return elem.data;
10492
}
10593

10694
// Set the value (with attr map support)
10795
if (typeof name === 'object' || value !== undefined) {
10896
domEach(this, function(i, el) {
109-
el.data = setData(el, name, value);
97+
setData(el, name, value);
11098
});
11199
return this;
112100
} else if (hasOwn.call(elem.data, name)) {
113101
// Get the (decoded) data
114-
var val = decode(elem.data[name]);
102+
var val = elem.data[name];
115103

116104
if (hasOwn.call(primitives, val)) {
117105
val = primitives[val];

lib/parse.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
*/
44
var htmlparser = require('htmlparser2'),
55
_ = require('underscore'),
6-
isTag = require('./utils').isTag,
6+
utils = require('./utils'),
7+
decode = utils.decode,
8+
isTag = utils.isTag,
79
camelCase = require('./utils').camelCase;
810

911
/*
@@ -98,11 +100,14 @@ var parseData = exports.parseData = function(elem) {
98100
if (elem.data === undefined) elem.data = {};
99101
var value;
100102
for (var key in elem.attribs) {
103+
value = decode(elem.attribs[key]);
104+
101105
if (key.substr(0, 5) === 'data-') {
102-
value = elem.attribs[key];
103106
key = key.slice(5);
104107
key = camelCase(key);
105108
elem.data[key] = value;
109+
} else {
110+
elem.attribs[key] = value;
106111
}
107112
}
108113

lib/render.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
var _ = require('underscore');
55
var utils = require('./utils');
66

7-
var decode = utils.decode;
87
var encode = utils.encode;
98

109
/*
@@ -27,7 +26,7 @@ var formatAttrs = function(attributes) {
2726
if (!value && (rboolean.test(key) || key === '/')) {
2827
output.push(key);
2928
} else {
30-
output.push(key + '="' + encode(decode(value)) + '"');
29+
output.push(key + '="' + encode(value) + '"');
3130
}
3231
}
3332

test/api.attributes.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ describe('$(...)', function() {
6666
it('(key, value) : should correctly encode then decode unsafe values', function() {
6767
var $apple = $('.apple', fruits);
6868
$apple.attr('href', 'http://github.com/"><script>alert("XSS!")</script><br');
69-
expect($apple[0].attribs.href).to.equal('http://github.com/&quot;&gt;&lt;script&gt;alert(&quot;XSS!&quot;)&lt;/script&gt;&lt;br');
7069
expect($apple.attr('href')).to.equal('http://github.com/"><script>alert("XSS!")</script><br');
7170

7271
$apple.attr('href', 'http://github.com/"><script>alert("XSS!")</script><br');

0 commit comments

Comments
 (0)