
com.shapesecurity.bandolier.es2017.ImportExportTransformer Maven / Gradle / Ivy
/*
* Copyright 2016 Shape Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.shapesecurity.bandolier.es2017;
import com.shapesecurity.functional.data.ImmutableList;
import com.shapesecurity.functional.data.Maybe;
import com.shapesecurity.shift.es2017.ast.AssignmentExpression;
import com.shapesecurity.shift.es2017.ast.BindingIdentifier;
import com.shapesecurity.shift.es2017.ast.CallExpression;
import com.shapesecurity.shift.es2017.ast.ClassDeclaration;
import com.shapesecurity.shift.es2017.ast.ComputedMemberAssignmentTarget;
import com.shapesecurity.shift.es2017.ast.ComputedMemberExpression;
import com.shapesecurity.shift.es2017.ast.Export;
import com.shapesecurity.shift.es2017.ast.ExportAllFrom;
import com.shapesecurity.shift.es2017.ast.ExportDeclaration;
import com.shapesecurity.shift.es2017.ast.ExportDefault;
import com.shapesecurity.shift.es2017.ast.ExportFrom;
import com.shapesecurity.shift.es2017.ast.ExportFromSpecifier;
import com.shapesecurity.shift.es2017.ast.ExportLocalSpecifier;
import com.shapesecurity.shift.es2017.ast.ExportLocals;
import com.shapesecurity.shift.es2017.ast.Expression;
import com.shapesecurity.shift.es2017.ast.ExpressionStatement;
import com.shapesecurity.shift.es2017.ast.ForInStatement;
import com.shapesecurity.shift.es2017.ast.FunctionDeclaration;
import com.shapesecurity.shift.es2017.ast.FunctionDeclarationClassDeclarationExpression;
import com.shapesecurity.shift.es2017.ast.FunctionDeclarationClassDeclarationVariableDeclaration;
import com.shapesecurity.shift.es2017.ast.FunctionExpression;
import com.shapesecurity.shift.es2017.ast.IdentifierExpression;
import com.shapesecurity.shift.es2017.ast.Import;
import com.shapesecurity.shift.es2017.ast.ImportDeclaration;
import com.shapesecurity.shift.es2017.ast.ImportDeclarationExportDeclarationStatement;
import com.shapesecurity.shift.es2017.ast.ImportNamespace;
import com.shapesecurity.shift.es2017.ast.ImportSpecifier;
import com.shapesecurity.shift.es2017.ast.LiteralStringExpression;
import com.shapesecurity.shift.es2017.ast.Module;
import com.shapesecurity.shift.es2017.ast.Script;
import com.shapesecurity.shift.es2017.ast.SpreadElementExpression;
import com.shapesecurity.shift.es2017.ast.Statement;
import com.shapesecurity.shift.es2017.ast.VariableDeclaration;
import com.shapesecurity.shift.es2017.ast.VariableDeclarationKind;
import com.shapesecurity.shift.es2017.ast.VariableDeclarationStatement;
import com.shapesecurity.shift.es2017.ast.VariableDeclarator;
/**
* ImportExportTransformer applies the transformations necessary for reducing a {@link Module} to a
* {@link Script}.
*/
public class ImportExportTransformer {
static public Module transformModule(Module module) {
ImmutableList statementItems =
module.items.bind(ImportExportTransformer::transformImportDeclarationExportDeclarationStatement);
ImmutableList items =
statementItems.map(x -> (ImportDeclarationExportDeclarationStatement) x);
return new Module(module.directives, items);
}
static private ImmutableList transformImportDeclarationExportDeclarationStatement(
ImportDeclarationExportDeclarationStatement statement) {
if (statement instanceof ImportDeclaration) {
return transformImportDeclaration((ImportDeclaration) statement);
} else if (statement instanceof ExportDeclaration) {
return transformExportDeclaration((ExportDeclaration) statement);
} else {
return ImmutableList.of((Statement) statement); // do not transform other statements
}
}
static private ImmutableList transformImportDeclaration(ImportDeclaration declaration) {
if (declaration instanceof Import) {
return transformImport((Import) declaration);
} else if (declaration instanceof ImportNamespace) {
return transformImportNamespace((ImportNamespace) declaration);
} else {
return ImmutableList.empty(); //This should never happen!
}
}
static private ImmutableList transformImport(Import statement) {
String resolver = "__resolver";
Statement requireStatement =
statement.namedImports.isEmpty() && statement.defaultBinding.isNothing() ?
makeRequireStatement(statement.moduleSpecifier) :
makeRequireStatement(resolver, statement.moduleSpecifier);
ImmutableList variableDeclarationStatements =
statement.namedImports.map(x -> (Statement) makeNamedImportStatement(resolver, x));
if (statement.defaultBinding.isJust()) {
variableDeclarationStatements = variableDeclarationStatements.cons(
makeDefaultBindingStatement(resolver, statement.defaultBinding.fromJust()));
}
return variableDeclarationStatements.cons(requireStatement);
}
static private ImmutableList transformImportNamespace(ImportNamespace statement) {
String resolver = "__resolver";
Statement requireStatement = makeRequireStatement(resolver, statement.moduleSpecifier);
ImmutableList variableDeclarationStatements =
ImmutableList.of(makeNameSpaceBindingStatement(resolver, statement.namespaceBinding));
if (statement.defaultBinding.isJust()) {
variableDeclarationStatements = variableDeclarationStatements.cons(
makeDefaultBindingStatement(resolver, statement.defaultBinding.fromJust()));
}
return variableDeclarationStatements.cons(requireStatement);
}
static private ImmutableList transformExportDeclaration(ExportDeclaration declaration) {
if (declaration instanceof Export) {
return transformExport((Export) declaration);
} else if (declaration instanceof ExportAllFrom) {
return transformExportAllFrom((ExportAllFrom) declaration);
} else if (declaration instanceof ExportDefault) {
return transformExportDefault((ExportDefault) declaration);
} else if (declaration instanceof ExportFrom) {
return transformExportFrom((ExportFrom) declaration);
} else if (declaration instanceof ExportLocals) {
return transformExportLocals((ExportLocals) declaration);
} else {
return ImmutableList.empty(); //This should never happen
}
}
static private ImmutableList transformExport(Export statement) {
FunctionDeclarationClassDeclarationVariableDeclaration declaration = statement.declaration;
if (declaration instanceof FunctionDeclaration) {
return transformExportFunctionDeclaration((FunctionDeclaration) declaration);
} else if (declaration instanceof ClassDeclaration) {
return transformExportClassDeclaration((ClassDeclaration) declaration);
} else if (declaration instanceof VariableDeclaration) {
return transformExportVariableDeclaration((VariableDeclaration) declaration);
} else {
return ImmutableList.empty(); //This should never happen
}
}
static private ImmutableList transformExportFunctionDeclaration(FunctionDeclaration declaration) {
return ImmutableList.of(declaration,
makeNamedExportStatement(new ExportLocalSpecifier(new IdentifierExpression(declaration.name.name), Maybe.empty())));
}
static private ImmutableList transformExportClassDeclaration(ClassDeclaration declaration) {
return ImmutableList.of(declaration,
makeNamedExportStatement(new ExportLocalSpecifier(new IdentifierExpression(declaration.name.name), Maybe.empty())));
}
static private ImmutableList transformExportVariableDeclaration(VariableDeclaration declaration) {
ImmutableList exportStatements =
declaration.declarators.map(x -> {
BindingIdentifier temp = (BindingIdentifier) x.binding;
return makeNamedExportStatement(new ExportLocalSpecifier(new IdentifierExpression(temp.name), Maybe.empty()));
});
return exportStatements.cons(new VariableDeclarationStatement(declaration));
}
static private ImmutableList transformExportAllFrom(ExportAllFrom statement) {
String resolver = "__resolver";
Statement requireStatement = makeRequireStatement(resolver, statement.moduleSpecifier);
Statement enumerateExports = makeEnumerateExports(resolver);
return ImmutableList.of(requireStatement, enumerateExports);
}
static private ImmutableList transformExportDefault(ExportDefault statement) {
FunctionDeclarationClassDeclarationExpression body = statement.body;
if (body instanceof FunctionDeclaration) {
return transformExportDefaultFunctionDeclaration((FunctionDeclaration) body);
} else if (body instanceof ClassDeclaration) {
return transformExportDefaultClassDeclaration((ClassDeclaration) body);
} else if (body instanceof Expression) {
return transformExportDefaultExpression((Expression) body);
} else {
return ImmutableList.empty(); //This should never happen
}
}
static private ImmutableList transformExportDefaultFunctionDeclaration(FunctionDeclaration declaration) {
String functionName = declaration.name.name;
if (functionName.equals("*default*")) {
IdentifierExpression exportsIden = new IdentifierExpression("exports");
ComputedMemberAssignmentTarget compMem = new ComputedMemberAssignmentTarget(exportsIden, new LiteralStringExpression("default"));
AssignmentExpression assignmentExpression =
new AssignmentExpression(compMem, new FunctionExpression(false, false, Maybe.empty(),
declaration.params, declaration.body));
return ImmutableList.of(new ExpressionStatement(assignmentExpression));
} else {
return ImmutableList.of(declaration,
makeExportDefaultStatement(new ExportLocalSpecifier(new IdentifierExpression(declaration.name.name), Maybe.empty())));
}
}
static private ImmutableList transformExportDefaultClassDeclaration(ClassDeclaration declaration) {
return ImmutableList.of(declaration,
makeExportDefaultStatement(new ExportLocalSpecifier(new IdentifierExpression(declaration.name.name), Maybe.empty())));
}
static private ImmutableList transformExportDefaultExpression(Expression expression) {
IdentifierExpression exportsIden = new IdentifierExpression("exports");
ComputedMemberAssignmentTarget staticMem = new ComputedMemberAssignmentTarget(exportsIden, new LiteralStringExpression("default"));
AssignmentExpression assignmentExpression =
new AssignmentExpression(staticMem, expression);
return ImmutableList.of(new ExpressionStatement(assignmentExpression));
}
static private ImmutableList transformExportLocals(ExportLocals declaration) {
return declaration.namedExports.map(x -> (Statement) makeNamedExportStatement(x));
}
static private ImmutableList transformExportFrom(ExportFrom statement) {
String resolver = "__resolver";
String moduleSpecifier = statement.moduleSpecifier;
ImmutableList statements = statement.namedExports.map(x -> (Statement) makeNamedExportStatement(resolver, x));
return statements.cons(makeRequireStatement(resolver, moduleSpecifier));
}
// e.g., exports.x = x;
static private ExpressionStatement makeNamedExportStatement(ExportLocalSpecifier specifier) {
IdentifierExpression exportsIden = new IdentifierExpression("exports");
ComputedMemberAssignmentTarget staticMem = new ComputedMemberAssignmentTarget(exportsIden, new LiteralStringExpression(specifier.exportedName.orJust(specifier.name.name)));
IdentifierExpression exportVar = makeExportVar(specifier);
AssignmentExpression assignmentExpression = new AssignmentExpression(staticMem, exportVar);
return new ExpressionStatement(assignmentExpression);
}
// e.g., exports.default = x;
static private ExpressionStatement makeExportDefaultStatement(ExportLocalSpecifier specifier) {
IdentifierExpression exportsIden = new IdentifierExpression("exports");
ComputedMemberAssignmentTarget staticMem = new ComputedMemberAssignmentTarget(exportsIden, new LiteralStringExpression("default"));
IdentifierExpression exportVar = makeExportVar(specifier);
AssignmentExpression assignmentExpression = new AssignmentExpression(staticMem, exportVar);
return new ExpressionStatement(assignmentExpression);
}
// e.g., exports.x = __resolver.x
static private ExpressionStatement makeNamedExportStatement(String resolver, ExportFromSpecifier specifier) {
IdentifierExpression exportsIden = new IdentifierExpression("exports");
ComputedMemberAssignmentTarget staticMem = new ComputedMemberAssignmentTarget(exportsIden, new LiteralStringExpression(specifier.exportedName.orJust(specifier.name)));
ComputedMemberExpression exportVar = makeExportVar(resolver, specifier);
AssignmentExpression assignmentExpression = new AssignmentExpression(staticMem, exportVar);
return new ExpressionStatement(assignmentExpression);
}
// e.g., __resolver.x
static private ComputedMemberExpression makeExportVar(String resolver, ExportFromSpecifier specifier) {
String property = specifier.name;
return new ComputedMemberExpression(new IdentifierExpression(resolver), new LiteralStringExpression(property));
}
// e.g., x
static private IdentifierExpression makeExportVar(ExportLocalSpecifier specifier) {
return new IdentifierExpression(specifier.name.name);
}
// e.g., require('lib');
static private ExpressionStatement makeRequireStatement(String moduleSpecifier) {
return new ExpressionStatement(makeRequireCallExpression(moduleSpecifier));
}
// e.g., var __resolver = require('lib');
static private VariableDeclarationStatement makeRequireStatement(String resolver, String moduleSpecifier) {
BindingIdentifier resolverIden = new BindingIdentifier(resolver); // e.g. _resolver = require(...);
CallExpression callExp = makeRequireCallExpression(moduleSpecifier);
ImmutableList declarators =
ImmutableList.of(new VariableDeclarator(resolverIden, Maybe.of(callExp)));
VariableDeclaration declaration = new VariableDeclaration(VariableDeclarationKind.Var, declarators);
return new VariableDeclarationStatement(declaration);
}
// e.g., require('lib')
static private CallExpression makeRequireCallExpression(String moduleSpecifier) {
IdentifierExpression require = new IdentifierExpression("require"); // function require
LiteralStringExpression module = new LiteralStringExpression(moduleSpecifier); // e.g. 'lib.js'
IdentifierExpression secondParam = new IdentifierExpression("module"); // the second parameter to require
ImmutableList requireArguments =
ImmutableList.of(module, secondParam); // parameters to pass to require
return new CallExpression(require, requireArguments);
}
// e.g., d = _resolver.default;
static private VariableDeclarationStatement makeDefaultBindingStatement(String resolver, BindingIdentifier binding) {
IdentifierExpression resolverIden = new IdentifierExpression(resolver);
ComputedMemberExpression staticMem = new ComputedMemberExpression(resolverIden, new LiteralStringExpression("default"));
ImmutableList declarators =
ImmutableList.of(new VariableDeclarator(binding, Maybe.of(staticMem)));
VariableDeclaration declaration = new VariableDeclaration(VariableDeclarationKind.Var, declarators);
return new VariableDeclarationStatement(declaration);
}
// e.g., m = __resolver;
static private VariableDeclarationStatement makeNameSpaceBindingStatement(String resolver, BindingIdentifier binding) {
IdentifierExpression resolverIden = new IdentifierExpression(resolver);
ImmutableList declarators =
ImmutableList.of(new VariableDeclarator(binding, Maybe.of(resolverIden)));
VariableDeclaration declaration = new VariableDeclaration(VariableDeclarationKind.Var, declarators);
return new VariableDeclarationStatement(declaration);
}
// e.g., x = __resolver.y or x = __resolver.x
static private VariableDeclarationStatement makeNamedImportStatement(String resolver, ImportSpecifier specifier) {
IdentifierExpression resolverIden = new IdentifierExpression(resolver);
ComputedMemberExpression staticMem = specifier.name.isJust() ?
new ComputedMemberExpression(resolverIden, new LiteralStringExpression(specifier.name.fromJust())) :
new ComputedMemberExpression(resolverIden, new LiteralStringExpression(specifier.binding.name));
ImmutableList declarators =
ImmutableList.of(new VariableDeclarator(specifier.binding, Maybe.of(staticMem)));
VariableDeclaration declaration = new VariableDeclaration(VariableDeclarationKind.Var, declarators);
return new VariableDeclarationStatement(declaration);
}
// e.g., for(var i in __resolver) exports[k] = __resolver[k];
static private ForInStatement makeEnumerateExports(String resolver) {
BindingIdentifier itemIden = new BindingIdentifier("i");
VariableDeclarator itemDeclarator = new VariableDeclarator(itemIden, Maybe.empty());
VariableDeclaration itemDeclaration =
new VariableDeclaration(VariableDeclarationKind.Var, ImmutableList.of(itemDeclarator));
IdentifierExpression resolverIden = new IdentifierExpression(resolver);
IdentifierExpression itemIdenExp = new IdentifierExpression("i");
IdentifierExpression exportsIden = new IdentifierExpression("exports");
ComputedMemberAssignmentTarget exportsItem = new ComputedMemberAssignmentTarget(exportsIden, itemIdenExp);
ComputedMemberExpression resolverItem = new ComputedMemberExpression(resolverIden, itemIdenExp);
AssignmentExpression assignment = new AssignmentExpression(exportsItem, resolverItem);
return new ForInStatement(itemDeclaration, resolverIden, new ExpressionStatement(assignment));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy