| "use strict"; |
| |
| Object.defineProperty(exports, "__esModule", { |
| value: true |
| }); |
| exports.default = void 0; |
| |
| var _assert = require("assert"); |
| |
| var _t = require("@babel/types"); |
| |
| var _importBuilder = require("./import-builder"); |
| |
| var _isModule = require("./is-module"); |
| |
| const { |
| numericLiteral, |
| sequenceExpression |
| } = _t; |
| |
| class ImportInjector { |
| constructor(path, importedSource, opts) { |
| this._defaultOpts = { |
| importedSource: null, |
| importedType: "commonjs", |
| importedInterop: "babel", |
| importingInterop: "babel", |
| ensureLiveReference: false, |
| ensureNoContext: false, |
| importPosition: "before" |
| }; |
| const programPath = path.find(p => p.isProgram()); |
| this._programPath = programPath; |
| this._programScope = programPath.scope; |
| this._hub = programPath.hub; |
| this._defaultOpts = this._applyDefaults(importedSource, opts, true); |
| } |
| |
| addDefault(importedSourceIn, opts) { |
| return this.addNamed("default", importedSourceIn, opts); |
| } |
| |
| addNamed(importName, importedSourceIn, opts) { |
| _assert(typeof importName === "string"); |
| |
| return this._generateImport(this._applyDefaults(importedSourceIn, opts), importName); |
| } |
| |
| addNamespace(importedSourceIn, opts) { |
| return this._generateImport(this._applyDefaults(importedSourceIn, opts), null); |
| } |
| |
| addSideEffect(importedSourceIn, opts) { |
| return this._generateImport(this._applyDefaults(importedSourceIn, opts), false); |
| } |
| |
| _applyDefaults(importedSource, opts, isInit = false) { |
| const optsList = []; |
| |
| if (typeof importedSource === "string") { |
| optsList.push({ |
| importedSource |
| }); |
| optsList.push(opts); |
| } else { |
| _assert(!opts, "Unexpected secondary arguments."); |
| |
| optsList.push(importedSource); |
| } |
| |
| const newOpts = Object.assign({}, this._defaultOpts); |
| |
| for (const opts of optsList) { |
| if (!opts) continue; |
| Object.keys(newOpts).forEach(key => { |
| if (opts[key] !== undefined) newOpts[key] = opts[key]; |
| }); |
| |
| if (!isInit) { |
| if (opts.nameHint !== undefined) newOpts.nameHint = opts.nameHint; |
| if (opts.blockHoist !== undefined) newOpts.blockHoist = opts.blockHoist; |
| } |
| } |
| |
| return newOpts; |
| } |
| |
| _generateImport(opts, importName) { |
| const isDefault = importName === "default"; |
| const isNamed = !!importName && !isDefault; |
| const isNamespace = importName === null; |
| const { |
| importedSource, |
| importedType, |
| importedInterop, |
| importingInterop, |
| ensureLiveReference, |
| ensureNoContext, |
| nameHint, |
| importPosition, |
| blockHoist |
| } = opts; |
| let name = nameHint || importName; |
| const isMod = (0, _isModule.default)(this._programPath); |
| const isModuleForNode = isMod && importingInterop === "node"; |
| const isModuleForBabel = isMod && importingInterop === "babel"; |
| |
| if (importPosition === "after" && !isMod) { |
| throw new Error(`"importPosition": "after" is only supported in modules`); |
| } |
| |
| const builder = new _importBuilder.default(importedSource, this._programScope, this._hub); |
| |
| if (importedType === "es6") { |
| if (!isModuleForNode && !isModuleForBabel) { |
| throw new Error("Cannot import an ES6 module from CommonJS"); |
| } |
| |
| builder.import(); |
| |
| if (isNamespace) { |
| builder.namespace(nameHint || importedSource); |
| } else if (isDefault || isNamed) { |
| builder.named(name, importName); |
| } |
| } else if (importedType !== "commonjs") { |
| throw new Error(`Unexpected interopType "${importedType}"`); |
| } else if (importedInterop === "babel") { |
| if (isModuleForNode) { |
| name = name !== "default" ? name : importedSource; |
| const es6Default = `${importedSource}$es6Default`; |
| builder.import(); |
| |
| if (isNamespace) { |
| builder.default(es6Default).var(name || importedSource).wildcardInterop(); |
| } else if (isDefault) { |
| if (ensureLiveReference) { |
| builder.default(es6Default).var(name || importedSource).defaultInterop().read("default"); |
| } else { |
| builder.default(es6Default).var(name).defaultInterop().prop(importName); |
| } |
| } else if (isNamed) { |
| builder.default(es6Default).read(importName); |
| } |
| } else if (isModuleForBabel) { |
| builder.import(); |
| |
| if (isNamespace) { |
| builder.namespace(name || importedSource); |
| } else if (isDefault || isNamed) { |
| builder.named(name, importName); |
| } |
| } else { |
| builder.require(); |
| |
| if (isNamespace) { |
| builder.var(name || importedSource).wildcardInterop(); |
| } else if ((isDefault || isNamed) && ensureLiveReference) { |
| if (isDefault) { |
| name = name !== "default" ? name : importedSource; |
| builder.var(name).read(importName); |
| builder.defaultInterop(); |
| } else { |
| builder.var(importedSource).read(importName); |
| } |
| } else if (isDefault) { |
| builder.var(name).defaultInterop().prop(importName); |
| } else if (isNamed) { |
| builder.var(name).prop(importName); |
| } |
| } |
| } else if (importedInterop === "compiled") { |
| if (isModuleForNode) { |
| builder.import(); |
| |
| if (isNamespace) { |
| builder.default(name || importedSource); |
| } else if (isDefault || isNamed) { |
| builder.default(importedSource).read(name); |
| } |
| } else if (isModuleForBabel) { |
| builder.import(); |
| |
| if (isNamespace) { |
| builder.namespace(name || importedSource); |
| } else if (isDefault || isNamed) { |
| builder.named(name, importName); |
| } |
| } else { |
| builder.require(); |
| |
| if (isNamespace) { |
| builder.var(name || importedSource); |
| } else if (isDefault || isNamed) { |
| if (ensureLiveReference) { |
| builder.var(importedSource).read(name); |
| } else { |
| builder.prop(importName).var(name); |
| } |
| } |
| } |
| } else if (importedInterop === "uncompiled") { |
| if (isDefault && ensureLiveReference) { |
| throw new Error("No live reference for commonjs default"); |
| } |
| |
| if (isModuleForNode) { |
| builder.import(); |
| |
| if (isNamespace) { |
| builder.default(name || importedSource); |
| } else if (isDefault) { |
| builder.default(name); |
| } else if (isNamed) { |
| builder.default(importedSource).read(name); |
| } |
| } else if (isModuleForBabel) { |
| builder.import(); |
| |
| if (isNamespace) { |
| builder.default(name || importedSource); |
| } else if (isDefault) { |
| builder.default(name); |
| } else if (isNamed) { |
| builder.named(name, importName); |
| } |
| } else { |
| builder.require(); |
| |
| if (isNamespace) { |
| builder.var(name || importedSource); |
| } else if (isDefault) { |
| builder.var(name); |
| } else if (isNamed) { |
| if (ensureLiveReference) { |
| builder.var(importedSource).read(name); |
| } else { |
| builder.var(name).prop(importName); |
| } |
| } |
| } |
| } else { |
| throw new Error(`Unknown importedInterop "${importedInterop}".`); |
| } |
| |
| const { |
| statements, |
| resultName |
| } = builder.done(); |
| |
| this._insertStatements(statements, importPosition, blockHoist); |
| |
| if ((isDefault || isNamed) && ensureNoContext && resultName.type !== "Identifier") { |
| return sequenceExpression([numericLiteral(0), resultName]); |
| } |
| |
| return resultName; |
| } |
| |
| _insertStatements(statements, importPosition = "before", blockHoist = 3) { |
| const body = this._programPath.get("body"); |
| |
| if (importPosition === "after") { |
| for (let i = body.length - 1; i >= 0; i--) { |
| if (body[i].isImportDeclaration()) { |
| body[i].insertAfter(statements); |
| return; |
| } |
| } |
| } else { |
| statements.forEach(node => { |
| node._blockHoist = blockHoist; |
| }); |
| const targetPath = body.find(p => { |
| const val = p.node._blockHoist; |
| return Number.isFinite(val) && val < 4; |
| }); |
| |
| if (targetPath) { |
| targetPath.insertBefore(statements); |
| return; |
| } |
| } |
| |
| this._programPath.unshiftContainer("body", statements); |
| } |
| |
| } |
| |
| exports.default = ImportInjector; |