-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathplugin.js
More file actions
133 lines (118 loc) · 5.95 KB
/
plugin.js
File metadata and controls
133 lines (118 loc) · 5.95 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
'use strict';
/*
* 'fast-async' plugin for Babel v6.x. It uses nodent to transform the entire program before passing it off
* to the next transformer.
*/
module.exports = function (babel) {
var logger = console.log.bind(console);
var NodentCompiler = require('nodent-compiler');
var compiler = null;
var compilerOpts = {};
var requiresTranspilation = false;
var defaultEnv = {
log:logger
};
function getRuntime(symbol, fn, opts, compiler) {
var runtime = symbol + '=' + fn.toString().replace(/[\s]+/g, ' ') + ';\n';
opts.parser.ranges = false;
opts.parser.locations = false;
// Use babel rather than nodent (acorn) as babel's AST is not ESTree compliant
var ast = babel.transform(runtime, { ast: true }).ast.program.body[0];
// Remove location information from the runtime as Babel >=6.5.0 does a search by
// location and barfs if multiple nodes apparently occupy the same source locations
ast = JSON.parse(JSON.stringify(ast, function replacer(key, value) {
return (key === 'start' || key === 'end' ? undefined : value);
}));
return ast;
}
return {
// Lifted from https://github.com/babel/babel/blob/master/packages/babel-plugin-syntax-async-functions/src/index.js#L3,
// which is not nice, but avoids installation complexity with plugins (which I must try to work out sometime)
manipulateOptions: function manipulateOptions(opts, parserOpts) {
parserOpts.plugins.push('asyncFunctions');
},
visitor: {
Program: {
enter: function(path, state){
requiresTranspilation = false;
},
exit: function (path, state) {
// Check if there was an async or await keyword before bothering to process the AST
if (!requiresTranspilation)
return ;
state.opts = state.opts || {} ;
var envOpts = state.opts.env || {};
Object.keys(defaultEnv).forEach(function(k){
if (!(k in envOpts))
envOpts[k] = defaultEnv[k] ;
}) ;
compiler = new NodentCompiler(envOpts);
/* Compiler options */
compilerOpts = {} ;
Object.keys(NodentCompiler.initialCodeGenOpts).forEach(function(k){
compilerOpts[k] = NodentCompiler.initialCodeGenOpts[k] ;
}) ;
compilerOpts.promises = true ;
compilerOpts.babelTree = true;
compilerOpts.parser = { noNodentExtensions: true} ;
var defCompilerOpts = state.opts.compiler || {} ;
if (state.opts.spec) {
defCompilerOpts.promises = true ;
defCompilerOpts.wrapAwait = true ;
defCompilerOpts.noRuntime = true ;
}
if (defCompilerOpts && typeof defCompilerOpts==="object") {
Object.keys(defCompilerOpts).forEach(function(k){
compilerOpts[k] = defCompilerOpts[k] ;
}) ;
}
var pr = { origCode: state.file.code, filename: '', ast: path.node };
compiler.asynchronize(pr, undefined, compilerOpts, compiler.log);
var runtime ;
if (!compilerOpts.noRuntime) {
if (compilerOpts.generators) {
runtime = getRuntime('Function.prototype.$asyncspawn', require('nodent-runtime').$asyncspawn, compilerOpts, compiler);
} else {
runtime = getRuntime('Function.prototype.$asyncbind', require('nodent-runtime').$asyncbind, compilerOpts, compiler);
}
if (state.opts.useRuntimeModule) {
state.addImport(state.opts.useRuntimeModule === true ? 'nodent-runtime' : state.opts.useRuntimeModule, 'default');
}
else if (!state.opts.runtimePattern) {
path.unshiftContainer('body', runtime);
}
else if (state.opts.runtimePattern === 'directive') {
var hasRuntime = false;
for (var index = 0; index < path.node.directives.length; index++) {
if (path.node.directives[index].value.value === 'use runtime-nodent') {
if (!hasRuntime) {
path.unshiftContainer('body', runtime);
hasRuntime = true;
}
path.node.directives.splice(index, 1);
}
}
}
else {
var pattern = new RegExp(state.opts.runtimePattern);
var parserOpts = state.file.parserOpts;
// The key is called sourceFileName since babel-core 6.16:
var sourceFileName = parserOpts.filename || parserOpts.sourceFileName;
if (sourceFileName.match(pattern)) {
path.unshiftContainer('body', runtime);
}
}
}
}
},
AwaitExpression: function Function(path, state) {
requiresTranspilation = true;
},
Function: function Function(path, state) {
if (path.node.async) {
requiresTranspilation = true;
}
}
}
};
};