How to parse and iterate prototype methods with Uglify.js?
Asked Answered
K

2

12

I 'd like to parse some JavasScript code to list all methods for a given "class" using uglify js 2. In my case the TreeWalker returns a node with name : null and there is no information that allow conclusions to parent.

Does anyone know a different approach? I expected something like name : "Test.method_name"
So far I tryied the folowing...

parsetests.js

var UglifyJS = require("uglify-js2");
var util = require("util");
var code = require("fs").readFileSync("test.js").toString();
var toplevel = UglifyJS.parse(code);
var log = function(obj, depth) {
    console.log(util.inspect(obj, showHidden=false, depth, colorize=true));
};
var toplevel = UglifyJS.parse(code);
var walker = new UglifyJS.TreeWalker(function(node){
    if (node instanceof UglifyJS.AST_Function ) {
        log(node, 2);        
    }
});
toplevel.walk(walker);

test.js

function Test(argument1) {
    var m = argument1 + "test";
    return this;
}


Test.prototype.method_name = function(first_argument) {
    // body...
    return "a";
};

UglifyJS.TreeWalker node:

{ end:
   { file: null,
     comments_before: [],
     nlb: true,
     endpos: 156,
     pos: 155,
     col: 0,
     line: 10,
     value: '}',
     type: 'punc' },
  start:
   { file: null,
     comments_before: [],
     nlb: false,
     endpos: 111,
     pos: 103,
     col: 29,
     line: 7,
     value: 'function',
     type: 'keyword' },
  body:
   [ { end: [Object],
       start: [Object],
       value: [Object] } ],
  cname: undefined,
  enclosed: undefined,
  parent_scope: undefined,
  uses_eval: undefined,
  uses_with: undefined,
  functions: undefined,
  variables: undefined,
  directives: undefined,
  uses_arguments: undefined,
  argnames:
   [ { end: [Object],
       start: [Object],
       thedef: undefined,
       name: 'first_argument',
       scope: undefined,
       init: undefined } ],
  name: null }
Kweiyang answered 7/4, 2015 at 9:39 Comment(2)
Do you exclusively want to use uglify-js2 or are you open to other solutions?Roommate
This won't be as easy as you think as you'd need to track dynamic allocation through other methods, unless you know they were done a certain way. I think Tern does a bit of analysis like this but I'm not sure whether that's suitable for your needs.Bismuthic
K
5

I wrote a script able to parse and identify those syntax. I open sourced it at https://github.com/s-a/deep-js.

Currently it covers a bunch of use cases described at https://github.com/s-a/deep-js/blob/3c1e52b75be197ff19a5530d011e999416e21afd/use-case-main.js And tested with https://github.com/s-a/deep-js/tree/3c1e52b75be197ff19a5530d011e999416e21afd/test. You can see the results at https://travis-ci.org/s-a/deep-js/builds/58511486. Current code state is limited. For example this could currently not resolved if used over another var like self. Deep nested assignments and namespaces are another problem. However so far it is stable if code complexity is not too high.

Kweiyang answered 14/4, 2015 at 22:23 Comment(0)
A
0

In your case the function does not have a name, it is assigned to a property which has a name. You must name your function as follows:

Test.prototype.method_name = function method_name(first_argument) {
    // body...
    return "a";
};
Anther answered 14/4, 2015 at 14:39 Comment(1)
I don't think you quite understand what the question is asking for. The OP is looking to statically determine the methods that a constructor has, not find the name of a function during debugging.Bismuthic

© 2022 - 2024 — McMap. All rights reserved.