This repository has been archived by the owner on Oct 2, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
/
register.js
188 lines (158 loc) · 5.28 KB
/
register.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
var assert = require("assert");
var path = require("path");
var fs = require("fs");
var hasOwn = Object.hasOwnProperty;
var convertSourceMap = require("convert-source-map");
var meteorBabel = require("./index.js");
var util = require("./util.js");
var Module = module.constructor;
require("reify/lib/runtime").enable(Module.prototype);
var config = {
sourceMapRootPath: null,
cacheDirectory: process.env.BABEL_CACHE_DIR,
allowedDirectories: Object.create(null),
excludedFiles: Object.create(null),
babelOptions: null
};
function setBabelOptions(options) {
config.babelOptions = util.deepClone(options);
// Overrides for default options:
config.babelOptions.sourceMaps = true;
return exports;
}
// Set default config.babelOptions.
setBabelOptions(require("./options.js").getDefaults({
nodeMajorVersion: parseInt(process.versions.node)
}));
exports.setBabelOptions = setBabelOptions;
exports.setSourceMapRootPath = function (smrp) {
config.sourceMapRootPath = smrp;
return exports;
};
exports.setCacheDirectory = function (dir) {
config.cacheDirectory = dir;
return exports;
};
exports.allowDirectory = function (dir) {
config.allowedDirectories[dir] = true;
// Sometimes the filename passed to the require.extensions handler is a
// real path, and thus may not appear to be contained by an allowed
// directory, even though it should be.
config.allowedDirectories[fs.realpathSync(dir)] = true;
return exports;
};
exports.excludeFile = function (path) {
config.excludedFiles[fs.realpathSync(path)] = true;
return exports;
};
var defaultJsHandler = require.extensions[".js"];
function enableExtension(ext) {
const defaultHandler = require.extensions[ext] || defaultJsHandler;
require.extensions[ext] = function(module, filename) {
if (shouldNotTransform(filename)) {
defaultHandler(module, filename);
} else {
module._compile(
getBabelResult(filename).code,
filename
);
// As of version 0.10.0, the Reify require.extensions[".js"] handler
// is responsible for running parent setters after the module has
// finished loading for the first time, so we need to call that
// method here because we are not calling the defaultHandler.
module.runSetters();
}
};
}
enableExtension(".js");
enableExtension(".ts");
exports.retrieveSourceMap = function(filename) {
if (shouldNotTransform(filename)) {
return null;
}
const babelCore = require("@babel/core");
if (typeof babelCore.transformFromAst !== "function") {
// The retrieveSourceMap function can be called as a result of
// importing @babel/core for the first time, at a point in time before
// babelCore.transformFromAst has been defined. The absence of that
// function will cause meteorBabel.compile to fail if we try to call
// getBabelResult here. Fortunately, we can just return null instead,
// which means we couldn't retrieve a source map, which is fine.
return null;
}
var result = getBabelResult(filename);
var map = null;
if (result) {
if (result.map) {
map = result.map;
} else {
var converted = convertSourceMap.fromSource(result.code);
map = converted && converted.toJSON();
}
}
return map && {
url: map.file,
map: map
} || null;
};
function shouldNotTransform(filename) {
if (filename.endsWith(".d.ts")) {
// The official TypeScript compiler's transpileModule function fails for
// .d.ts declaration files with the cryptic error "Error: Debug Failure.
// Output generation failed".
return true;
}
if (path.resolve(filename) !==
path.normalize(filename)) {
// If the filename is not absolute, then it's a file in a core Node
// module, and should not be transformed.
return true;
}
// Check if we have explicitly excluded this file.
if (config.excludedFiles[filename] === true) {
return true;
}
var dirs = Object.keys(config.allowedDirectories);
var allowed = dirs.some(function (dir) {
var relPath = path.relative(dir, filename);
if (relPath.slice(0, 2) === "..") {
// Ignore files that are not contained by an allowed directory.
return false;
}
if (relPath.split(path.sep).indexOf("node_modules") >= 0) {
// Ignore files that are contained by a node_modules directory that
// is itself contained by the allowed dir.
return false;
}
return true;
});
return ! allowed;
}
function getBabelResult(filename) {
var source = fs.readFileSync(filename, "utf8");
var babelOptions = {};
for (var key in config.babelOptions) {
if (hasOwn.call(config.babelOptions, key)) {
babelOptions[key] = config.babelOptions[key];
}
}
if (babelOptions.sourceMaps) {
if (config.sourceMapRootPath) {
var relativePath = path.relative(
config.sourceMapRootPath,
filename
);
if (relativePath.slice(0, 2) !== "..") {
// If the given filename is a path contained within
// config.sourceMapRootPath, use the relative path but prepend
// path.sep so that source maps work more reliably.
filename = path.sep + relativePath;
}
}
babelOptions.sourceFileName = filename;
}
babelOptions.filename = filename;
return meteorBabel.compile(source, babelOptions, {
cacheDirectory: config.cacheDirectory
});
}