"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), void 0); } _applyDefaults(importedSource, opts, isInit = false) { let newOpts; if (typeof importedSource === "string") { newOpts = Object.assign({}, this._defaultOpts, { importedSource }, opts); } else { _assert(!opts, "Unexpected secondary arguments."); newOpts = Object.assign({}, this._defaultOpts, importedSource); } if (!isInit && opts) { 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;