Skip to content

Commit 514705a

Browse files
committed
[msgpack#19, msgpack#21] Implement recursive toJSON compatibility
1 parent 0c4e1c3 commit 514705a

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

‎src/msgpack.cc‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ _free_sbuf(char *data, void *hint) {
9696
// If a circular reference is detected, an exception is thrown.
9797
static void
9898
v8_to_msgpack(Handle<Value> v8obj, msgpack_object *mo, msgpack_zone *mz, size_t depth) {
99+
static const Persistent<String> TOJSON = NODE_PSYMBOL("toJSON");
99100

100101
if (512 < ++depth) {
101102
throw MsgpackException("Cowardly refusing to pack object with circular reference");
@@ -158,6 +159,14 @@ v8_to_msgpack(Handle<Value> v8obj, msgpack_object *mo, msgpack_zone *mz, size_t
158159
mo->via.raw.ptr = Buffer::Data(buf);
159160
} else {
160161
Local<Object> o = v8obj->ToObject();
162+
163+
// for o.toJSON()
164+
if (o->Has(TOJSON) && o->Get(TOJSON)->IsFunction()) {
165+
Local<Function> fn = Local<Function>::Cast(o->Get(TOJSON));
166+
v8_to_msgpack(fn->Call(o, 0, NULL), mo, mz, depth);
167+
return;
168+
}
169+
161170
Local<Array> a = o->GetPropertyNames();
162171

163172
mo->type = MSGPACK_OBJECT_MAP;
@@ -277,16 +286,16 @@ pack(const Arguments &args) {
277286
}
278287

279288
v8::Local<Buffer> slowBuffer = node::Buffer::New(
280-
sb->data, sb->alloc, _free_sbuf, (void *)sb
289+
sb->data, sb->alloc, _free_sbuf, (void *)sb
281290
);
282291

283292
// godsflaw: this part makes msgpack.pack() 1x slower than JSON.stringify()
284293
// reaching back into JS appears to be expensive.
285294
v8::Local<Object> global = v8::Context::GetCurrent()->Global();
286295
v8::Local<Value> bv = global->Get(String::NewSymbol("Buffer"));
287-
296+
288297
assert(bv->IsFunction());
289-
298+
290299
Local<Function> bc = v8::Local<Function>::Cast(bv);
291300
Handle<Value> cArgs[3] = {
292301
slowBuffer->handle_,

‎test/lib/msgpack.js‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,24 @@ exports.msgpack = {
237237
test.deepEqual(expect, msgpack.unpack(msgpack.pack(subject, subject1)));
238238
test.done();
239239
},
240+
'test toJSON compatibility for nested toJSON' : function (test) {
241+
var expect = { msg: 'hello world' };
242+
var subject = {
243+
toJSON: function() {
244+
return [
245+
expect,
246+
{
247+
toJSON: function() {
248+
return expect;
249+
}
250+
}
251+
];
252+
}
253+
};
254+
test.expect(1);
255+
test.deepEqual([expect, expect], msgpack.unpack(msgpack.pack(subject)));
256+
test.done();
257+
},
240258
'test toJSON compatibility with prototype' : function (test) {
241259
var expect = { msg: 'hello world' };
242260
var subject = { __proto__: { toJSON: function() { return expect; }}};

0 commit comments

Comments
 (0)