You've already forked node-redis
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:
8
lib/rawObject.js
Normal file
8
lib/rawObject.js
Normal 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;
|
@@ -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];
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user