UNPKG

8.99 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _assert = _interopRequireDefault(require("assert"));
9
10var t = _interopRequireWildcard(require("@babel/types"));
11
12var _importBuilder = _interopRequireDefault(require("./import-builder"));
13
14var _isModule = _interopRequireDefault(require("./is-module"));
15
16function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
17
18function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
20function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
22class ImportInjector {
23 constructor(path, importedSource, opts) {
24 this._defaultOpts = {
25 importedSource: null,
26 importedType: "commonjs",
27 importedInterop: "babel",
28 importingInterop: "babel",
29 ensureLiveReference: false,
30 ensureNoContext: false
31 };
32 const programPath = path.find(p => p.isProgram());
33 this._programPath = programPath;
34 this._programScope = programPath.scope;
35 this._hub = programPath.hub;
36 this._defaultOpts = this._applyDefaults(importedSource, opts, true);
37 }
38
39 addDefault(importedSourceIn, opts) {
40 return this.addNamed("default", importedSourceIn, opts);
41 }
42
43 addNamed(importName, importedSourceIn, opts) {
44 (0, _assert.default)(typeof importName === "string");
45 return this._generateImport(this._applyDefaults(importedSourceIn, opts), importName);
46 }
47
48 addNamespace(importedSourceIn, opts) {
49 return this._generateImport(this._applyDefaults(importedSourceIn, opts), null);
50 }
51
52 addSideEffect(importedSourceIn, opts) {
53 return this._generateImport(this._applyDefaults(importedSourceIn, opts), false);
54 }
55
56 _applyDefaults(importedSource, opts, isInit = false) {
57 const optsList = [];
58
59 if (typeof importedSource === "string") {
60 optsList.push({
61 importedSource
62 });
63 optsList.push(opts);
64 } else {
65 (0, _assert.default)(!opts, "Unexpected secondary arguments.");
66 optsList.push(importedSource);
67 }
68
69 const newOpts = Object.assign({}, this._defaultOpts);
70
71 for (const opts of optsList) {
72 if (!opts) continue;
73 Object.keys(newOpts).forEach(key => {
74 if (opts[key] !== undefined) newOpts[key] = opts[key];
75 });
76
77 if (!isInit) {
78 if (opts.nameHint !== undefined) newOpts.nameHint = opts.nameHint;
79 if (opts.blockHoist !== undefined) newOpts.blockHoist = opts.blockHoist;
80 }
81 }
82
83 return newOpts;
84 }
85
86 _generateImport(opts, importName) {
87 const isDefault = importName === "default";
88 const isNamed = !!importName && !isDefault;
89 const isNamespace = importName === null;
90 const {
91 importedSource,
92 importedType,
93 importedInterop,
94 importingInterop,
95 ensureLiveReference,
96 ensureNoContext,
97 nameHint,
98 blockHoist
99 } = opts;
100 let name = nameHint || importName;
101 const isMod = (0, _isModule.default)(this._programPath);
102 const isModuleForNode = isMod && importingInterop === "node";
103 const isModuleForBabel = isMod && importingInterop === "babel";
104 const builder = new _importBuilder.default(importedSource, this._programScope, this._hub);
105
106 if (importedType === "es6") {
107 if (!isModuleForNode && !isModuleForBabel) {
108 throw new Error("Cannot import an ES6 module from CommonJS");
109 }
110
111 builder.import();
112
113 if (isNamespace) {
114 builder.namespace(nameHint || importedSource);
115 } else if (isDefault || isNamed) {
116 builder.named(name, importName);
117 }
118 } else if (importedType !== "commonjs") {
119 throw new Error(`Unexpected interopType "${importedType}"`);
120 } else if (importedInterop === "babel") {
121 if (isModuleForNode) {
122 name = name !== "default" ? name : importedSource;
123 const es6Default = `${importedSource}$es6Default`;
124 builder.import();
125
126 if (isNamespace) {
127 builder.default(es6Default).var(name || importedSource).wildcardInterop();
128 } else if (isDefault) {
129 if (ensureLiveReference) {
130 builder.default(es6Default).var(name || importedSource).defaultInterop().read("default");
131 } else {
132 builder.default(es6Default).var(name).defaultInterop().prop(importName);
133 }
134 } else if (isNamed) {
135 builder.default(es6Default).read(importName);
136 }
137 } else if (isModuleForBabel) {
138 builder.import();
139
140 if (isNamespace) {
141 builder.namespace(name || importedSource);
142 } else if (isDefault || isNamed) {
143 builder.named(name, importName);
144 }
145 } else {
146 builder.require();
147
148 if (isNamespace) {
149 builder.var(name || importedSource).wildcardInterop();
150 } else if ((isDefault || isNamed) && ensureLiveReference) {
151 if (isDefault) {
152 name = name !== "default" ? name : importedSource;
153 builder.var(name).read(importName);
154 builder.defaultInterop();
155 } else {
156 builder.var(importedSource).read(importName);
157 }
158 } else if (isDefault) {
159 builder.var(name).defaultInterop().prop(importName);
160 } else if (isNamed) {
161 builder.var(name).prop(importName);
162 }
163 }
164 } else if (importedInterop === "compiled") {
165 if (isModuleForNode) {
166 builder.import();
167
168 if (isNamespace) {
169 builder.default(name || importedSource);
170 } else if (isDefault || isNamed) {
171 builder.default(importedSource).read(name);
172 }
173 } else if (isModuleForBabel) {
174 builder.import();
175
176 if (isNamespace) {
177 builder.namespace(name || importedSource);
178 } else if (isDefault || isNamed) {
179 builder.named(name, importName);
180 }
181 } else {
182 builder.require();
183
184 if (isNamespace) {
185 builder.var(name || importedSource);
186 } else if (isDefault || isNamed) {
187 if (ensureLiveReference) {
188 builder.var(importedSource).read(name);
189 } else {
190 builder.prop(importName).var(name);
191 }
192 }
193 }
194 } else if (importedInterop === "uncompiled") {
195 if (isDefault && ensureLiveReference) {
196 throw new Error("No live reference for commonjs default");
197 }
198
199 if (isModuleForNode) {
200 builder.import();
201
202 if (isNamespace) {
203 builder.default(name || importedSource);
204 } else if (isDefault) {
205 builder.default(name);
206 } else if (isNamed) {
207 builder.default(importedSource).read(name);
208 }
209 } else if (isModuleForBabel) {
210 builder.import();
211
212 if (isNamespace) {
213 builder.default(name || importedSource);
214 } else if (isDefault) {
215 builder.default(name);
216 } else if (isNamed) {
217 builder.named(name, importName);
218 }
219 } else {
220 builder.require();
221
222 if (isNamespace) {
223 builder.var(name || importedSource);
224 } else if (isDefault) {
225 builder.var(name);
226 } else if (isNamed) {
227 if (ensureLiveReference) {
228 builder.var(importedSource).read(name);
229 } else {
230 builder.var(name).prop(importName);
231 }
232 }
233 }
234 } else {
235 throw new Error(`Unknown importedInterop "${importedInterop}".`);
236 }
237
238 const {
239 statements,
240 resultName
241 } = builder.done();
242
243 this._insertStatements(statements, blockHoist);
244
245 if ((isDefault || isNamed) && ensureNoContext && resultName.type !== "Identifier") {
246 return t.sequenceExpression([t.numericLiteral(0), resultName]);
247 }
248
249 return resultName;
250 }
251
252 _insertStatements(statements, blockHoist = 3) {
253 statements.forEach(node => {
254 node._blockHoist = blockHoist;
255 });
256
257 const targetPath = this._programPath.get("body").find(p => {
258 const val = p.node._blockHoist;
259 return Number.isFinite(val) && val < 4;
260 });
261
262 if (targetPath) {
263 targetPath.insertBefore(statements);
264 } else {
265 this._programPath.unshiftContainer("body", statements);
266 }
267 }
268
269}
270
271exports.default = ImportInjector;
\No newline at end of file