Mangling externally imported names by using aliasing

This commit is contained in:
Fábio Santos
2016-02-27 12:01:16 +00:00
committed by Richard van Velzen
parent 59e1601fb8
commit 86b5248837
5 changed files with 44 additions and 2 deletions

View File

@@ -707,6 +707,12 @@ var AST_NameImport = DEFNODE("NameImport", "foreign_name name", {
$propdoc: { $propdoc: {
foreign_name: "[AST_SymbolImportForeign] The name being imported (as specified in the module)", foreign_name: "[AST_SymbolImportForeign] The name being imported (as specified in the module)",
name: "[AST_SymbolImport] The name as it becomes available to this module." name: "[AST_SymbolImport] The name as it becomes available to this module."
},
_walk: function (visitor) {
return visitor._visit(this, function() {
this.foreign_name._walk(visitor);
this.name._walk(visitor);
});
} }
}) })
@@ -722,6 +728,11 @@ var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", {
if (this.imported_name) { if (this.imported_name) {
this.imported_name._walk(visitor); this.imported_name._walk(visitor);
} }
if (this.imported_names) {
this.imported_names.forEach(function (name_import) {
name_import._walk(visitor);
});
}
this.module_name._walk(visitor); this.module_name._walk(visitor);
}); });
} }

View File

@@ -1070,8 +1070,12 @@ function OutputStream(options) {
}); });
DEFPRINT(AST_NameImport, function(self, output) { DEFPRINT(AST_NameImport, function(self, output) {
if (self.foreign_name) { var definition = self.name.definition();
self.foreign_name.print(output); var names_are_different =
(definition && definition.mangled_name || self.name.name) !==
self.foreign_name.name;
if (names_are_different) {
output.print(self.foreign_name.name);
output.space(); output.space();
output.print("as"); output.print("as");
output.space(); output.space();

View File

@@ -1667,6 +1667,14 @@ function parse($TEXT, options) {
} }
name = as_symbol(AST_SymbolImport); name = as_symbol(AST_SymbolImport);
if (foreign_name === undefined) {
foreign_name = new AST_SymbolImportForeign({
name: name.name,
start: name.start,
end: name.end,
});
}
return new AST_NameImport({ return new AST_NameImport({
start: start, start: start,
foreign_name: foreign_name, foreign_name: foreign_name,

View File

@@ -171,6 +171,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
else if (node instanceof AST_SymbolClass) { else if (node instanceof AST_SymbolClass) {
defun.def_variable(node); defun.def_variable(node);
} }
else if (node instanceof AST_SymbolImport) {
scope.def_variable(node);
}
else if (node instanceof AST_SymbolDefClass) { else if (node instanceof AST_SymbolDefClass) {
// This deals with the name of the class being available // This deals with the name of the class being available
// inside the class. // inside the class.
@@ -302,6 +305,12 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol){
this.variables.set(symbol.name, def); this.variables.set(symbol.name, def);
def.object_destructuring_arg = symbol.object_destructuring_arg; def.object_destructuring_arg = symbol.object_destructuring_arg;
def.global = !this.parent_scope; def.global = !this.parent_scope;
if (symbol instanceof AST_SymbolImport) {
// Imports are not global
def.global = false;
// TODO The real fix comes with block scoping being first class in uglifyJS,
// enabling import definitions to behave like module-level let declarations
}
} else { } else {
def = this.variables.get(symbol.name); def = this.variables.get(symbol.name);
def.orig.push(symbol); def.orig.push(symbol);

View File

@@ -320,11 +320,21 @@ import_statement_mangling: {
mangle = { }; mangle = { };
input: { input: {
import Foo from "foo"; import Foo from "foo";
import Bar, {Food} from "lel";
import {What as Whatever} from "lel";
Foo(); Foo();
Bar();
Food();
Whatever();
} }
expect: { expect: {
import a from "foo"; import a from "foo";
import b, {Food as c} from "lel";
import {What as d} from "lel";
a(); a();
b();
c();
d();
} }
} }