Search code examples
javascriptdebuggingunderscore.jsunderscore.js-templating

Underscore template doesn't work in debugger


// run with console open
//and paste following when you hit the debugger:

/*
_.templateSettings = {
  interpolate: /\{\{(.+?)\}\}/g
};

var template = _.template("Hello {{ name }}!");

console.log(template({name: "Mustache"}))
*/
debugger
//should return:
//underscore-min.js:5Uncaught TypeError: Cannot read property 'call' of undefined

//out of debugger though, it works:
_.templateSettings = {
  interpolate: /\{\{(.+?)\}\}/g
};
var template = _.template("Hello {{ name }}!");
console.log(template({name: "Mustache"}))
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

I can't run underscore's sample template code while in a debugger (I want to play with actual data in the console).

  1. code in .js file runs fine. ✓
  2. pasted in console after page load runs fine. ✓
  3. pasted in at time of debugger breakpoint - doesnt work. ✘

    _.templateSettings = {
        interpolate: /\{\{(.+?)\}\}/g
    }
    
    var template = _.template("Hello {{ name }}!");
    
    template({name: "Mustache"});
    

    Error:

    underscore.js:1461 Uncaught TypeError: Cannot read property 'call' of undefined
    

edit:


Errors on template({name: "Mustache"});

Line 1461 of Underscore version 1.8.3:

var template = function(data) {
  return render.call(this, data, _);
};

Solution

  • This is a symptom of Function instantiation (underscore line 1454), and it can be recreated using the following statement:

    new Function('return true;')
    

    With any page open in the browser (even this one), copy this into the console and execute, it will print the following:

    function anonymous() {
        return true;
    }
    

    However if the page is currently Paused in debugger the statement returns undefined. I tried running the same in Firefox, it doesn't work either, doesn't even return.

    I can't explain the effect on the V8 (Chrome) or SpiderMonkey (Firefox) Javascript engines when they are paused in the debugger.

    If you really need it, here's a workaround: https://jsfiddle.net/na4Lpt7L/

    var source = "Hello {{ name }}!";
    debugger;
    var template = _.template(source);
    debugger;
    

    When the first breakpoint hits:

    > source = "Goodbye {{ name }}!";
    < "Goodbye {{ name }}!"
    

    Now continue execution, and on the second breakpoint:

    > template({name: "Mustache"});
    < "Goodbye Mustache!"
    

    If you want to try a few options I'd say stick it in a loop (while (source.length) { ... })