forked from babel/babel
/
node.js
168 lines (141 loc) · 3.91 KB
/
node.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import cloneDeep from "clone-deep";
import sourceMapSupport from "source-map-support";
import * as registerCache from "./cache";
import * as babel from "@babel/core";
import { OptionManager, DEFAULT_EXTENSIONS } from "@babel/core";
import { addHook } from "pirates";
import fs from "fs";
import path from "path";
import Module from "module";
const maps = {};
let transformOpts = {};
let piratesRevert = null;
function installSourceMapSupport() {
sourceMapSupport.install({
handleUncaughtExceptions: false,
environment: "node",
retrieveSourceMap(source) {
const map = maps && maps[source];
if (map) {
return {
url: null,
map: map,
};
} else {
return null;
}
},
});
}
let cache;
function mtime(filename) {
return +fs.statSync(filename).mtime;
}
function compile(code, filename) {
// merge in base options and resolve all the plugins and presets relative to this file
const opts = new OptionManager().init(
// sourceRoot can be overwritten
{
sourceRoot: path.dirname(filename) + path.sep,
...cloneDeep(transformOpts),
filename,
},
);
// Bail out ASAP if the file has been ignored.
if (opts === null) return code;
let cacheKey = `${JSON.stringify(opts)}:${babel.version}`;
const env = babel.getEnv(false);
if (env) cacheKey += `:${env}`;
let cached = cache && cache[cacheKey];
if (!cached || cached.mtime !== mtime(filename)) {
cached = babel.transform(code, {
...opts,
sourceMaps: opts.sourceMaps === undefined ? "both" : opts.sourceMaps,
ast: false,
});
if (cache) {
cache[cacheKey] = cached;
cached.mtime = mtime(filename);
registerCache.setDirty();
}
}
if (cached.map) {
if (Object.keys(maps).length === 0) {
installSourceMapSupport();
}
maps[filename] = cached.map;
}
return cached.code;
}
let compiling = false;
const internalModuleCache = Module._cache;
function compileHook(code, filename) {
if (compiling) return code;
const globalModuleCache = Module._cache;
try {
compiling = true;
Module._cache = internalModuleCache;
return compile(code, filename);
} finally {
compiling = false;
Module._cache = globalModuleCache;
}
}
function hookExtensions(exts) {
if (piratesRevert) piratesRevert();
piratesRevert = addHook(compileHook, { exts, ignoreNodeModules: false });
}
export function revert() {
if (piratesRevert) piratesRevert();
}
function escapeRegExp(string) {
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
}
export default function register(opts?: Object = {}) {
// Clone to avoid mutating the arguments object with the 'delete's below.
opts = {
...opts,
};
hookExtensions(opts.extensions || DEFAULT_EXTENSIONS);
if (opts.cache === false && cache) {
registerCache.clear();
cache = null;
} else if (opts.cache !== false && !cache) {
registerCache.load();
cache = registerCache.get();
}
delete opts.extensions;
delete opts.cache;
transformOpts = {
...opts,
caller: {
name: "@babel/register",
...(opts.caller || {}),
},
};
let { cwd = "." } = transformOpts;
// Ensure that the working directory is resolved up front so that
// things don't break if it changes later.
cwd = transformOpts.cwd = path.resolve(cwd);
if (transformOpts.ignore === undefined && transformOpts.only === undefined) {
transformOpts.only = [
// Only compile things inside the current working directory.
// $FlowIgnore
new RegExp("^" + escapeRegExp(cwd), "i"),
];
transformOpts.ignore = [
// Ignore any node_modules inside the current working directory.
new RegExp(
"^" +
// $FlowIgnore
escapeRegExp(cwd) +
"(?:" +
path.sep +
".*)?" +
// $FlowIgnore
escapeRegExp(path.sep + "node_modules" + path.sep),
"i",
),
];
}
}