JavaScript/Dojo Module Pattern - how to debug?

2019-05-01 09:04发布

问题:

I'm working with Dojo and using the "Module Pattern" as described in Mastering Dojo. So far as I can see this pattern is a general, and widely used, JavaScript pattern. My question is: How do we debug our modules?

So far I've not been able to persuade Firebug to show me the source of my module. Firebug seems to show only the dojo eval statement used to execute the factory method. Hence I'm not able to step through my module source. I've tried putting "debugger" statements in my module code, and Firebug seems to halt correctly, but does not show the source.

Contrived example code below. This is just an example of sufficient complexity to make the need for debugging plausible, it's not intended to be useful code.

The page

<!--
  Experiments with Debugging
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head> 
    <title>console me</title>

    <style type="text/css">
      @import "../dojoroot/dojo/resources/dojo.css";
      @import "../dojoroot/dijit/themes/tundra/tundra.css";
      @import "edf.css";
    </style>    

    <script type="text/javascript" src="../dojoroot/dojo/dojo.js">
    </script>

    <script type="text/javascript" >
      dojo.registerModulePath("mytest", "../../mytest");

      dojo.require("mytest.example");

      dojo.addOnLoad(function(){
         mytest.example.greet();                     
      });
    </script>

  </head>
  <body class="tundra">
    <div id="bulletin">
      <p>Just Testing</p>
    </div>
  </body>
</html>
<!-- END: snip1 -->

The java script I'd like to debug

dojo.provide("mytest.example");
dojo.require("dijit.layout.ContentPane");

/**
 * define module
 */
(function(){
      //define the main program functions...
      var example= mytest.example;
      example.greet= function(args) {

          var bulletin = dojo.byId("bulletin");

          console.log("bulletin:" + bulletin);

          if ( bulletin) {
                var content = new dijit.layout.ContentPane({
                    id: "dummy",
                    region: "center"
                  });
                content.setContent('Greetings!');

                dojo._destroyElement(bulletin);
                dojo.place(content.domNode, dojo.body(), "first");
              console.log("greeting done");
          } else {
              console.error("no bulletin board");
          }           
      }
})(); 

回答1:

(Answering this myself because it seems like a common problem whose solution is not well known.)

It seems that one can nicely debug eval-ed code in FireBug provided that dojo does a little cooperating. The trick is to configure dojo to enable such debugging using debugAtAllCosts

<script type="text/javascript" src="/dojoroot/dojo/dojo.js"
        djConfig="parseOnLoad: true, debugAtAllCosts: true"></script>

This is described on dojo campus under debugging, which also notes that this setting is not recommended in production for performance reasons and suggests an approach using server-side conditionality to control whether such debugging is enabled.



回答2:

The pattern is essentially xhr+eval... really it's the eval that's the problem... Firefox in particular has no way to track code from an eval back to its original source and instead points at the eval call site, plus whatever line offset there is in the eval buffer. Firebug has implemented a clever scheme to workaround this problem, and added an optional hint which loaders like Dojo can use to embed the original file path in a comment. Webkit now supports this scheme also. It's not perfect, but debugger; and other breakpoints ought to bring you into the correct buffer.

I'm not sure why none of this would be working for you. Which version of Firebug are you using?



回答3:

Also, if you are using a version of Firebug less than 1.7a10 also verify that you have the "Decompile for eval() source" on the scripts drop-down disabled (extensions.firebug.decompileEvals in about:config). When enabled I think this causes Firebug to overwrite the source with its own decompiled version and somehow lose the filename along the way as well.

@peller, This could be why your answer wasn't working for us.

It's disabled by default, but I turned it on at some point and didn't realize it.

It's also being removed completely in 1.7a10 as part of Firebug issue http://code.google.com/p/fbug/issues/detail?id=4035. Also related discussion at https://groups.google.com/d/topic/firebug/y2VR17IFHHI/discussion and https://groups.google.com/d/topic/dojo-interest/nWlZdJDlic8/discussion.



回答4:

Here's a solution I found for the inability to recurse into dojo.require mudules from reading the NGs.

Change

<script src="dojoroot/dojo/dojo.js" type="text/javascript">

to

<script src="dojoroot/dojo/dojo.js.uncompressed.js" type="text/javascript">

This fixes the less than helpful undefineddojo._scopeArgs = [undefined]; error that one sees otherwise.



回答5:

djna's debugAtAllCosts solution works for me, for the reasons described at http://dojotdg.zaffra.com/tag/dojorequire/.

However, note that using debugAtAllCosts causes dojo.require to become asynchronous because it uses script inserts rather than xhr+eval. This can cause problems with code that expects dojo.require to be synchronous that isn't brought in using require itself (as described at http://kennethfranqueiro.com/2010/08/dojo-required-reading/). In my case it was testing code I had being run by unit test framework. So the following failed saying that EntityInfo was not defined

var e1 = new EntityInfo();

until I changed it to

dojo.addOnLoad(function() {
  var e1 = new EntityInfo();
}

@peller, For me FireBug 1.6.1 will take me to the right eval block but not the right file and line numbers (because its an eval string rather than the original file)..



回答6:

I'll add one more alternative, use Chrome. It's great for debugging evals (seems to catch some things Firebug doesn't). Do be aware of its issue with caching JS files - http://code.google.com/p/chromium/issues/detail?id=8742.

Personally Firebug is still my main environment, but I am now also using Chrome when things get tricky with evals to get a second view at the problem. Chrome helped me twice yesterday with undefined function/variable issues with the dojo loader that Firebug skipped right past).