UNPKG

strong-trace

Version:

StrongTrace Node.js Tracer

74 lines (57 loc) 2.36 kB
scopenodes ===== Find the AST nodes from a string of JavaScript that define scope. E.g. The outer Program scope and functions. Example --- ```javascript var scopenodes = require("./scopenodes") var fs = require("fs") var filename = process.argv[2] || "./test/lib/nested.js" var content = fs.readFileSync(filename).toString() var out = scopenodes(content) console.log(out) /* [ { type: 'Program', body: [ [Object], [Object] ], range: [ 0, 116 ], loc: { start: [Object], end: [Object] }, path: [], parent: null }, { type: 'BlockStatement', body: [ [Object] ], range: [ 21, 69 ], loc: { start: [Object], end: [Object] }, path: [ [Object] ], parent: { type: 'FunctionDeclaration', id: [Object], params: [Object], ... */ ``` API === `scopenodes(jsString)` --- Will return a list of nodes from an AST (Esprima) that define scoped blocks of the provided JavaScript string. It will add some properties to each node: * fnName: An attempted guess at the function name. It should always be right if the function is named. * path: A list of outer scopes in order of scopechain for this node * parent: For a FunctionDeclaration or FunctionExpression node, the declaration or expression. * isStrict: a boolean value as to whether *THIS SCOPE SPECIFICALLY* has declared strict mode. Does not account for inherited strict mode. Naming generally works like the following, and may change as we go: 1. If the function is named, use that name. 2. If it is an assigment, use what it is assigned to 3. If it is a function call argument or `new` argument, call it "fnName() fn argument" where fnName is the function called. 4. If the call is complex (contains a parenthesis) attempt to remove all but the last bit. (e.g. foo.map(...).sort(...).forEach(...) will become ".forEach() fn argument") 5. If the function looks like listener for an on event (e.g. `foo.on('exit', ...))` call it `foo.on 'exit' listener` 6. In any of the above cases if that name has already been assigned, start indexing the names like so: foo, foo{2}, foo{3}, etc. Naming nests with scope, so if you have code such as this: ```js function foo() { function bar() { // ... } } ``` The two functions would be named `foo` and `foo>bar` denoting that this bar is the one defind in the scope of `foo`.