1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00

Support __proto__ and similar as object attribute in hgetall

This commit is contained in:
Ruben Bridgewater
2016-04-13 03:48:33 +02:00
parent a11e0c5ff9
commit 228573b8d7
4 changed files with 25 additions and 37 deletions

8
lib/rawObject.js Normal file
View File

@@ -0,0 +1,8 @@
'use strict';
// Using a predefined object with this prototype is faster than calling `Object.create(null)` directly
// This is needed to make sure `__proto__` and similar reserved words can be used
function RawObject () {}
RawObject.prototype = Object.create(null);
module.exports = RawObject;

View File

@@ -1,5 +1,7 @@
'use strict'; 'use strict';
var RawObject = require('./rawObject');
// hgetall converts its replies to an Object. If the reply is empty, null is returned. // hgetall converts its replies to an Object. If the reply is empty, null is returned.
// These function are only called with internal data and have therefor always the same instanceof X // These function are only called with internal data and have therefor always the same instanceof X
function replyToObject (reply) { function replyToObject (reply) {
@@ -7,7 +9,7 @@ function replyToObject (reply) {
if (reply.length === 0 || !(reply instanceof Array)) { if (reply.length === 0 || !(reply instanceof Array)) {
return null; return null;
} }
var obj = {}; var obj = new RawObject();
for (var i = 0; i < reply.length; i += 2) { for (var i = 0; i < reply.length; i += 2) {
obj[reply[i].toString('binary')] = reply[i + 1]; obj[reply[i].toString('binary')] = reply[i + 1];
} }

View File

@@ -22,10 +22,10 @@ describe("The 'hgetall' method", function () {
}); });
it('handles simple keys and values', function (done) { it('handles simple keys and values', function (done) {
client.hmset(['hosts', 'mjr', '1', 'another', '23', 'home', '1234'], helper.isString('OK')); client.hmset(['hosts', '__proto__', '1', 'another', '23', 'home', '1234'], helper.isString('OK'));
client.HGETALL(['hosts'], function (err, obj) { client.HGETALL(['hosts'], function (err, obj) {
assert.strictEqual(3, Object.keys(obj).length); assert.strictEqual(3, Object.keys(obj).length);
assert.strictEqual('1', obj.mjr.toString()); assert.strictEqual('1', obj.__proto__.toString()); // eslint-disable-line no-proto
assert.strictEqual('23', obj.another.toString()); assert.strictEqual('23', obj.another.toString());
assert.strictEqual('1234', obj.home.toString()); assert.strictEqual('1234', obj.home.toString());
return done(err); return done(err);

View File

@@ -206,49 +206,27 @@ describe('publish/subscribe', function () {
sub.subscribe(channel); sub.subscribe(channel);
}); });
it('handles SUBSCRIBE_CLOSE_RESUBSCRIBE', function (done) { it('subscribe; close; resubscribe with prototype inherited property names', function (done) {
var count = 0; var count = 0;
/* Create two clients. c1 subscribes to two channels, c2 will publish to them. var channels = ['__proto__', 'channel 2'];
c2 publishes the first message. var msg = ['hi from channel __proto__', 'hi from channel 2'];
c1 gets the message and drops its connection. It must resubscribe itself.
When it resubscribes, c2 publishes the second message, on the same channel
c1 gets the message and drops its connection. It must resubscribe itself, again.
When it resubscribes, c2 publishes the third message, on the second channel
c1 gets the message and drops its connection. When it reconnects, the test ends.
*/
sub.on('message', function (channel, message) { sub.on('message', function (channel, message) {
if (channel === 'chan1') { var n = Math.max(count - 1, 0);
assert.strictEqual(message, 'hi on channel 1'); assert.strictEqual(channel, channels[n]);
sub.stream.end(); assert.strictEqual(message, msg[n]);
} else if (channel === 'chan2') { if (count === 2) return done();
assert.strictEqual(message, 'hi on channel 2'); sub.stream.end();
sub.stream.end();
} else {
sub.quit();
pub.quit();
assert.fail('test failed');
}
}); });
sub.subscribe('chan1', 'chan2'); sub.subscribe(channels);
sub.on('ready', function (err, results) { sub.on('ready', function (err, results) {
pub.publish(channels[count], msg[count]);
count++; count++;
if (count === 1) {
pub.publish('chan1', 'hi on channel 1');
return;
} else if (count === 2) {
pub.publish('chan2', 'hi on channel 2');
} else {
sub.quit(function () {
pub.quit(function () {
return done();
});
});
}
}); });
pub.publish('chan1', 'hi on channel 1'); pub.publish(channels[count], msg[count]);
}); });
}); });