Issue with __nextSuper


#1

I posted this on StackOverflow, but I want to parrot the post here. I worked on this issue all weekend and didn’t get anywhere, so I’d like to get a little more exposure on it. Hopefully somebody out there can help. Here’s the link to the original question. And here’s the content:


Moving from Ember 1.5.1 to 1.6.0, I’ve run into an issue with __nextSuper (which has been changing in the last few versions). You can see the offending code here.

And here’s the relevant Ember code:

function wrap(func, superFunc) {
  function superWrapper() {
    var ret, sup = this.__nextSuper; // THIS LINE
    this.__nextSuper = superFunc;
    ret = apply(this, func, arguments);
    this.__nextSuper = sup;
    return ret;
  }

  superWrapper.wrappedFunction = func;
  superWrapper.wrappedFunction.__ember_arity__ = func.length;
  superWrapper.__ember_observes__ = func.__ember_observes__;
  superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
  superWrapper.__ember_listens__ = func.__ember_listens__;

  return superWrapper;
};

What happens is, at some point, the superWrapper function gets called with window as the this value. So when I reach the line marked above, this.__nextSuper comes out to be undefined. But rather than sup simply being undefined, it throws the following error:

TypeError: Cannot read property '__nextSuper' of undefined

The thing is, when I pause in the debugger, this is defined (it’s the window object). And when I paste var ret, sup = this.__nextSuper; into the console, it works as expected. And, if I go up the stack frame and check the this value, it’s exactly what I expect. So I have no idea why superWrapper suddenly has a bad this value.

Finally, the most interesting part, this only happens in the browser; it works fine in PhantomJS. The changelog didn’t seem to list anything to do with __nextSuper as a breaking bugfix, but obviously something has changed. How can I solve this issue?


#2

Can you recreate the bad behavior in a jsbin? I authored the famous/infamous nextSuper stuff, and would be happy to look into this more.


#3

FWIW, most __nextSuper issues are related to _super being called in an asynchronous way. This previously worked, but the behavior changed when we repaired a different, more infinite-looping bug.


#4

Here’s a quick JSBin that produces the issue. It’ll probably be pretty difficult to debug in JSBin though, so if you wanted to, you could just clone and run the tests from the Ember-Graph repo directly (just be sure to change Ember 1.5.1 for 1.6.0).

FWIW, most __nextSuper issues are related to _super being called in an asynchronous way. This previously worked, but the behavior changed when we repaired a different, more infinite-looping bug.

This was actually the first thing I checked. But I actually don’t call this._super() at all, so I’m fairly sure it can’t be that.


#5

Ember has a requirement on a super method being called from the scope of the object. In your case you’d want to keep track of the scope, then call it using it:

(scope is the object that houses isEqual)

 var scope = meta.isEqual ? meta : this.get('store').attributeTypeFor(meta.type);

 if (scope.isEqual(server, value)) { ...

instead of (scope is window and explodes in 1.6+)

 var isEqual = meta.isEqual || this.get('store').attributeTypeFor(meta.type).isEqual;
 if (isEqual(server, value)) {

I’m not sure if this is a bug, or intended.

These look like the offending lines: https://github.com/gordonkristan/ember-graph/pull/43/files

Here’s a super simple example showing the problem (1.6+): http://emberjs.jsbin.com/yelesahe/1/edit

And working in 1.5.1: http://emberjs.jsbin.com/zedevudo/1/edit

Issue: https://github.com/emberjs/ember.js/issues/5198