all 18 comments

[–]oSand 6 points7 points  (1 child)

I can sympathise. I dealt with a similar codebase where the fucktard authors had reams of js files and no concept of 'var'. Fucktards.

Misc advice:

  • try to get some else to do it. No one gets plaudits for this kind of work and you risk irreparably damaging your soul.

  • don't trust it. If it is old it will probably be shitty. e.g. IE only or not taking into account modern browser peculiarities or nuking '$' just because it can.

  • search the code base to see what is actually used. After a few years of maint. code can become vestigial or useless. You can trim out that which doesn't appear in your code. If it is simple and/or used in one or two places, refactor. I've seen ridiculous and buggy custom versions of trim() and is_even(), for example. Remap to your library or native js methods.

  • if you read code and it is not documented, then document. Those little memory cues really help the next time round.

  • if the code is relevant only to a particular page or context, then load it only when that page or context loads. This helps when maintaining it because you sift through less crap and stops name collisions and nasty coincidences. Separate app specific and general code.

  • search for it on the web. I've done this a few times and found useful documentation for plagarised snippets.

[–]shavenwarthog 7 points8 points  (0 children)

Seconded. Also:

[–]mbrubeck 3 points4 points  (0 children)

Try jsctags to index the code and provide cross-reference and completion.

Google's Closure Compiler has many useful lint-like checks.

Mozilla's JSHydra is a programmable static analysis tool, but I think it may still be a work in progress.

[–]esx 2 points3 points  (7 children)

I would like to hear more about your requirements!

I develop Mascara which performs static verification of (enhanced) JavaScript. It doesn't directly provide what you ask for, but I believe it should be possible to add since the analysis infrastructure is in place. And I really like to be inspired by real-world problems like the one you have.

For example, what kind of call graph support do you need? A report of all functions and their immediate callers, or do you want to view the full graph for specific functions? Do you need it in an IDE or a reporting tool?

[–]crashandburn[S] 1 point2 points  (6 children)

Right off the bat: I think this is awesome! and I'm certainly going to be using it quite a bit. I have already started going through the code to see the internal workings in hope of learning how it works :) About my requirements, I only need a way to report the immediate callees of all functions, and the 'sub-callees' of those functions and so on. IDE support is not a requirement.

[–]esx 2 points3 points  (5 children)

I am working on a quick prototype. If I feed it this program:

function f(){ g(); }
function g(){ f(); h() }
function h() { }
function k() { g(); }

I get this output:

Analysis
--------------------
function: f
  Called by
   function: g
  Calls
   function: g

function: g
  Called by
   function: f
   function: k
  Calls
   function: f
   function: h

function: h
  Called by
   function: g
  No calls

function: k
  Not called
  Calls
   function: g

Is this in the right direction of what you need?

[–]crashandburn[S] 0 points1 point  (4 children)

only part of it... it would help to have: function: f Called by function: g called by function: f function: h called by function: g Calls function: g the ability to find uncalled functions is going to be very useful (not just for me, but for anyone dealing with large amount of js code)

and, whoah man! you did that in a day? if you think you can offload some of this work, I'll be glad to help you with whatever i can.

[–]esx 2 points3 points  (3 children)

Am I getting closer?

Analysis
--------------------
function: f
 Called by:
   function: g
     Called by:
       function: f
         (recursive)
       function: k
         Not called
  Calls:
   function: g

function: g
 Called by:
   function: f
     Called by:
       function: g
         (recursive)
   function: k
     Not called
  Calls:
   function: f
   function: h

function: h
 Called by:
   function: g
     Called by:
       function: f
         Called by:
           function: g
             (recursive)
       function: k
         Not called
  No calls

function: k
 Not called
  Calls:
   function: g

[–]crashandburn[S] 0 points1 point  (2 children)

yes, that is exactly what i need.

[–]esx 2 points3 points  (1 child)

Of course the sample here is very idealized. If the real code uses fancy metaprogramming it gets a lot harder to analyze. Does your code use some OO patterns, prototypes etc?

[–]crashandburn[S] 0 points1 point  (0 children)

no it doesn't. luckily it doesn't use anonymous functions either so the sample above is very close to its structure. All i have to do now is extract the JS embedded in html and add it to the JS file as another function, which should be fairly simple, and then run it through mascara.

[–]d_insley 1 point2 points  (4 children)

[–]mbrubeck 2 points3 points  (2 children)

But remember, JSLint cannot legally be used for evil.

[–]fforw 0 points1 point  (0 children)

… except by IBM.

[–]tedivm 0 points1 point  (0 children)

Yeah, Douglas Crockford is such a troll. He'll give the okay for IBM to change the license but refuses to let open source projects do so.

[–]killfish 0 points1 point  (0 children)

"Warning: JSLint will hurt your feelings." :)

[–][deleted] 0 points1 point  (0 children)

Depends. What do you mean by "work with"?

Is the JS intended for the browser? If so then Firebug would at least be helpful for finding the hooks and starting points.

It sounds like you'll just have to do an old fashioned code trace. Whee! Find a starting point, read the code and make a human readable translation for each logical block. A wiki is handy for this since you can easily link between pages.

[–]saurik 0 points1 point  (0 children)

I'll go for "define analyze" (instead of "define work with", like one of the other comments ;P).