babelPlugin: first attempt at import rewrites
RENAME
src/modulePlugin.js
src/babelPlugin.js
@@ -2,12 +2,13 @@ import * as h from './hidden';
export default options =>
function rewriteModules({ types: t }) {
- const { fixedExports, liveExportMap } = options;
+ const { fixedExports, imports, importDecls, liveExportMap } = options;
const hiddenIdentifier = hi => {
const ident = t.identifier(hi);
ident.allowedInternalHidden = true;
return ident;
};
+ const updaters = {};
const visitor = {
Identifier(path) {
if (options.allowHidden || path.node.allowedInternalHidden) {
@@ -32,20 +33,40 @@ export default options =>
// We handle all the import and export productions.
const moduleVisitor = {
- ImportNamespaceSpecifier(path) {
- throw path.buildCodeFrameError(
- `FIXME: "import *" is not yet implemented`,
- );
- },
- ImportDefaultSpecifier(path) {
- throw path.buildCodeFrameError(
- `FIXME: "import default" is not yet implemented`,
- );
- },
- ImportSpecifier(path) {
+ ImportDeclaration(path) {
+ const specs = path.node.specifiers;
+ const myImports = [];
+ imports[path.node.source.value] = myImports;
+ if (!specs) {
+ return;
+ }
+ specs.forEach(spec => {
+ const importTo = spec.local.name;
+ importDecls.push(importTo);
+ let importFrom;
+ switch (spec.type) {
+ case 'ImportDefaultSpecifier':
+ importFrom = 'default';
+ break;
+ case 'ImportNamespaceSpecifier':
+ importFrom = '*';
+ break;
+ case 'ImportSpecifier':
+ importFrom = spec.imported.name;
+ break;
+ default:
throw path.buildCodeFrameError(
- `FIXME: "import {}" is not yet implemented`,
+ `Unrecognized import specifier type ${spec.type}`,
);
+ }
+
+ const myUpdaters = myImports[importFrom] || [];
+ if (myUpdaters.length === 0) {
+ myImports[importFrom] = myUpdaters;
+ }
+ myUpdaters.push(`${h.HIDDEN_A} => (${importTo} = ${h.HIDDEN_A})`);
+ updaters[importTo] = myUpdaters;
+ });
},
ExportDefaultDeclaration(path) {
// export default FOO -> $h_once.default(FOO)
@@ -188,8 +209,18 @@ export default options =>
}
replace.push(
...specs.map(spec => {
- const { local, exported } = spec;
- liveExportMap[exported.name] = [local.name];
+ const { local, exported, source } = spec;
+ // If local.name is reexported we omit it.
+ const myUpdaters = updaters[local.name];
+ if (myUpdaters) {
+ // If there are updaters, we must have a local
+ // name, so update it with this export.
+ myUpdaters.push(`${h.HIDDEN_LIVE}.${local.name}`);
+ }
+ // If it was imported directly (i.e. has a source or updaters)
+ // then don't put the local name in the liveExportMap.
+ liveExportMap[exported.name] =
+ source || myUpdaters ? [] : [local.name];
const callee = t.memberExpression(
hiddenIdentifier(h.HIDDEN_LIVE),
exported,

MODIFY
src/hidden.js
src/hidden.js
export const HIDDEN_PREFIX = '$h\u200d_';
+export const HIDDEN_A = `${HIDDEN_PREFIX}a`;
export const HIDDEN_IMPORT = `${HIDDEN_PREFIX}import`;
export const HIDDEN_IMPORT_SELF = `${HIDDEN_PREFIX}importSelf`;
export const HIDDEN_IMPORTS = `${HIDDEN_PREFIX}imports`;
export const HIDDEN_ONCE = `${HIDDEN_PREFIX}once`;
export const HIDDEN_LIVE = `${HIDDEN_PREFIX}live`;
export const HIDDEN_SYMBOLS = [
+ HIDDEN_A,
HIDDEN_IMPORT,
HIDDEN_IMPORT_SELF,
HIDDEN_IMPORTS,

MODIFY
src/index.js
src/index.js
import * as h from './hidden';
-import makeModulePlugin from './modulePlugin';
+import makeModulePlugin from './babelPlugin';
const makeModuleTransformer = (babelCore, makeImporter) => {
function transformSource(source, sourceOptions = {}) {

babelPlugin: first attempt at import rewrites