Skip to content
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

Caching bug with template inheritance #206

Open
David-Mulder opened this issue Sep 29, 2014 · 5 comments · May be fixed by #255
Open

Caching bug with template inheritance #206

David-Mulder opened this issue Sep 29, 2014 · 5 comments · May be fixed by #255
Assignees

Comments

@David-Mulder
Copy link

Ok, so I am not sure of all terminology and everything (pretty new to mustache still), but I was able to boil it down to a pretty small test case that shows the functionality

Express

router.get('/a', function(req, res) {
    res.render("A");
});
router.get('/b', function(req, res) {
    res.render("B");
});

A.mustache

{{<C}}
     {{$C}}
          A
     {{/C}}
{{/C}}

B.mustache

{{<C}}
     {{$C}}
          B
     {{/C}}
{{/C}}

C.mustache

{{>D}}
C: {{$C}}{{/C}}

D.mustache

D: {{$C}}{{/C}}

Now, load up /a and then /b, the first will output D: AA C: AA as expected, the second D: AA C: BB, now reload node.js and load up /b first and then /a and you get the exact opposite (D: BB gets 'stuck'). I have tried figuring this one out myself, but I got lost in the source code entirely.

@TenaciousDarius
Copy link

+1 We've been seeing this as well. The issue arises when you cache partials after compiling them and have an inheritance hierarchy similar to the following:

Grandparent
^
Parent
^
Child1 Child2

When Child1 is rendered, Parent has Child1 set as one of it's partials. Then when Child2 is rendered, Parent isn't reloaded and it's the content of Child1 which we see. The opposite is true if we load Child2 first. If the partials are loaded from the FS on every page load the problem goes away.

We've created a snippet which illustrates the problem. The second time the tests are run, the output matches the first test rather than the second.

var Hogan = Hogan || require('./lib/hogan');

var tests = [{
    template: "{{<parent}}{{$a}}c{{/a}}{{/parent}}",
    partials: {
        parent: "{{<grandParent}}{{$a}}p{{/a}}{{/grandParent}}",
        grandParent: "{{$a}}g{{/a}}"
    },
    expected: "c"
}, {
    template: "{{<parent}}{{/parent}}",
    partials:{
        parent: "{{<grandParent}}{{$a}}p{{/a}}{{/grandParent}}",
        grandParent: "{{$a}}g{{/a}}"
    },
    expected: "p"
}],
    cache={},
    getResults=function(test){
        var output = cache[test.template].template.render({},   cache[test.template].partials);
        console.log('---------------');
        console.log(test.template);
        console.log("output:"+output);
        console.log("expected:"+test.expected);
    };

tests.forEach(function(test) {
    var partials = {};

    for (var i in test.partials) {
        partials[i] = Hogan.compile(test.partials[i]);
    }
    cache[test.template]={
        template: Hogan.compile(test.template),
        partials:partials
    };
    getResults(test);

});

/* renders reference previous paritals */
tests.forEach(function(test) {
    getResults(test);
});

Has anyone else seen this issue or found a solution please? We're at the point of avoiding inheritance and using composition instead but would be useful to know if there's a solution. Thanks for any help in advance.

@David-Mulder
Copy link
Author

No such luck here at least@finding a solution. I somehow worked myself around it, but it's an ugly bug indeed.

@TenaciousDarius
Copy link

I see, sad panda. We'll work around it by using composition rather than inheritance I guess. Thanks very much for responding. I might take a closer looks at how hogan works over the weekend to see if a fix presents itself.

@paulwib
Copy link

paulwib commented Aug 13, 2015

+1

Same thing here, here's another set of steps to reproduce:

var hogan = require('hogan.js');

var layouts = {
  outerLayout: hogan.compile('OUTER: {{$inner}}Inner stuff goes here{{/inner}}'),
  innerLayout: hogan.compile('{{<outerLayout}}{{$inner}}INNER: {{$content}}Content goes here{{/content}}{{/inner}}{{/outerLayout}}')
};
var page1 = hogan.compile('{{<innerLayout}}{{$content}}Page 1{{/content}}{{/innerLayout}}');
var page2 = hogan.compile('{{<innerLayout}}{{$content}}Page 2{{/content}}{{/innerLayout}}');

console.log(page1.render({}, layouts));
console.log(page2.render({}, layouts));
$ node index.js
OUTER: INNER: Page 1
OUTER: INNER: Page 1

If you switch the rendering order this will change to "Page 2".

paulwib added a commit to paulwib/hogan.js that referenced this issue Aug 17, 2015
@setthase
Copy link

Any news about this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants