@parcel/transformer-babel 2.0.0-beta.3.1 → 2.0.0-dev.1515
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/BabelTransformer.js +28 -81
- package/lib/babel7.js +56 -52
- package/lib/babelErrorUtils.js +15 -0
- package/lib/config.js +164 -124
- package/lib/constants.js +2 -3
- package/lib/flow.js +26 -7
- package/lib/jsx.js +2 -10
- package/lib/remapAstLocations.js +55 -0
- package/lib/utils.js +21 -38
- package/package.json +13 -17
- package/src/BabelTransformer.js +29 -11
- package/src/babel7.js +64 -12
- package/src/babelErrorUtils.js +30 -0
- package/src/config.js +209 -58
- package/src/constants.js +1 -1
- package/src/flow.js +36 -5
- package/src/jsx.js +2 -1
- package/src/remapAstLocations.js +70 -0
- package/src/utils.js +17 -14
- package/lib/astConverter.js +0 -114
- package/lib/getBabelTargets.js +0 -104
- package/src/astConverter.js +0 -102
- package/src/getBabelTargets.js +0 -97
package/src/config.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
-
import type {Config, PluginOptions} from '@parcel/types';
|
|
4
|
-
import type {PluginLogger} from '@parcel/logger';
|
|
3
|
+
import type {Config, PluginOptions, PluginLogger} from '@parcel/types';
|
|
5
4
|
import typeof * as BabelCore from '@babel/core';
|
|
5
|
+
import type {Diagnostic} from '@parcel/diagnostic';
|
|
6
|
+
import type {BabelConfig} from './types';
|
|
6
7
|
|
|
8
|
+
import json5 from 'json5';
|
|
7
9
|
import path from 'path';
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
+
import {hashObject, relativePath, resolveConfig} from '@parcel/utils';
|
|
11
|
+
import {md, generateJSONCodeHighlights} from '@parcel/diagnostic';
|
|
12
|
+
import {BABEL_CORE_RANGE} from './constants';
|
|
10
13
|
|
|
11
14
|
import isJSX from './jsx';
|
|
12
15
|
import getFlowOptions from './flow';
|
|
13
16
|
import {enginesToBabelTargets} from './utils';
|
|
14
17
|
|
|
15
18
|
const TYPESCRIPT_EXTNAME_RE = /\.tsx?$/;
|
|
16
|
-
const BABEL_TRANSFORMER_DIR = path.dirname(__dirname);
|
|
17
19
|
const JS_EXTNAME_RE = /^\.(js|cjs|mjs)$/;
|
|
18
20
|
const BABEL_CONFIG_FILENAMES = [
|
|
19
21
|
'.babelrc',
|
|
@@ -28,11 +30,18 @@ const BABEL_CONFIG_FILENAMES = [
|
|
|
28
30
|
'babel.config.cjs',
|
|
29
31
|
];
|
|
30
32
|
|
|
33
|
+
type BabelConfigResult = {|
|
|
34
|
+
internal: boolean,
|
|
35
|
+
config: BabelConfig,
|
|
36
|
+
targets?: mixed,
|
|
37
|
+
syntaxPlugins?: mixed,
|
|
38
|
+
|};
|
|
39
|
+
|
|
31
40
|
export async function load(
|
|
32
41
|
config: Config,
|
|
33
42
|
options: PluginOptions,
|
|
34
43
|
logger: PluginLogger,
|
|
35
|
-
): Promise
|
|
44
|
+
): Promise<?BabelConfigResult> {
|
|
36
45
|
// Don't transpile inside node_modules
|
|
37
46
|
if (!config.isSource) {
|
|
38
47
|
return;
|
|
@@ -56,24 +65,26 @@ export async function load(
|
|
|
56
65
|
options.projectRoot,
|
|
57
66
|
))
|
|
58
67
|
) {
|
|
59
|
-
|
|
60
|
-
return;
|
|
68
|
+
return buildDefaultBabelConfig(options, config);
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
const babelCore: BabelCore = await options.packageManager.require(
|
|
64
72
|
'@babel/core',
|
|
65
73
|
config.searchPath,
|
|
66
74
|
{
|
|
67
|
-
range:
|
|
75
|
+
range: BABEL_CORE_RANGE,
|
|
68
76
|
saveDev: true,
|
|
69
77
|
shouldAutoInstall: options.shouldAutoInstall,
|
|
70
78
|
},
|
|
71
79
|
);
|
|
72
80
|
config.addDevDependency({
|
|
73
|
-
|
|
81
|
+
specifier: '@babel/core',
|
|
74
82
|
resolveFrom: config.searchPath,
|
|
83
|
+
range: BABEL_CORE_RANGE,
|
|
75
84
|
});
|
|
76
85
|
|
|
86
|
+
config.invalidateOnEnvChange('BABEL_ENV');
|
|
87
|
+
config.invalidateOnEnvChange('NODE_ENV');
|
|
77
88
|
let babelOptions = {
|
|
78
89
|
filename: config.searchPath,
|
|
79
90
|
cwd: options.projectRoot,
|
|
@@ -96,23 +107,28 @@ export async function load(
|
|
|
96
107
|
// We need to invalidate on startup in case the config is non-static,
|
|
97
108
|
// e.g. uses unknown environment variables, reads from the filesystem, etc.
|
|
98
109
|
logger.warn({
|
|
99
|
-
message: `It looks like you're using a JavaScript Babel config file. This means the config cannot be watched for changes, and Babel transformations cannot be cached. You'll need to restart Parcel for changes to this config to take effect. Try using a ${
|
|
100
|
-
file,
|
|
101
|
-
|
|
102
|
-
) + '.json'} file instead.`,
|
|
110
|
+
message: `It looks like you're using a JavaScript Babel config file. This means the config cannot be watched for changes, and Babel transformations cannot be cached. You'll need to restart Parcel for changes to this config to take effect. Try using a ${
|
|
111
|
+
path.basename(file, path.extname(file)) + '.json'
|
|
112
|
+
} file instead.`,
|
|
103
113
|
});
|
|
104
|
-
config.
|
|
114
|
+
config.invalidateOnStartup();
|
|
105
115
|
|
|
106
116
|
// But also add the config as a dev dependency so we can at least attempt invalidation in watch mode.
|
|
107
117
|
config.addDevDependency({
|
|
108
|
-
|
|
118
|
+
specifier: relativePath(options.projectRoot, file),
|
|
109
119
|
resolveFrom: path.join(options.projectRoot, 'index'),
|
|
110
|
-
// Also invalidate @
|
|
120
|
+
// Also invalidate @babel/core when the config or a dependency updates.
|
|
111
121
|
// This ensures that the caches in @babel/core are also invalidated.
|
|
112
|
-
|
|
122
|
+
additionalInvalidations: [
|
|
123
|
+
{
|
|
124
|
+
specifier: '@babel/core',
|
|
125
|
+
resolveFrom: config.searchPath,
|
|
126
|
+
range: BABEL_CORE_RANGE,
|
|
127
|
+
},
|
|
128
|
+
],
|
|
113
129
|
});
|
|
114
130
|
} else {
|
|
115
|
-
config.
|
|
131
|
+
config.invalidateOnFileChange(file);
|
|
116
132
|
}
|
|
117
133
|
};
|
|
118
134
|
|
|
@@ -121,7 +137,7 @@ export async function load(
|
|
|
121
137
|
message:
|
|
122
138
|
'You are using an old version of @babel/core which does not support the necessary features for Parcel to cache and watch babel config files safely. You may need to restart Parcel for config changes to take effect. Please upgrade to @babel/core 7.12.0 or later to resolve this issue.',
|
|
123
139
|
});
|
|
124
|
-
config.
|
|
140
|
+
config.invalidateOnStartup();
|
|
125
141
|
};
|
|
126
142
|
|
|
127
143
|
// Old versions of @babel/core return null from loadPartialConfig when the file should explicitly not be run through babel (ignore/exclude)
|
|
@@ -167,13 +183,6 @@ export async function load(
|
|
|
167
183
|
syntaxPlugins.push('jsx');
|
|
168
184
|
}
|
|
169
185
|
|
|
170
|
-
config.setResult({
|
|
171
|
-
internal: false,
|
|
172
|
-
config: partialConfig.options,
|
|
173
|
-
targets: enginesToBabelTargets(config.env),
|
|
174
|
-
syntaxPlugins,
|
|
175
|
-
});
|
|
176
|
-
|
|
177
186
|
// If the config has plugins loaded with require(), or inline plugins in the config,
|
|
178
187
|
// we can't cache the result of the compilation because we don't know where they came from.
|
|
179
188
|
if (hasRequire(partialConfig.options)) {
|
|
@@ -182,18 +191,29 @@ export async function load(
|
|
|
182
191
|
'It looks like you are using `require` to configure Babel plugins or presets. This means Babel transformations cannot be cached and will run on each build. Please use strings to configure Babel instead.',
|
|
183
192
|
});
|
|
184
193
|
|
|
185
|
-
config.
|
|
186
|
-
config.
|
|
194
|
+
config.setCacheKey(JSON.stringify(Date.now()));
|
|
195
|
+
config.invalidateOnStartup();
|
|
187
196
|
} else {
|
|
188
|
-
|
|
189
|
-
config
|
|
197
|
+
await warnOnRedundantPlugins(options.inputFS, partialConfig, logger);
|
|
198
|
+
definePluginDependencies(config, partialConfig.options, options);
|
|
199
|
+
config.setCacheKey(hashObject(partialConfig.options));
|
|
190
200
|
}
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
internal: false,
|
|
204
|
+
config: partialConfig.options,
|
|
205
|
+
targets: enginesToBabelTargets(config.env),
|
|
206
|
+
syntaxPlugins,
|
|
207
|
+
};
|
|
191
208
|
} else {
|
|
192
|
-
|
|
209
|
+
return buildDefaultBabelConfig(options, config);
|
|
193
210
|
}
|
|
194
211
|
}
|
|
195
212
|
|
|
196
|
-
async function buildDefaultBabelConfig(
|
|
213
|
+
async function buildDefaultBabelConfig(
|
|
214
|
+
options: PluginOptions,
|
|
215
|
+
config: Config,
|
|
216
|
+
): Promise<?BabelConfigResult> {
|
|
197
217
|
// If this is a .ts or .tsx file, we don't need to enable flow.
|
|
198
218
|
if (TYPESCRIPT_EXTNAME_RE.test(config.searchPath)) {
|
|
199
219
|
return;
|
|
@@ -211,25 +231,12 @@ async function buildDefaultBabelConfig(options: PluginOptions, config: Config) {
|
|
|
211
231
|
syntaxPlugins.push('jsx');
|
|
212
232
|
}
|
|
213
233
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
type: 'preset',
|
|
217
|
-
dirname: BABEL_TRANSFORMER_DIR,
|
|
218
|
-
}),
|
|
219
|
-
);
|
|
220
|
-
babelOptions.plugins = (babelOptions.plugins || []).map(plugin =>
|
|
221
|
-
internalBabelCore.createConfigItem(plugin, {
|
|
222
|
-
type: 'plugin',
|
|
223
|
-
dirname: BABEL_TRANSFORMER_DIR,
|
|
224
|
-
}),
|
|
225
|
-
);
|
|
226
|
-
|
|
227
|
-
config.setResult({
|
|
234
|
+
definePluginDependencies(config, babelOptions, options);
|
|
235
|
+
return {
|
|
228
236
|
internal: true,
|
|
229
237
|
config: babelOptions,
|
|
230
238
|
syntaxPlugins,
|
|
231
|
-
}
|
|
232
|
-
definePluginDependencies(config, options);
|
|
239
|
+
};
|
|
233
240
|
}
|
|
234
241
|
|
|
235
242
|
function hasRequire(options) {
|
|
@@ -237,26 +244,170 @@ function hasRequire(options) {
|
|
|
237
244
|
return configItems.some(item => !item.file);
|
|
238
245
|
}
|
|
239
246
|
|
|
240
|
-
function definePluginDependencies(config, options) {
|
|
241
|
-
let babelConfig = config.result.config;
|
|
247
|
+
function definePluginDependencies(config, babelConfig: ?BabelConfig, options) {
|
|
242
248
|
if (babelConfig == null) {
|
|
243
249
|
return;
|
|
244
250
|
}
|
|
245
251
|
|
|
246
|
-
let configItems = [
|
|
252
|
+
let configItems = [
|
|
253
|
+
...(babelConfig.presets || []),
|
|
254
|
+
...(babelConfig.plugins || []),
|
|
255
|
+
];
|
|
247
256
|
for (let configItem of configItems) {
|
|
248
257
|
// FIXME: this uses a relative path from the project root rather than resolving
|
|
249
258
|
// from the config location because configItem.file.request can be a shorthand
|
|
250
259
|
// rather than a full package name.
|
|
251
260
|
config.addDevDependency({
|
|
252
|
-
|
|
253
|
-
options.projectRoot,
|
|
254
|
-
configItem.file.resolved,
|
|
255
|
-
),
|
|
261
|
+
specifier: relativePath(options.projectRoot, configItem.file.resolved),
|
|
256
262
|
resolveFrom: path.join(options.projectRoot, 'index'),
|
|
257
|
-
// Also invalidate @
|
|
263
|
+
// Also invalidate @babel/core when the plugin or a dependency updates.
|
|
258
264
|
// This ensures that the caches in @babel/core are also invalidated.
|
|
259
|
-
|
|
265
|
+
additionalInvalidations: [
|
|
266
|
+
{
|
|
267
|
+
specifier: '@babel/core',
|
|
268
|
+
resolveFrom: config.searchPath,
|
|
269
|
+
range: BABEL_CORE_RANGE,
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const redundantPresets = new Set([
|
|
277
|
+
'@babel/preset-env',
|
|
278
|
+
'@babel/preset-react',
|
|
279
|
+
'@babel/preset-typescript',
|
|
280
|
+
'@parcel/babel-preset-env',
|
|
281
|
+
]);
|
|
282
|
+
|
|
283
|
+
async function warnOnRedundantPlugins(fs, babelConfig, logger) {
|
|
284
|
+
if (babelConfig == null) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
let configPath = babelConfig.config ?? babelConfig.babelrc;
|
|
289
|
+
if (!configPath) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
let presets = babelConfig.options.presets || [];
|
|
294
|
+
let plugins = babelConfig.options.plugins || [];
|
|
295
|
+
let foundRedundantPresets = new Set();
|
|
296
|
+
|
|
297
|
+
let filteredPresets = presets.filter(preset => {
|
|
298
|
+
if (redundantPresets.has(preset.file.request)) {
|
|
299
|
+
foundRedundantPresets.add(preset.file.request);
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return true;
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
let filePath = path.relative(process.cwd(), configPath);
|
|
307
|
+
let diagnostics: Array<Diagnostic> = [];
|
|
308
|
+
|
|
309
|
+
if (
|
|
310
|
+
filteredPresets.length === 0 &&
|
|
311
|
+
foundRedundantPresets.size > 0 &&
|
|
312
|
+
plugins.length === 0
|
|
313
|
+
) {
|
|
314
|
+
diagnostics.push({
|
|
315
|
+
message: md`Parcel includes transpilation by default. Babel config __${filePath}__ contains only redundant presets. Deleting it may significantly improve build performance.`,
|
|
316
|
+
codeFrames: [
|
|
317
|
+
{
|
|
318
|
+
filePath: configPath,
|
|
319
|
+
codeHighlights: await getCodeHighlights(
|
|
320
|
+
fs,
|
|
321
|
+
configPath,
|
|
322
|
+
foundRedundantPresets,
|
|
323
|
+
),
|
|
324
|
+
},
|
|
325
|
+
],
|
|
326
|
+
hints: [md`Delete __${filePath}__`],
|
|
327
|
+
documentationURL:
|
|
328
|
+
'https://parceljs.org/languages/javascript/#default-presets',
|
|
329
|
+
});
|
|
330
|
+
} else if (foundRedundantPresets.size > 0) {
|
|
331
|
+
diagnostics.push({
|
|
332
|
+
message: md`Parcel includes transpilation by default. Babel config __${filePath}__ includes the following redundant presets: ${[
|
|
333
|
+
...foundRedundantPresets,
|
|
334
|
+
].map(p =>
|
|
335
|
+
md.underline(p),
|
|
336
|
+
)}. Removing these may improve build performance.`,
|
|
337
|
+
codeFrames: [
|
|
338
|
+
{
|
|
339
|
+
filePath: configPath,
|
|
340
|
+
codeHighlights: await getCodeHighlights(
|
|
341
|
+
fs,
|
|
342
|
+
configPath,
|
|
343
|
+
foundRedundantPresets,
|
|
344
|
+
),
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
hints: [md`Remove the above presets from __${filePath}__`],
|
|
348
|
+
documentationURL:
|
|
349
|
+
'https://parceljs.org/languages/javascript/#default-presets',
|
|
260
350
|
});
|
|
261
351
|
}
|
|
352
|
+
|
|
353
|
+
if (foundRedundantPresets.has('@babel/preset-env')) {
|
|
354
|
+
diagnostics.push({
|
|
355
|
+
message:
|
|
356
|
+
"@babel/preset-env does not support Parcel's targets, which will likely result in unnecessary transpilation and larger bundle sizes.",
|
|
357
|
+
codeFrames: [
|
|
358
|
+
{
|
|
359
|
+
filePath: babelConfig.config ?? babelConfig.babelrc,
|
|
360
|
+
codeHighlights: await getCodeHighlights(
|
|
361
|
+
fs,
|
|
362
|
+
babelConfig.config ?? babelConfig.babelrc,
|
|
363
|
+
new Set(['@babel/preset-env']),
|
|
364
|
+
),
|
|
365
|
+
},
|
|
366
|
+
],
|
|
367
|
+
hints: [
|
|
368
|
+
`Either remove __@babel/preset-env__ to use Parcel's builtin transpilation, or replace with __@parcel/babel-preset-env__`,
|
|
369
|
+
],
|
|
370
|
+
documentationURL:
|
|
371
|
+
'https://parceljs.org/languages/javascript/#custom-plugins',
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (diagnostics.length > 0) {
|
|
376
|
+
logger.warn(diagnostics);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async function getCodeHighlights(fs, filePath, redundantPresets) {
|
|
381
|
+
let ext = path.extname(filePath);
|
|
382
|
+
if (ext !== '.js' && ext !== '.cjs' && ext !== '.mjs') {
|
|
383
|
+
let contents = await fs.readFile(filePath, 'utf8');
|
|
384
|
+
let json = json5.parse(contents);
|
|
385
|
+
|
|
386
|
+
let presets = json.presets || [];
|
|
387
|
+
let pointers = [];
|
|
388
|
+
for (let i = 0; i < presets.length; i++) {
|
|
389
|
+
if (Array.isArray(presets[i]) && redundantPresets.has(presets[i][0])) {
|
|
390
|
+
pointers.push({type: 'value', key: `/presets/${i}/0`});
|
|
391
|
+
} else if (redundantPresets.has(presets[i])) {
|
|
392
|
+
pointers.push({type: 'value', key: `/presets/${i}`});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (pointers.length > 0) {
|
|
397
|
+
return generateJSONCodeHighlights(contents, pointers);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return [
|
|
402
|
+
{
|
|
403
|
+
start: {
|
|
404
|
+
line: 1,
|
|
405
|
+
column: 1,
|
|
406
|
+
},
|
|
407
|
+
end: {
|
|
408
|
+
line: 1,
|
|
409
|
+
column: 1,
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
];
|
|
262
413
|
}
|
package/src/constants.js
CHANGED
package/src/flow.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
-
import type {Config, PluginOptions} from '@parcel/types';
|
|
3
|
+
import type {Config, PluginOptions, PackageJSON} from '@parcel/types';
|
|
4
4
|
import type {BabelConfig} from './types';
|
|
5
|
+
import typeof * as BabelCore from '@babel/core';
|
|
6
|
+
|
|
7
|
+
import {BABEL_CORE_RANGE} from './constants';
|
|
8
|
+
import path from 'path';
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
11
|
* Generates a babel config for stripping away Flow types.
|
|
@@ -15,9 +19,10 @@ export default async function getFlowOptions(
|
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
// Only add flow plugin if `flow-bin` is listed as a dependency in the root package.json
|
|
18
|
-
let conf = await config.getConfigFrom(
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
let conf = await config.getConfigFrom<PackageJSON>(
|
|
23
|
+
options.projectRoot + '/index',
|
|
24
|
+
['package.json'],
|
|
25
|
+
);
|
|
21
26
|
let pkg = conf?.contents;
|
|
22
27
|
if (
|
|
23
28
|
!pkg ||
|
|
@@ -27,9 +32,35 @@ export default async function getFlowOptions(
|
|
|
27
32
|
return null;
|
|
28
33
|
}
|
|
29
34
|
|
|
35
|
+
const babelCore: BabelCore = await options.packageManager.require(
|
|
36
|
+
'@babel/core',
|
|
37
|
+
config.searchPath,
|
|
38
|
+
{
|
|
39
|
+
range: BABEL_CORE_RANGE,
|
|
40
|
+
saveDev: true,
|
|
41
|
+
shouldAutoInstall: options.shouldAutoInstall,
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
await options.packageManager.require(
|
|
46
|
+
'@babel/plugin-transform-flow-strip-types',
|
|
47
|
+
config.searchPath,
|
|
48
|
+
{
|
|
49
|
+
range: '^7.0.0',
|
|
50
|
+
saveDev: true,
|
|
51
|
+
shouldAutoInstall: options.shouldAutoInstall,
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
|
|
30
55
|
return {
|
|
31
56
|
plugins: [
|
|
32
|
-
|
|
57
|
+
babelCore.createConfigItem(
|
|
58
|
+
['@babel/plugin-transform-flow-strip-types', {requireDirective: true}],
|
|
59
|
+
{
|
|
60
|
+
type: 'plugin',
|
|
61
|
+
dirname: path.dirname(config.searchPath),
|
|
62
|
+
},
|
|
63
|
+
),
|
|
33
64
|
],
|
|
34
65
|
};
|
|
35
66
|
}
|
package/src/jsx.js
CHANGED
|
@@ -33,7 +33,8 @@ export default async function isJSX(
|
|
|
33
33
|
libName =>
|
|
34
34
|
pkg &&
|
|
35
35
|
((pkg.dependencies && pkg.dependencies[libName]) ||
|
|
36
|
-
(pkg.devDependencies && pkg.devDependencies[libName])
|
|
36
|
+
(pkg.devDependencies && pkg.devDependencies[libName]) ||
|
|
37
|
+
(pkg.peerDependencies && pkg.peerDependencies[libName])),
|
|
37
38
|
);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// @flow strict-local
|
|
2
|
+
|
|
3
|
+
import type {File as BabelNodeFile} from '@babel/types';
|
|
4
|
+
import type SourceMap from '@parcel/source-map';
|
|
5
|
+
import type {Node} from '@babel/types';
|
|
6
|
+
import typeof * as BabelTypes from '@babel/types';
|
|
7
|
+
|
|
8
|
+
export function remapAstLocations(
|
|
9
|
+
t: BabelTypes,
|
|
10
|
+
ast: BabelNodeFile,
|
|
11
|
+
map: SourceMap,
|
|
12
|
+
) {
|
|
13
|
+
// remap ast to original mappings
|
|
14
|
+
// This improves sourcemap accuracy and fixes sourcemaps when scope-hoisting
|
|
15
|
+
traverseAll(t, ast.program, node => {
|
|
16
|
+
if (node.loc) {
|
|
17
|
+
if (node.loc?.start) {
|
|
18
|
+
let mapping = map.findClosestMapping(
|
|
19
|
+
node.loc.start.line,
|
|
20
|
+
node.loc.start.column,
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
if (mapping?.original) {
|
|
24
|
+
// $FlowFixMe
|
|
25
|
+
node.loc.start.line = mapping.original.line;
|
|
26
|
+
// $FlowFixMe
|
|
27
|
+
node.loc.start.column = mapping.original.column;
|
|
28
|
+
|
|
29
|
+
// $FlowFixMe
|
|
30
|
+
let length = node.loc.end.column - node.loc.start.column;
|
|
31
|
+
|
|
32
|
+
// $FlowFixMe
|
|
33
|
+
node.loc.end.line = mapping.original.line;
|
|
34
|
+
// $FlowFixMe
|
|
35
|
+
node.loc.end.column = mapping.original.column + length;
|
|
36
|
+
|
|
37
|
+
// $FlowFixMe
|
|
38
|
+
node.loc.filename = mapping.source;
|
|
39
|
+
} else {
|
|
40
|
+
// Maintain null mappings?
|
|
41
|
+
node.loc = null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function traverseAll(
|
|
49
|
+
t: BabelTypes,
|
|
50
|
+
node: Node,
|
|
51
|
+
visitor: (node: Node) => void,
|
|
52
|
+
): void {
|
|
53
|
+
if (!node) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
visitor(node);
|
|
58
|
+
|
|
59
|
+
for (let key of t.VISITOR_KEYS[node.type] || []) {
|
|
60
|
+
// $FlowFixMe
|
|
61
|
+
let subNode: Node | Array<Node> = node[key];
|
|
62
|
+
if (Array.isArray(subNode)) {
|
|
63
|
+
for (let i = 0; i < subNode.length; i++) {
|
|
64
|
+
traverseAll(t, subNode[i], visitor);
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
traverseAll(t, subNode, visitor);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/utils.js
CHANGED
|
@@ -5,7 +5,22 @@ import type {Targets as BabelTargets} from '@babel/preset-env';
|
|
|
5
5
|
|
|
6
6
|
import invariant from 'assert';
|
|
7
7
|
import semver from 'semver';
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
// Copied from @babel/helper-compilation-targets/lib/options.js
|
|
10
|
+
const TargetNames = {
|
|
11
|
+
node: 'node',
|
|
12
|
+
chrome: 'chrome',
|
|
13
|
+
opera: 'opera',
|
|
14
|
+
edge: 'edge',
|
|
15
|
+
firefox: 'firefox',
|
|
16
|
+
safari: 'safari',
|
|
17
|
+
ie: 'ie',
|
|
18
|
+
ios: 'ios',
|
|
19
|
+
android: 'android',
|
|
20
|
+
electron: 'electron',
|
|
21
|
+
samsung: 'samsung',
|
|
22
|
+
rhino: 'rhino',
|
|
23
|
+
};
|
|
9
24
|
|
|
10
25
|
// List of browsers to exclude when the esmodule target is specified.
|
|
11
26
|
// Based on https://caniuse.com/#feat=es6-module
|
|
@@ -47,7 +62,7 @@ export function enginesToBabelTargets(env: Environment): BabelTargets {
|
|
|
47
62
|
} else {
|
|
48
63
|
invariant(typeof engineValue === 'string');
|
|
49
64
|
if (!TargetNames.hasOwnProperty(engineName)) continue;
|
|
50
|
-
let minVersion =
|
|
65
|
+
let minVersion = semver.minVersion(engineValue)?.toString();
|
|
51
66
|
targets[engineName] = minVersion ?? engineValue;
|
|
52
67
|
}
|
|
53
68
|
}
|
|
@@ -69,15 +84,3 @@ export function enginesToBabelTargets(env: Environment): BabelTargets {
|
|
|
69
84
|
|
|
70
85
|
return targets;
|
|
71
86
|
}
|
|
72
|
-
|
|
73
|
-
// TODO: Replace with `minVersion` (https://github.com/npm/node-semver#ranges-1)
|
|
74
|
-
// once semver has been upgraded across Parcel.
|
|
75
|
-
export function getMinSemver(version: string): ?string {
|
|
76
|
-
try {
|
|
77
|
-
let range = new semver.Range(version);
|
|
78
|
-
let sorted = range.set.sort((a, b) => a[0].semver.compare(b[0].semver));
|
|
79
|
-
return sorted[0][0].semver.version;
|
|
80
|
-
} catch (err) {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
}
|
package/lib/astConverter.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.babel7toBabel6 = babel7toBabel6;
|
|
7
|
-
exports.babel6toBabel7 = babel6toBabel7;
|
|
8
|
-
|
|
9
|
-
function _traverse() {
|
|
10
|
-
const data = _interopRequireDefault(require("@babel/traverse"));
|
|
11
|
-
|
|
12
|
-
_traverse = function () {
|
|
13
|
-
return data;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
return data;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
20
|
-
|
|
21
|
-
// Convert between babel 7 and babel 6 AST
|
|
22
|
-
// More info on the AST Changes: https://babeljs.io/docs/en/v7-migration-api#ast-changes
|
|
23
|
-
function babel7toBabel6(ast) {
|
|
24
|
-
const visitor = {
|
|
25
|
-
ArrowFunctionExpression: node => {
|
|
26
|
-
node.expression = node.body.type !== 'BlockStatement';
|
|
27
|
-
},
|
|
28
|
-
ExistsTypeAnnotation: node => {
|
|
29
|
-
node.type = 'ExistentialTypeParam';
|
|
30
|
-
},
|
|
31
|
-
NumberLiteralTypeAnnotation: node => {
|
|
32
|
-
node.type = 'NumericLiteralTypeAnnotation';
|
|
33
|
-
},
|
|
34
|
-
ObjectTypeIndexer: node => {
|
|
35
|
-
node.end++;
|
|
36
|
-
node.loc.end.column++;
|
|
37
|
-
},
|
|
38
|
-
ForOfStatement: node => {
|
|
39
|
-
node.type = 'ForAwaitStatement';
|
|
40
|
-
delete node.await;
|
|
41
|
-
},
|
|
42
|
-
SpreadElement: (node, path) => {
|
|
43
|
-
if (path.parentPath.isObjectExpression() || path.parentPath.isArrayExpression()) {
|
|
44
|
-
node.type = 'SpreadProperty';
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
RestElement: (node, path) => {
|
|
48
|
-
if (path.parentPath.isObjectPattern() || path.parentPath.isArrayPattern()) {
|
|
49
|
-
node.type = 'RestProperty';
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
(0, _traverse().default)(ast, {
|
|
54
|
-
enter(path) {
|
|
55
|
-
if (path.node.variance && path.node.variance.type === 'Variance') {
|
|
56
|
-
path.node.variance = path.node.variance.kind;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let visitorFunc = visitor[path.node.type];
|
|
60
|
-
|
|
61
|
-
if (visitorFunc) {
|
|
62
|
-
visitorFunc(path.node, path);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
});
|
|
67
|
-
return ast;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function babel6toBabel7(ast) {
|
|
71
|
-
const visitor = {
|
|
72
|
-
ArrowFunctionExpression: node => {
|
|
73
|
-
delete node.expression;
|
|
74
|
-
},
|
|
75
|
-
ExistentialTypeParam: node => {
|
|
76
|
-
node.type = 'ExistsTypeAnnotation';
|
|
77
|
-
},
|
|
78
|
-
NumericLiteralTypeAnnotation: node => {
|
|
79
|
-
node.type = 'NumberLiteralTypeAnnotation';
|
|
80
|
-
},
|
|
81
|
-
ObjectTypeIndexer: node => {
|
|
82
|
-
node.end--;
|
|
83
|
-
node.loc.end.column--;
|
|
84
|
-
},
|
|
85
|
-
ForAwaitStatement: node => {
|
|
86
|
-
node.type = 'ForOfStatement';
|
|
87
|
-
node.await = true;
|
|
88
|
-
},
|
|
89
|
-
SpreadProperty: node => {
|
|
90
|
-
node.type = 'SpreadElement';
|
|
91
|
-
},
|
|
92
|
-
RestProperty: node => {
|
|
93
|
-
node.type = 'RestElement';
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
(0, _traverse().default)(ast, {
|
|
97
|
-
enter(path) {
|
|
98
|
-
if (path.node.variance && typeof path.node.variance === 'string') {
|
|
99
|
-
path.node.variance = {
|
|
100
|
-
type: 'VarianceNode',
|
|
101
|
-
kind: path.node.variance
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
let visitorFunc = visitor[path.node.type];
|
|
106
|
-
|
|
107
|
-
if (visitorFunc) {
|
|
108
|
-
visitorFunc(path.node);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
});
|
|
113
|
-
return ast;
|
|
114
|
-
}
|