-
Notifications
You must be signed in to change notification settings - Fork 42
/
continuation.js
114 lines (98 loc) · 2.78 KB
/
continuation.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
var util = require('util');
var traverse = require('./lib/traverse');
var helpers = require('./lib/helpers');
var sourceMap;
exports.compile = function (code, options) {
if (!options) {
options = {
sourceMap: false
};
}
var indent = ' ';
if (options.indent) {
indent = options.indent;
}
if (!options.force && options.explicit && code.indexOf('use continuation') === -1) {
//Mark literal not found in code
return code;
}
var aliases = helpers.aliases;
if (options.aliases) {
aliases = util._extend(aliases, options.aliases);
}
//Reset helper
helpers.reset();
//Parse code
var parser = require('./lib/parser');
var ast = parser.parse(code);
if (options.explicit) {
//Traverse ast and find explicit compilation mark
if (!findExplicitMark(ast)) {
return code;
}
}
var meta = require('./package.json');
var mark = '/* Generated by Continuation.js v' + meta.version + ' */';
//Tranformation not needed
if (!options.force && !transformNeeded(ast, aliases)) {
return code + '\n' + mark;
}
traverse(ast, function (node) {
return node.normalize ? node.normalize(aliases) : node;
});
//console.error(util.inspect(ast, false, null, true)); //debug
ast.transform(undefined, aliases);
//console.error(util.inspect(ast, false, null, true)); //debug
//Generate code
var escodegen = require('escodegen');
//ast = escodegen.attachComments(ast, ast.comments, ast.tokens); //debug
var genOptions = {
format: {
indent: {
style: indent,
base: 0
}
},
comment: true
};
code = escodegen.generate(ast, genOptions);
//Generate source map
if (options.sourceMap) {
genOptions.sourceMap = 'continuation.js';
sourceMap = JSON.parse(escodegen.generate(ast, genOptions));
}
return code + '\n' + mark;
};
exports.getSourceMap = function (file, sources) {
sourceMap.file = file;
sourceMap.sources = sources;
return JSON.stringify(sourceMap);
};
var findExplicitMark = function (ast) {
var found = false;
traverse(ast, function (node) {
if (node.type === 'ExpressionStatement') {
if (node.expression.type === 'Literal' && node.expression.value === 'use continuation') {
found = true;
}
}
return node;
});
return found;
};
var transformNeeded = function (ast, aliases) {
var needed = false;
traverse(ast, function (node) {
if (node.type === 'CallExpression') {
node.arguments.forEach(function (argument) {
if (argument.type === 'CallExpression' && argument.callee.type === 'Identifier') {
if (argument.callee.name === aliases.contName || argument.callee.name === aliases.obtainName) {
needed = true;
}
}
});
}
return node;
});
return needed;
};