Implement a new utility module for injecting module imports.
This commit is contained in:
parent
84184e2ddd
commit
ec9754bc40
@ -10,6 +10,7 @@ export default {
|
|||||||
* - 1 Default node position
|
* - 1 Default node position
|
||||||
* - 2 Priority over normal nodes
|
* - 2 Priority over normal nodes
|
||||||
* - 3 We want this to be at the **very** top
|
* - 3 We want this to be at the **very** top
|
||||||
|
* - 4 Reserved for the helpers used to implement module imports.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
name: "internal.blockHoist",
|
name: "internal.blockHoist",
|
||||||
|
|||||||
3
packages/babel-helper-module-imports/.npmignore
Normal file
3
packages/babel-helper-module-imports/.npmignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
src
|
||||||
|
test
|
||||||
|
*.log
|
||||||
27
packages/babel-helper-module-imports/README.md
Normal file
27
packages/babel-helper-module-imports/README.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# babel-helper-module-imports
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Adding a named impport
|
||||||
|
|
||||||
|
```
|
||||||
|
import { addNamed } from "babel-helper-module-imports";
|
||||||
|
|
||||||
|
export default function({ types: t }) {
|
||||||
|
return {
|
||||||
|
visitor: {
|
||||||
|
ReferencedIdentifier(path) {
|
||||||
|
let importName = this.importName;
|
||||||
|
if (importName) {
|
||||||
|
importName = t.cloneDeep(importName);
|
||||||
|
} else {
|
||||||
|
// require('bluebird').coroutine
|
||||||
|
importName = this.importName = addName(path, 'coroutine', 'bluebird');
|
||||||
|
}
|
||||||
|
|
||||||
|
path.replaceWith(importName);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
14
packages/babel-helper-module-imports/package.json
Normal file
14
packages/babel-helper-module-imports/package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "babel-helper-module-imports",
|
||||||
|
"version": "7.0.0-beta.2",
|
||||||
|
"description": "Babel helper functions for inserting module loads",
|
||||||
|
"author": "Logan Smyth <loganfsmyth@gmail.com>",
|
||||||
|
"homepage": "https://babeljs.io/",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-module-imports",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"babel-types": "7.0.0-beta.2",
|
||||||
|
"lodash": "^4.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
142
packages/babel-helper-module-imports/src/import-builder.js
Normal file
142
packages/babel-helper-module-imports/src/import-builder.js
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import assert from "assert";
|
||||||
|
import * as t from "babel-types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to track and accumulate mutations to the AST that will eventually
|
||||||
|
* output a new require/import statement list.
|
||||||
|
*/
|
||||||
|
export default class ImportBuilder {
|
||||||
|
_statements = [];
|
||||||
|
_resultName = null;
|
||||||
|
|
||||||
|
_scope = null;
|
||||||
|
_file = null;
|
||||||
|
|
||||||
|
constructor(importedSource, scope, file) {
|
||||||
|
this._scope = scope;
|
||||||
|
this._file = file;
|
||||||
|
this._importedSource = importedSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
done() {
|
||||||
|
return {
|
||||||
|
statements: this._statements,
|
||||||
|
resultName: this._resultName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
import() {
|
||||||
|
const importedSource = this._file.resolveModuleSource(this._importedSource);
|
||||||
|
|
||||||
|
this._statements.push(
|
||||||
|
t.importDeclaration([], t.stringLiteral(importedSource)),
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
require() {
|
||||||
|
const importedSource = this._file.resolveModuleSource(this._importedSource);
|
||||||
|
|
||||||
|
this._statements.push(
|
||||||
|
t.expressionStatement(
|
||||||
|
t.callExpression(t.identifier("require"), [
|
||||||
|
t.stringLiteral(importedSource),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace(name) {
|
||||||
|
name = this._scope.generateUidIdentifier(name);
|
||||||
|
|
||||||
|
const statement = this._statements[this._statements.length - 1];
|
||||||
|
assert(statement.type === "ImportDeclaration");
|
||||||
|
assert(statement.specifiers.length === 0);
|
||||||
|
statement.specifiers = [t.importNamespaceSpecifier(name)];
|
||||||
|
this._resultName = t.clone(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
default(name) {
|
||||||
|
name = this._scope.generateUidIdentifier(name);
|
||||||
|
const statement = this._statements[this._statements.length - 1];
|
||||||
|
assert(statement.type === "ImportDeclaration");
|
||||||
|
assert(statement.specifiers.length === 0);
|
||||||
|
statement.specifiers = [t.importDefaultSpecifier(name)];
|
||||||
|
this._resultName = t.clone(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
named(name, importName) {
|
||||||
|
if (importName === "default") return this.default(name);
|
||||||
|
|
||||||
|
name = this._scope.generateUidIdentifier(name);
|
||||||
|
const statement = this._statements[this._statements.length - 1];
|
||||||
|
assert(statement.type === "ImportDeclaration");
|
||||||
|
assert(statement.specifiers.length === 0);
|
||||||
|
statement.specifiers = [t.importSpecifier(name, t.identifier(importName))];
|
||||||
|
this._resultName = t.clone(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
var(name) {
|
||||||
|
name = this._scope.generateUidIdentifier(name);
|
||||||
|
let statement = this._statements[this._statements.length - 1];
|
||||||
|
if (statement.type !== "ExpressionStatement") {
|
||||||
|
assert(this._resultName);
|
||||||
|
statement = t.expressionStatement(this._resultName);
|
||||||
|
this._statements.push(statement);
|
||||||
|
}
|
||||||
|
this._statements[
|
||||||
|
this._statements.length - 1
|
||||||
|
] = t.variableDeclaration("var", [
|
||||||
|
t.variableDeclarator(name, statement.expression),
|
||||||
|
]);
|
||||||
|
this._resultName = t.clone(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultInterop() {
|
||||||
|
return this._interop(this._file.addHelper("interopRequireDefault"));
|
||||||
|
}
|
||||||
|
wildcardInterop() {
|
||||||
|
return this._interop(this._file.addHelper("interopRequireWildcard"));
|
||||||
|
}
|
||||||
|
|
||||||
|
_interop(callee) {
|
||||||
|
const statement = this._statements[this._statements.length - 1];
|
||||||
|
if (statement.type === "ExpressionStatement") {
|
||||||
|
statement.expression = t.callExpression(callee, [statement.expression]);
|
||||||
|
} else if (statement.type === "VariableDeclaration") {
|
||||||
|
assert(statement.declarations.length === 1);
|
||||||
|
statement.declarations[0].init = t.callExpression(callee, [
|
||||||
|
statement.declarations[0].init,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
assert.fail("Unexpected type.");
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop(name) {
|
||||||
|
const statement = this._statements[this._statements.length - 1];
|
||||||
|
if (statement.type === "ExpressionStatement") {
|
||||||
|
statement.expression = t.memberExpression(
|
||||||
|
statement.expression,
|
||||||
|
t.identifier(name),
|
||||||
|
);
|
||||||
|
} else if (statement.type === "VariableDeclaration") {
|
||||||
|
assert(statement.declarations.length === 1);
|
||||||
|
statement.declarations[0].init = t.memberExpression(
|
||||||
|
statement.declarations[0].init,
|
||||||
|
t.identifier(name),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
assert.fail("Unexpected type:" + statement.type);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
read(name) {
|
||||||
|
this._resultName = t.memberExpression(this._resultName, t.identifier(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
425
packages/babel-helper-module-imports/src/import-injector.js
Normal file
425
packages/babel-helper-module-imports/src/import-injector.js
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
import assert from "assert";
|
||||||
|
import * as t from "babel-types";
|
||||||
|
|
||||||
|
import ImportBuilder from "./import-builder";
|
||||||
|
import isModule from "./is-module";
|
||||||
|
|
||||||
|
export type ImportOptions = {
|
||||||
|
/**
|
||||||
|
* The module being referenced.
|
||||||
|
*/
|
||||||
|
importedSource: string | null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of module being imported:
|
||||||
|
*
|
||||||
|
* * 'es6' - An ES6 module.
|
||||||
|
* * 'commonjs' - A CommonJS module. (Default)
|
||||||
|
*/
|
||||||
|
importedType: "es6" | "commonjs",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of interop behavior for namespace/default/named when loading
|
||||||
|
* CommonJS modules.
|
||||||
|
*
|
||||||
|
* ## 'babel' (Default)
|
||||||
|
*
|
||||||
|
* Load using Babel's interop.
|
||||||
|
*
|
||||||
|
* If '.__esModule' is true, treat as 'compiled', else:
|
||||||
|
*
|
||||||
|
* * Namespace: A copy of the module.exports with .default
|
||||||
|
* populated by the module.exports object.
|
||||||
|
* * Default: The module.exports value.
|
||||||
|
* * Named: The .named property of module.exports.
|
||||||
|
*
|
||||||
|
* The 'ensureLiveReference' has no effect on the liveness of these.
|
||||||
|
*
|
||||||
|
* ## 'compiled'
|
||||||
|
*
|
||||||
|
* Assume the module is ES6 compiled to CommonJS. Useful to avoid injecting
|
||||||
|
* interop logic if you are confident that the module is a certain format.
|
||||||
|
*
|
||||||
|
* * Namespace: The root module.exports object.
|
||||||
|
* * Default: The .default property of the namespace.
|
||||||
|
* * Named: The .named property of the namespace.
|
||||||
|
*
|
||||||
|
* Will return erroneous results if the imported module is _not_ compiled
|
||||||
|
* from ES6 with Babel.
|
||||||
|
*
|
||||||
|
* ## 'uncompiled'
|
||||||
|
*
|
||||||
|
* Assume the module is _not_ ES6 compiled to CommonJS. Used a simplified
|
||||||
|
* access pattern that doesn't require additional function calls.
|
||||||
|
*
|
||||||
|
* Will return erroneous results if the imported module _is_ compiled
|
||||||
|
* from ES6 with Babel.
|
||||||
|
*
|
||||||
|
* * Namespace: The module.exports object.
|
||||||
|
* * Default: The module.exports object.
|
||||||
|
* * Named: The .named property of module.exports.
|
||||||
|
*/
|
||||||
|
importedInterop: "babel" | "node" | "compiled" | "uncompiled",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of CommonJS interop included in the environment that will be
|
||||||
|
* loading the output code.
|
||||||
|
*
|
||||||
|
* * 'babel' - CommonJS modules load with Babel's interop. (Default)
|
||||||
|
* * 'node' - CommonJS modules load with Node's interop.
|
||||||
|
*
|
||||||
|
* See descriptions in 'importedInterop' for more details.
|
||||||
|
*/
|
||||||
|
importingInterop: "babel" | "node",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define whether we explicitly care that the import be a live reference.
|
||||||
|
* Only applies when importing default and named imports, not the namespace.
|
||||||
|
*
|
||||||
|
* * true - Force imported values to be live references.
|
||||||
|
* * false - No particular requirements. Keeps the code simplest. (Default)
|
||||||
|
*/
|
||||||
|
ensureLiveReference: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define if we explicitly care that the result not be a property reference.
|
||||||
|
*
|
||||||
|
* * true - Force calls to exclude context. Useful if the value is going to
|
||||||
|
* be used as function callee.
|
||||||
|
* * false - No particular requirements for context of the access. (Default)
|
||||||
|
*/
|
||||||
|
ensureNoContext: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A general helper classes add imports via transforms. See README for usage.
|
||||||
|
*/
|
||||||
|
export default class ImportInjector {
|
||||||
|
/**
|
||||||
|
* The path used for manipulation.
|
||||||
|
*/
|
||||||
|
_programPath: NodePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scope used to generate unique variable names.
|
||||||
|
*/
|
||||||
|
_programScope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file used to inject helpers and resolve paths.
|
||||||
|
*/
|
||||||
|
_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default options to use with this instance when imports are added.
|
||||||
|
*/
|
||||||
|
_defaultOpts: ImportOptions = {
|
||||||
|
importedSource: null,
|
||||||
|
importedType: "commonjs",
|
||||||
|
importedInterop: "babel",
|
||||||
|
importingInterop: "babel",
|
||||||
|
ensureLiveReference: false,
|
||||||
|
ensureNoContext: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(path, importedSource, opts) {
|
||||||
|
const programPath = path.find(p => p.isProgram());
|
||||||
|
|
||||||
|
this._programPath = programPath;
|
||||||
|
this._programScope = programPath.scope;
|
||||||
|
this._file = programPath.hub.file;
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
|
// Provide a hint for generateUidIdentifier for the local variable name
|
||||||
|
// to use for the import, if the code will generate a simple assignment
|
||||||
|
// to a variable.
|
||||||
|
nameHint = importName,
|
||||||
|
|
||||||
|
// Not meant for public usage. Allows code that absolutely must control
|
||||||
|
// ordering to set a specific hoist value on the import nodes.
|
||||||
|
blockHoist,
|
||||||
|
} = opts;
|
||||||
|
|
||||||
|
const isMod = isModule(this._programPath, true);
|
||||||
|
const isModuleForNode = isMod && importingInterop === "node";
|
||||||
|
const isModuleForBabel = isMod && importingInterop === "babel";
|
||||||
|
|
||||||
|
const builder = new ImportBuilder(
|
||||||
|
importedSource,
|
||||||
|
this._programScope,
|
||||||
|
this._file,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (importedType === "es6") {
|
||||||
|
if (!isModuleForNode && !isModuleForBabel) {
|
||||||
|
throw new Error("Cannot import an ES6 module from CommonJS");
|
||||||
|
}
|
||||||
|
|
||||||
|
// import * as namespace from ''; namespace
|
||||||
|
// import def from ''; def
|
||||||
|
// import { named } from ''; named
|
||||||
|
builder.import();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.namespace("namespace");
|
||||||
|
} else if (isDefault || isNamed) {
|
||||||
|
builder.named(nameHint, importName);
|
||||||
|
}
|
||||||
|
} else if (importedType !== "commonjs") {
|
||||||
|
throw new Error(`Unexpected interopType "${importedType}"`);
|
||||||
|
} else if (importedInterop === "babel") {
|
||||||
|
if (isModuleForNode) {
|
||||||
|
// import _tmp from ''; var namespace = interopRequireWildcard(_tmp); namespace
|
||||||
|
// import _tmp from ''; var def = interopRequireDefault(_tmp).default; def
|
||||||
|
// import _tmp from ''; _tmp.named
|
||||||
|
|
||||||
|
builder.import();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder
|
||||||
|
.default("es6Default")
|
||||||
|
.var(nameHint || "namespace")
|
||||||
|
.wildcardInterop();
|
||||||
|
} else if (isDefault) {
|
||||||
|
if (ensureLiveReference) {
|
||||||
|
builder
|
||||||
|
.default("es6Default")
|
||||||
|
.var("namespace")
|
||||||
|
.defaultInterop()
|
||||||
|
.read("default");
|
||||||
|
} else {
|
||||||
|
builder
|
||||||
|
.default("es6Default")
|
||||||
|
.var(nameHint)
|
||||||
|
.defaultInterop()
|
||||||
|
.prop(importName);
|
||||||
|
}
|
||||||
|
} else if (isNamed) {
|
||||||
|
builder.default("es6Default").read(importName);
|
||||||
|
}
|
||||||
|
} else if (isModuleForBabel) {
|
||||||
|
// import * as namespace from ''; namespace
|
||||||
|
// import def from ''; def
|
||||||
|
// import { named } from ''; named
|
||||||
|
builder.import();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.namespace("namespace");
|
||||||
|
} else if (isDefault || isNamed) {
|
||||||
|
builder.named(nameHint, importName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// var namespace = interopRequireWildcard(require(''));
|
||||||
|
// var def = interopRequireDefault(require('')).default; def
|
||||||
|
// var named = require('').named; named
|
||||||
|
builder.require();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.var("namespace").wildcardInterop();
|
||||||
|
} else if ((isDefault || isNamed) && ensureLiveReference) {
|
||||||
|
builder.var("namespace").read(importName);
|
||||||
|
|
||||||
|
if (isDefault) builder.defaultInterop();
|
||||||
|
} else if (isDefault) {
|
||||||
|
builder
|
||||||
|
.var(nameHint)
|
||||||
|
.defaultInterop()
|
||||||
|
.prop(importName);
|
||||||
|
} else if (isNamed) {
|
||||||
|
builder.var(nameHint).prop(importName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (importedInterop === "compiled") {
|
||||||
|
if (isModuleForNode) {
|
||||||
|
// import namespace from ''; namespace
|
||||||
|
// import namespace from ''; namespace.default
|
||||||
|
// import namespace from ''; namespace.named
|
||||||
|
|
||||||
|
builder.import();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.default("namespace");
|
||||||
|
} else if (isDefault || isNamed) {
|
||||||
|
builder.default("namespace").read(importName);
|
||||||
|
}
|
||||||
|
} else if (isModuleForBabel) {
|
||||||
|
// import * as namespace from ''; namespace
|
||||||
|
// import def from ''; def
|
||||||
|
// import { named } from ''; named
|
||||||
|
// Note: These lookups will break if the module has no __esModule set,
|
||||||
|
// hence the warning that 'compiled' will not work on standard CommonJS.
|
||||||
|
|
||||||
|
builder.import();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.namespace("namespace");
|
||||||
|
} else if (isDefault || isNamed) {
|
||||||
|
builder.named(nameHint, importName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// var namespace = require(''); namespace
|
||||||
|
// var namespace = require(''); namespace.default
|
||||||
|
// var namespace = require(''); namespace.named
|
||||||
|
// var named = require('').named;
|
||||||
|
|
||||||
|
builder.require();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.var("namespace");
|
||||||
|
} else if (isDefault || isNamed) {
|
||||||
|
if (ensureLiveReference) {
|
||||||
|
builder.var("namespace").read(importName);
|
||||||
|
} else {
|
||||||
|
builder.prop(importName).var(nameHint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (importedInterop === "uncompiled") {
|
||||||
|
if (isDefault && ensureLiveReference) {
|
||||||
|
throw new Error("No live reference for commonjs default");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isModuleForNode) {
|
||||||
|
// import namespace from ''; namespace
|
||||||
|
// import def from ''; def;
|
||||||
|
// import namespace from ''; namespace.named
|
||||||
|
|
||||||
|
builder.import();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.default("namespace");
|
||||||
|
} else if (isDefault) {
|
||||||
|
builder.default(nameHint);
|
||||||
|
} else if (isNamed) {
|
||||||
|
builder.default("namespace").read(importName);
|
||||||
|
}
|
||||||
|
} else if (isModuleForBabel) {
|
||||||
|
// import namespace from '';
|
||||||
|
// import def from '';
|
||||||
|
// import { named } from ''; named;
|
||||||
|
// Note: These lookups will break if the module has __esModule set,
|
||||||
|
// hence the warning that 'uncompiled' will not work on ES6 transpiled
|
||||||
|
// to CommonJS.
|
||||||
|
|
||||||
|
builder.import();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.default("namespace");
|
||||||
|
} else if (isDefault) {
|
||||||
|
builder.default(nameHint);
|
||||||
|
} else if (isNamed) {
|
||||||
|
builder.named(nameHint, importName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// var namespace = require(''); namespace
|
||||||
|
// var def = require(''); def
|
||||||
|
// var namespace = require(''); namespace.named
|
||||||
|
// var named = require('').named;
|
||||||
|
|
||||||
|
builder.require();
|
||||||
|
if (isNamespace) {
|
||||||
|
builder.var("namespace");
|
||||||
|
} else if (isDefault) {
|
||||||
|
builder.var(nameHint);
|
||||||
|
} else if (isNamed) {
|
||||||
|
if (ensureLiveReference) {
|
||||||
|
builder.var("namespace").read(importName);
|
||||||
|
} else {
|
||||||
|
builder.var(nameHint).prop(importName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unknown importedInterop "${importedInterop}".`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { statements, resultName } = builder.done();
|
||||||
|
|
||||||
|
this._insertStatements(statements, blockHoist);
|
||||||
|
|
||||||
|
if (
|
||||||
|
(isDefault || isNamed) &&
|
||||||
|
ensureNoContext &&
|
||||||
|
resultName.type !== "Identifier"
|
||||||
|
) {
|
||||||
|
return t.sequenceExpression([t.numericLiteral(0), resultName]);
|
||||||
|
}
|
||||||
|
return resultName;
|
||||||
|
}
|
||||||
|
|
||||||
|
_insertStatements(statements, blockHoist = 3) {
|
||||||
|
statements.forEach(node => {
|
||||||
|
node._blockHoist = blockHoist;
|
||||||
|
});
|
||||||
|
|
||||||
|
const targetPath = this._programPath.get("body").filter(p => {
|
||||||
|
const val = p.node._blockHoist;
|
||||||
|
return Number.isFinite(val) && val < 4;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
if (targetPath) {
|
||||||
|
targetPath.insertBefore(statements);
|
||||||
|
} else {
|
||||||
|
this._programPath.unshiftContainer("body", statements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
packages/babel-helper-module-imports/src/index.js
Normal file
21
packages/babel-helper-module-imports/src/index.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import ImportInjector from "./import-injector";
|
||||||
|
|
||||||
|
export { ImportInjector };
|
||||||
|
|
||||||
|
export { default as isModule } from "./is-module";
|
||||||
|
|
||||||
|
export function addDefault(path, importedSource, opts) {
|
||||||
|
return new ImportInjector(path).addDefault(importedSource, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addNamed(path, name, importedSource, opts) {
|
||||||
|
return new ImportInjector(path).addNamed(name, importedSource, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addNamespace(path, importedSource, opts) {
|
||||||
|
return new ImportInjector(path).addNamespace(importedSource, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addSideEffect(path, importedSource, opts) {
|
||||||
|
return new ImportInjector(path).addSideEffect(importedSource, opts);
|
||||||
|
}
|
||||||
31
packages/babel-helper-module-imports/src/is-module.js
Normal file
31
packages/babel-helper-module-imports/src/is-module.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* A small utility to check if a file qualifies as a module, based on a few
|
||||||
|
* possible conditions.
|
||||||
|
*/
|
||||||
|
export default function isModule(
|
||||||
|
path: NodePath,
|
||||||
|
requireUnambiguous: boolean = false,
|
||||||
|
) {
|
||||||
|
const { sourceType } = path.node;
|
||||||
|
if (sourceType !== "module" && sourceType !== "script") {
|
||||||
|
throw path.buildCodeFrameError(
|
||||||
|
`Unknown sourceType "${sourceType}", cannot transform.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename = path.hub.file.opts.filename;
|
||||||
|
if (/\.mjs$/.test(filename)) {
|
||||||
|
requireUnambiguous = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
path.node.sourceType === "module" &&
|
||||||
|
(!requireUnambiguous || isUnambiguousModule(path))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This approach is not ideal. It is here to preserve compatibility for now,
|
||||||
|
// but really this should just return true or be deleted.
|
||||||
|
function isUnambiguousModule(path) {
|
||||||
|
return path.get("body").some(p => p.isModuleDeclaration());
|
||||||
|
}
|
||||||
1100
packages/babel-helper-module-imports/test/index.js
Normal file
1100
packages/babel-helper-module-imports/test/index.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@
|
|||||||
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-module-transforms",
|
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-module-transforms",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"babel-helper-module-imports": "7.0.0-beta.2",
|
||||||
"babel-template": "7.0.0-beta.2",
|
"babel-template": "7.0.0-beta.2",
|
||||||
"babel-types": "7.0.0-beta.2",
|
"babel-types": "7.0.0-beta.2",
|
||||||
"lodash": "^4.2.0"
|
"lodash": "^4.2.0"
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import * as t from "babel-types";
|
|||||||
import template from "babel-template";
|
import template from "babel-template";
|
||||||
import chunk from "lodash/chunk";
|
import chunk from "lodash/chunk";
|
||||||
|
|
||||||
|
import { isModule } from "babel-helper-module-imports";
|
||||||
|
|
||||||
import rewriteThis from "./rewrite-this";
|
import rewriteThis from "./rewrite-this";
|
||||||
import rewriteLiveReferences from "./rewrite-live-references";
|
import rewriteLiveReferences from "./rewrite-live-references";
|
||||||
import normalizeAndLoadModuleMetadata, {
|
import normalizeAndLoadModuleMetadata, {
|
||||||
@ -10,32 +12,7 @@ import normalizeAndLoadModuleMetadata, {
|
|||||||
isSideEffectImport,
|
isSideEffectImport,
|
||||||
} from "./normalize-and-load-metadata";
|
} from "./normalize-and-load-metadata";
|
||||||
|
|
||||||
export { hasExports, isSideEffectImport };
|
export { hasExports, isSideEffectImport, isModule };
|
||||||
|
|
||||||
export function isModule(path: NodePath, requireUnambiguous: boolean = false) {
|
|
||||||
const { sourceType } = path.node;
|
|
||||||
if (sourceType !== "module" && sourceType !== "script") {
|
|
||||||
throw path.buildCodeFrameError(
|
|
||||||
`Unknown sourceType "${sourceType}", cannot transform.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const filename = path.hub.file.opts.filename;
|
|
||||||
if (/\.mjs$/.test(filename)) {
|
|
||||||
requireUnambiguous = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
path.node.sourceType === "module" &&
|
|
||||||
(!requireUnambiguous || isUnambiguousModule(path))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This approach is not ideal. It is here to preserve compatibility for now,
|
|
||||||
// but really this should just return true or be deleted.
|
|
||||||
function isUnambiguousModule(path) {
|
|
||||||
return path.get("body").some(p => p.isModuleDeclaration());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform all of the generic ES6 module rewriting needed to handle initial
|
* Perform all of the generic ES6 module rewriting needed to handle initial
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user