UNPKG

2.98 kBJavaScriptView Raw
1'use strict';
2
3const path = require('path');
4const Macros = require('./utils/macros');
5const normalizeOptions = require('./utils/normalize-options').normalizeOptions;
6
7function macros(babel) {
8 let t = babel.types;
9
10 function buildIdentifier(value, name) {
11 let replacement = t.booleanLiteral(value);
12
13 // when we only support babel@7 we should change this
14 // to `path.addComment` or `t.addComment`
15 let comment = {
16 type: 'CommentBlock',
17 value: ` ${name} `,
18 leading: false,
19 trailing: true,
20 };
21 replacement.trailingComments = [comment];
22
23 return replacement;
24 }
25
26 return {
27 name: 'babel-feature-flags-and-debug-macros',
28 visitor: {
29 ImportSpecifier(path, state) {
30 let importPath = path.parent.source.value;
31 let flagsForImport = state.opts.flags[importPath];
32
33 if (flagsForImport) {
34 let flagName = path.node.imported.name;
35 let localBindingName = path.node.local.name;
36
37 if (!(flagName in flagsForImport)) {
38 throw new Error(
39 `Imported ${flagName} from ${importPath} which is not a supported flag.`
40 );
41 }
42
43 let flagValue = flagsForImport[flagName];
44 if (flagValue === null) {
45 return;
46 }
47
48 let binding = path.scope.getBinding(localBindingName);
49
50 binding.referencePaths.forEach(p => {
51 p.replaceWith(buildIdentifier(flagValue, flagName));
52 });
53
54 path.remove();
55 path.scope.removeOwnBinding(localBindingName);
56 }
57 },
58
59 ImportDeclaration: {
60 exit(path, state) {
61 let importPath = path.node.source.value;
62 let flagsForImport = state.opts.flags[importPath];
63
64 // remove flag source imports when no specifiers are left
65 if (flagsForImport && path.get('specifiers').length === 0) {
66 path.remove();
67 }
68 },
69 },
70
71 Program: {
72 enter(path, state) {
73 state.opts = normalizeOptions(state.opts);
74 this.macroBuilder = new Macros(babel, state.opts);
75
76 let body = path.get('body');
77
78 body.forEach(item => {
79 if (item.isImportDeclaration()) {
80 let importPath = item.node.source.value;
81
82 let debugToolsImport = state.opts.debugTools.debugToolsImport;
83
84 if (debugToolsImport && debugToolsImport === importPath) {
85 if (!item.node.specifiers.length) {
86 item.remove();
87 } else {
88 this.macroBuilder.collectDebugToolsSpecifiers(item.get('specifiers'));
89 }
90 }
91 }
92 });
93 },
94
95 exit(path) {
96 this.macroBuilder.expand(path);
97 },
98 },
99
100 ExpressionStatement(path) {
101 this.macroBuilder.build(path);
102 },
103 },
104 };
105}
106
107macros.baseDir = function() {
108 return path.dirname(__dirname);
109};
110
111module.exports = macros;