New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning a custom EJSON object from a method doesn't seem to work. #731

Closed
sjoerdvisscher opened this Issue Feb 22, 2013 · 2 comments

Comments

Projects
None yet
3 participants
@sjoerdvisscher

sjoerdvisscher commented Feb 22, 2013

I wanted to play with EJSON in the new 0.5.7 a bit, so I created a new meteor project and added the following bit of js. (I've deployed it on http://ejson-github-issue.meteor.com)

if (Meteor.isClient) {
  Template.hello.greeting = function () {
    return "Click the button";
  };

  Template.hello.events({
    'click input' : function () {
      Meteor.call("getDog", new Dog("brown", "stinky"), function(_, dog) {
        console.log(dog.toString(), dog);
      });
    }
  });
}

function Dog(fur, breath) {
  this.fur = fur;
  this.breath = breath;
}
Dog.prototype.clone = function() {
  console.log("cloning: " + this)
  return new Dog(this.fur, this.breath);
}
Dog.prototype.equals = function(that) {
  console.log("equals")
  return this.fur == that.fur && this.breath == that.breath;
}
Dog.prototype.typeName = function() {
  console.log("typeName")      
  return "Dog";
}
Dog.prototype.toJSONValue = function() {
  console.log("serializing: " + this)
  return {
    fur: this.fur,
    breath: this.breath
  }
}
Dog.prototype.toString = function() {
  return "A " + this.fur + " dog with " + this.breath + " breath."
}

EJSON.addType("Dog", function(obj) {
  console.log("parsing: ", obj)
  return new Dog(obj.fur, obj.breath);
})

if (Meteor.isServer) {
  Meteor.methods({
    getDog: function(dog)
    {
      console.log("Got: ", dog.toString())
      return new Dog(dog.fur, dog.breath);
    }
  });
}

A click on the button sends a Dog object to the server, and the server sends a Dog object back.

What I see in the console on the client is:

cloning: A brown dog with stinky breath. ejson.js:20
typeName ejson.js:28
typeName ejson.js:28
serializing: A brown dog with stinky breath. ejson.js:32
[object Object] Object {fur: "brown", breath: "stinky"} ejson.js:9

And on the server:

parsing:  { fur: 'brown', breath: 'stinky' }
Got:  A brown dog with stinky breath.
cloning: A brown dog with stinky breath.

So when sending the Dog object from client to server, the object is first cloned, then serialized on the client, and then parsed on the server, and the method receives a proper Dog object.

But when sending the Dog object from server to client, only the cloning happens. typeName is never called, and serializing and parsing doesn't happen. So the clients receives a plain JSON object.

@glasser

This comment has been minimized.

Member

glasser commented Feb 27, 2013

Good catch! The bug appears to be in Meteor._stringifyDDP:

  // adjust types to basic
  _.each(['fields', 'params', 'result'], function (field) {
    if (_.has(copy, field))
      EJSON._adjustTypesToJSONValue(copy[field]);
  });

EJSON._adjustTypesToJSONValue doesn't actually work if copy[field] itself is an extended type (as opposed to an element inside it, which is what happens for fields and params).

@ghost ghost assigned sixolet Feb 27, 2013

sixolet pushed a commit that referenced this issue Feb 28, 2013

Naomi Seyfer
Fix for returning a scalar EJSON type from a method #731
Tests for returning a scalar EJSON type from a method
@sixolet

This comment has been minimized.

Contributor

sixolet commented Feb 28, 2013

Fixed on devel as of 88f2969

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment