1 | 'use strict';
|
2 |
|
3 | var estraverse = require('estraverse');
|
4 | var esprima = require('esprima');
|
5 | var EventEmitter = require('events').EventEmitter;
|
6 | var inherits = require('util').inherits;
|
7 | var EsNode = require('./esnode');
|
8 | var forEach = require('array-foreach');
|
9 | var reduce = require('array-reduce');
|
10 |
|
11 | function ContextTraversal (context) {
|
12 | this.context = context;
|
13 | EventEmitter.call(this);
|
14 | }
|
15 | inherits(ContextTraversal, EventEmitter);
|
16 |
|
17 | ContextTraversal.prototype.traverse = function () {
|
18 | var _this = this;
|
19 | forEach(this.context.args, function (arg) {
|
20 | onEachEsNode(arg, _this.context.source.content, function (esNode) {
|
21 | _this.emit('esnode', esNode);
|
22 | });
|
23 | });
|
24 | };
|
25 |
|
26 | function onEachEsNode(arg, jsCode, callback) {
|
27 | var parseResult = parse(jsCode);
|
28 | var tokens = parseResult.tokens;
|
29 | var espathToValue = reduce(arg.events, function (accum, ev) {
|
30 | accum[ev.espath] = ev.value;
|
31 | return accum;
|
32 | }, {});
|
33 | var nodeStack = [];
|
34 | estraverse.traverse(parseResult.expression, {
|
35 | enter: function (currentNode, parentNode) {
|
36 | var esNode = new EsNode(this.path(), currentNode, parentNode, espathToValue, jsCode, tokens);
|
37 | if (1 < nodeStack.length) {
|
38 | esNode.setParent(nodeStack[nodeStack.length - 1]);
|
39 | }
|
40 | nodeStack.push(esNode);
|
41 | callback(esNode);
|
42 | },
|
43 | leave: function (currentNode, parentNode) {
|
44 | nodeStack.pop();
|
45 | }
|
46 | });
|
47 | }
|
48 |
|
49 | function parserOptions() {
|
50 | return {sourceType: 'module', tolerant: true, loc: true, tokens: true, raw: true};
|
51 | }
|
52 |
|
53 | function wrappedInGenerator(jsCode) {
|
54 | return 'function *wrapper() {\n' + jsCode + '\n}';
|
55 | }
|
56 |
|
57 | function parse(jsCode) {
|
58 | var ast;
|
59 | var top;
|
60 | try {
|
61 |
|
62 | top = ast = esprima.parse(jsCode, parserOptions());
|
63 | } catch (e) {
|
64 |
|
65 |
|
66 |
|
67 | ast = esprima.parse(wrappedInGenerator(jsCode), parserOptions());
|
68 | top = ast.body[0].body;
|
69 | }
|
70 | return {
|
71 | tokens: ast.tokens,
|
72 | expression: extractExpressionFrom(top)
|
73 | };
|
74 | }
|
75 |
|
76 | function extractExpressionFrom (tree) {
|
77 | var expressionStatement = tree.body[0];
|
78 | var expression = expressionStatement.expression;
|
79 | return expression;
|
80 | }
|
81 |
|
82 | module.exports = ContextTraversal;
|