如何从Javascript获取所有函数和顶级名称

时间:2014-01-04 20:03:37

标签: javascript static static-analysis introspection ffi

我正在尝试编写一个程序,它将在Javascript和另一种语言(Elm)之间自动生成FFI文件。

我在想,是否有任何工具可以使用Javascript模块并列出所有可用的功能,可能带有参数数量?如果它只能做顶级函数,那没关系,我意识到这会因闭包和thunks等而变得复杂。

是否可以在Javascript中做一些类似内省的内容,或者我是否必须使用某种解析器/分析器?如果是这样,是否存在任何此类工具并且相当成熟/易于使用?

编辑:我意识到JavaScript是动态的。我的主要目标是为库和API生成FFI接口,所以那里的东西应该很容易静态推理,因为它们不会动态地改变。我没关系,如果它不完美,我正在寻找一种工具来减轻我对样板的写作,而不是保证防弹的东西。

2 个答案:

答案 0 :(得分:2)

对你来说很棘手的是,创建Javascript模块有许多不同的约定:将变量放在全局范围内,从文件返回表等等。模块创建也非常动态,所以它可能是更容易从Javascript内部做事。

假设您可以使用与模块对应的javascript对象,可以使用for in循环进行检查:

var myModule = ...
for(var key in myModule){
  if( Object.hasOwnProperty.call(myModule, key) ){
    var func = myModule[key];
    ...
  }
}

要检查对象属性是否为函数,可以使用typeof运算符:

if(typeod func == "function")

并查看参数的数量,您可以检查函数的length属性:

func.length

请注意,如果函数是可变参数或以其他方式从arguments数组获取参数,则参数的数量可能是错误的。但检查源文本的内容也会出错......

答案 1 :(得分:2)

可以在node.js中执行此操作。运行脚本时出于安全原因: node script.js无法查看nodejs提供的global对象中的函数或变量,但在运行带node -e "some script"的脚本时,可以访问global object中的函数和变量。

所以我写了3个脚本。

  1. 读取需要解析的文件(scriptThatNeedsToBeParsed.js)和解释文件(interpretFile.js)。合并它们并使用node -e combinedFileContents
  2. 创建一个进程
  3. 需要解析的脚本
  4. 用于解释已解析文件的脚本
  5. <强> scriptThatNeedsToBeParsed.js:

    function A(a,b,c){}
    var abc;
    function T(){}
    

    <强> readFile.js:

    我正在读取需要解析的文件,我定义了2个变量: 在文件内容之前START_FROM_THIS_OBJECT,在文件内容之后END_TO_THIS_OBJECT。所以稍后我会知道在哪里搜索函数和变量。

    if(process.argv.length !=4 )
    {
        console.log("Usage %s <input-file> <interpret-file>",process.argv[0]);
        process.exit(0);
    }
    var input_file = process.argv[2];
    var interpret_file = process.argv[3];
    var fs = require('fs');
    var fileToParse = ";var START_FROM_THIS_OBJECT;";
    fileToParse += fs.readFileSync(input_file, "utf8");
    var interpretFile = fs.readFileSync(interpret_file, "utf8");
    fileToParse += ";var END_TO_THIS_OBJECT;";
    var script = fileToParse + interpretFile;
    var child = require('child_process').execFile('node', 
    [ 
        '-e', script, 
    ], function(err, stdout, stderr) { 
        console.log(stdout); 
    });
    

    <强> interpretFile.js: 我只是在上面定义的2个控制变量之间搜索函数和变量

    var printObjects = false;
    for(var item in global)
    {
        if(item == "END_TO_THIS_OBJECT")
        {
            printObjects = false;
        }
        if(printObjects)
        {
    
            if(typeof(global[item]) == "function")
            {
                console.log("Function :%s with nr args: %d",item,global[item].length); 
            }
            else
            {
                console.log("Variable :%s with value: %d",item,global[item]); 
            }
        }
        if(item == "START_FROM_THIS_OBJECT")
        {
            printObjects = true;
        }
    }
    

    来自nodejs的global对象的最后一部分:console.log(global);

         module:
          { id: '[eval]',
            exports: {},
            parent: undefined,
            filename: 'E:\\LOCAL\\xampp\\htdocs\\nodejs\\[eval]',
            loaded: false,
            children: [],
            paths:
             [ 'E:\\LOCAL\\xampp\\htdocs\\nodejs\\node_modules',
               'E:\\LOCAL\\xampp\\htdocs\\node_modules',
               'E:\\LOCAL\\xampp\\node_modules',
               'E:\\LOCAL\\node_modules',
               'E:\\node_modules' ] },
         __dirname: '.',
         require:
          { [Function: require]
            resolve: [Function],
            main: undefined,
            extensions: { '.js': [Function], '.json': [Function], '.node': [Function] },
            registerExtension: [Function],
            cache: {} },
         START_FROM_THIS_OBJECT: undefined,<<<<<<<<<<<<<<
         A: [Function: A],
         abc: undefined,
         T: [Function: T],
         END_TO_THIS_OBJECT: undefined,<<<<<<<<<<<<<<<<
    

    我用以下代码运行脚本:node readFile.js scriptThatNeedsToBeParsed.js interpretFile.js 这是输出:
    功能:A与nr args:3
    变量:abc with value:NaN
    功能:T with nr args:0