1.1.6pre - something going wrong with can.computes() in Mustache templates #376

Closed
SteveEisner opened this Issue May 2, 2013 · 7 comments

Comments

Projects
None yet
2 participants
@SteveEisner

Just an FYI since the "1.1.6pre" has been pushed to "latest" on the CDN.

In this version only (same code confirmed working when I switch back to 1.1.5) when rendering a model via mustache template, if I reference a can.compute property via {{name}} the context passed into the compute is the global window, rather than the model... Any compute that is trying to use "this" will break.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 2, 2013

Contributor

Example code/test?

Sent from my iPhone

On May 2, 2013, at 6:03 AM, SteveEisner notifications@github.com wrote:

Just an FYI since the "1.1.6pre" has been pushed to "latest" on the CDN.

In this version only (same code confirmed working when I switch back to 1.1.5) when rendering a model via mustache template, if I reference a can.compute property via {{name}} the context passed into the compute is the global window, rather than the model... Any compute that is trying to use "this" will break.


Reply to this email directly or view it on GitHub.

Contributor

justinbmeyer commented May 2, 2013

Example code/test?

Sent from my iPhone

On May 2, 2013, at 6:03 AM, SteveEisner notifications@github.com wrote:

Just an FYI since the "1.1.6pre" has been pushed to "latest" on the CDN.

In this version only (same code confirmed working when I switch back to 1.1.5) when rendering a model via mustache template, if I reference a can.compute property via {{name}} the context passed into the compute is the global window, rather than the model... Any compute that is trying to use "this" will break.


Reply to this email directly or view it on GitHub.

@SteveEisner

This comment has been minimized.

Show comment
Hide comment
@SteveEisner

SteveEisner May 3, 2013

@justinbmeyer Sorry, I built a fiddle but I can't get it to repro. http://jsfiddle.net/G34Vf/2/
This models what's going on in my class definition and instance use, but it doesn't break.

So instead I'm attaching a souce & stack example of the break from my production code. I realize that a non-executing example may not be that helpful, but this might at least give you an idea?

In the topmost frame, I'm inside a can.compute and "this" is global/window. In the bottom frame, I'm setting an attr of a can.Observe which has been rendered through a mustache template.

I've confirmed that the same code runs just fine if I switch to 1.1.5 ... I don't think I'm doing anything out of the ordinary, but I have hit other boundary cases before with the same code [issue #218]

Source

//=== template (person.mustache) ======
{{#model}}
  .....  {{name}} .....            <-- name is the can.compute
{{/model}}

//===  top frame (person.js) =====
Person = Model({
  // No class methods
},{
  name: can.compute(function() {
    var first = this.attr('first');        <-- line 7, where the error is in the stack below
        *** Uncaught TypeError: Object [object global] has no method 'attr'  ***
    var last = this.attr('last');
    if (!first) return last;
    if (!last) return first;
    return first + ' ' + last;
  })
});

//===  bottom frame (frame.js) =====
  ...
    setModel: function(model) {
      this.attrs.attr({ model: model });   <--- attrs is the Observe instance that was rendered
      return model;
    }
 ....

Stack

Only the top and bottom frames are user code, the rest are can JS modules, generated template code, or jquery.

Model.name (person.js:7)  <-- in this frame, "this" is global
computed (compute.js:213)
Mustache.resolve (mustache.js:724)
Mustache.get (mustache.js:688)
fn.___v1ew.push.can.view.txt.can.Mustache.txt.fn.___v1ew.push.can.view.txt.can.Mustache.txt.context ((program):1)
getValueAndObserved (compute.js:36)
getValueAndBind (compute.js:98)
computeBinder (compute.js:132)
can.extend.txt (render.js:204)
fn.___v1ew.push.can.view.txt.can.Mustache.txt.fn ((program):1)
Mustache.txt (mustache.js:593)
fn.___v1ew.push.can.view.txt.can.Mustache.txt.context ((program):1)
getValueAndObserved (compute.js:36)
getValueAndBind (compute.js:98)
computeBinder (compute.js:132)
can.extend.txt (render.js:204)
fn ((program):1)
Mustache.render (mustache.js:82)
(anonymous function) (mustache.js:51)
can.Control.render (view.js:77)
v.isFunction.s (jquery-1.8.3.min.js:2)
v.event.dispatch (jquery-1.8.3.min.js:2)
o.handle.u (jquery-1.8.3.min.js:2)
v.event.trigger (jquery-1.8.3.min.js:2)
$.extend.trigger (jquery.js:14)
can.Observe.can.Construct.triggerBatch (observe.js:165)
can.Observe.can.Construct._changes (observe.js:212)
v.isFunction.s (jquery-1.8.3.min.js:2)
v.event.dispatch (jquery-1.8.3.min.js:2)
o.handle.u (jquery-1.8.3.min.js:2)
v.event.trigger (jquery-1.8.3.min.js:2)
$.extend.trigger (jquery.js:14)
(anonymous function) (observe.js:153)
can.each (each.js:17)
can.Observe.can.Construct.stopBatch (observe.js:152)
can.Observe.can.Construct._attrs (observe.js:433)
can.Observe.can.Construct.attr (observe.js:235)
declare.setModel (frame.js:33)

@justinbmeyer Sorry, I built a fiddle but I can't get it to repro. http://jsfiddle.net/G34Vf/2/
This models what's going on in my class definition and instance use, but it doesn't break.

So instead I'm attaching a souce & stack example of the break from my production code. I realize that a non-executing example may not be that helpful, but this might at least give you an idea?

In the topmost frame, I'm inside a can.compute and "this" is global/window. In the bottom frame, I'm setting an attr of a can.Observe which has been rendered through a mustache template.

I've confirmed that the same code runs just fine if I switch to 1.1.5 ... I don't think I'm doing anything out of the ordinary, but I have hit other boundary cases before with the same code [issue #218]

Source

//=== template (person.mustache) ======
{{#model}}
  .....  {{name}} .....            <-- name is the can.compute
{{/model}}

//===  top frame (person.js) =====
Person = Model({
  // No class methods
},{
  name: can.compute(function() {
    var first = this.attr('first');        <-- line 7, where the error is in the stack below
        *** Uncaught TypeError: Object [object global] has no method 'attr'  ***
    var last = this.attr('last');
    if (!first) return last;
    if (!last) return first;
    return first + ' ' + last;
  })
});

//===  bottom frame (frame.js) =====
  ...
    setModel: function(model) {
      this.attrs.attr({ model: model });   <--- attrs is the Observe instance that was rendered
      return model;
    }
 ....

Stack

Only the top and bottom frames are user code, the rest are can JS modules, generated template code, or jquery.

Model.name (person.js:7)  <-- in this frame, "this" is global
computed (compute.js:213)
Mustache.resolve (mustache.js:724)
Mustache.get (mustache.js:688)
fn.___v1ew.push.can.view.txt.can.Mustache.txt.fn.___v1ew.push.can.view.txt.can.Mustache.txt.context ((program):1)
getValueAndObserved (compute.js:36)
getValueAndBind (compute.js:98)
computeBinder (compute.js:132)
can.extend.txt (render.js:204)
fn.___v1ew.push.can.view.txt.can.Mustache.txt.fn ((program):1)
Mustache.txt (mustache.js:593)
fn.___v1ew.push.can.view.txt.can.Mustache.txt.context ((program):1)
getValueAndObserved (compute.js:36)
getValueAndBind (compute.js:98)
computeBinder (compute.js:132)
can.extend.txt (render.js:204)
fn ((program):1)
Mustache.render (mustache.js:82)
(anonymous function) (mustache.js:51)
can.Control.render (view.js:77)
v.isFunction.s (jquery-1.8.3.min.js:2)
v.event.dispatch (jquery-1.8.3.min.js:2)
o.handle.u (jquery-1.8.3.min.js:2)
v.event.trigger (jquery-1.8.3.min.js:2)
$.extend.trigger (jquery.js:14)
can.Observe.can.Construct.triggerBatch (observe.js:165)
can.Observe.can.Construct._changes (observe.js:212)
v.isFunction.s (jquery-1.8.3.min.js:2)
v.event.dispatch (jquery-1.8.3.min.js:2)
o.handle.u (jquery-1.8.3.min.js:2)
v.event.trigger (jquery-1.8.3.min.js:2)
$.extend.trigger (jquery.js:14)
(anonymous function) (observe.js:153)
can.each (each.js:17)
can.Observe.can.Construct.stopBatch (observe.js:152)
can.Observe.can.Construct._attrs (observe.js:433)
can.Observe.can.Construct.attr (observe.js:235)
declare.setModel (frame.js:33)
@SteveEisner

This comment has been minimized.

Show comment
Hide comment
@SteveEisner

SteveEisner May 3, 2013

I went looking for other similar bugs and found #305 -- which happens to be exactly the same model I'm trying to create. When I first made these models, I guess I thought that for a function to work in a mustache rendering, it had to be a can.compute (based on examples?) But I've confirmed that my code works with 1.1.6 now if I simply remove the can.compute() and make the "name" method a simple function.

I went looking for other similar bugs and found #305 -- which happens to be exactly the same model I'm trying to create. When I first made these models, I guess I thought that for a function to work in a mustache rendering, it had to be a can.compute (based on examples?) But I've confirmed that my code works with 1.1.6 now if I simply remove the can.compute() and make the "name" method a simple function.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 7, 2013

Contributor

You shouldn't do it that way. Closing this issue.

Contributor

justinbmeyer commented May 7, 2013

You shouldn't do it that way. Closing this issue.

@SteveEisner

This comment has been minimized.

Show comment
Hide comment
@SteveEisner

SteveEisner May 7, 2013

No need to write out a detailed description in a bug, but I'm curious if you have a link that explains why one shouldn't do it that way -- I got the pattern from a canjs team member's code at: https://forum.javascriptmvc.com/topic/can-compute-crazies

If I want to be able to observe the "name" attribute, how should I build the model instead?

No need to write out a detailed description in a bug, but I'm curious if you have a link that explains why one shouldn't do it that way -- I got the pattern from a canjs team member's code at: https://forum.javascriptmvc.com/topic/can-compute-crazies

If I want to be able to observe the "name" attribute, how should I build the model instead?

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 7, 2013

Contributor

#305 shows how

Contributor

justinbmeyer commented May 7, 2013

#305 shows how

@SteveEisner

This comment has been minimized.

Show comment
Hide comment
@SteveEisner

SteveEisner May 7, 2013

Thanks!

On Tue, May 7, 2013 at 9:41 AM, Justin Meyer notifications@github.comwrote:

#305 #305 shows how


Reply to this email directly or view it on GitHubhttps://github.com/bitovi/canjs/issues/376#issuecomment-17554192
.

Thanks!

On Tue, May 7, 2013 at 9:41 AM, Justin Meyer notifications@github.comwrote:

#305 #305 shows how


Reply to this email directly or view it on GitHubhttps://github.com/bitovi/canjs/issues/376#issuecomment-17554192
.

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