From 59e1601fb8fbcf03a2e26ce7eea72afac86ee880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Santos?= Date: Fri, 26 Feb 2016 21:12:19 +0000 Subject: [PATCH] importing names in the modules, not just default imports --- lib/ast.js | 15 ++++++++++++++- lib/output.js | 31 +++++++++++++++++++++++++++++++ lib/parse.js | 40 ++++++++++++++++++++++++++++++++++++++++ test/compress/harmony.js | 5 ++++- 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/lib/ast.js b/lib/ast.js index 3457c134..768bfc78 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -702,10 +702,19 @@ var AST_Const = DEFNODE("Const", null, { $documentation: "A `const` statement" }, AST_Definitions); -var AST_Import = DEFNODE("Import", "imported_name module_name", { +var AST_NameImport = DEFNODE("NameImport", "foreign_name name", { + $documentation: "The part of the import statement that imports names from a module.", + $propdoc: { + 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." + } +}) + +var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", { $documentation: "An `import` statement", $propdoc: { imported_name: "[AST_SymbolImport] The name of the variable holding the module's default export.", + imported_names: "[AST_NameImport*] The names of non-default imported variables", module_name: "[AST_String] String literal describing where this module came from", }, _walk: function(visitor) { @@ -1085,6 +1094,10 @@ var AST_SymbolImport = DEFNODE("SymbolImport", null, { $documentation: "Symbol refering to an imported name", }, AST_SymbolDeclaration); +var AST_SymbolImportForeign = DEFNODE("SymbolImportForeign", null, { + $documentation: "A symbol imported from a module, but it is defined in the other module, and its real name is irrelevant for this module's purposes", +}, AST_Symbol); + var AST_Label = DEFNODE("Label", "references", { $documentation: "Symbol naming a label (declaration)", $propdoc: { diff --git a/lib/output.js b/lib/output.js index 52747603..a9c78bbf 100644 --- a/lib/output.js +++ b/lib/output.js @@ -1042,6 +1042,25 @@ function OutputStream(options) { output.space(); if (self.imported_name) { self.imported_name.print(output); + } + if (self.imported_name && self.imported_names) { + output.print(","); + output.space(); + } + if (self.imported_names) { + output.print("{"); + self.imported_names.forEach(function(name_import, i) { + output.space(); + name_import.print(output); + if (i < self.imported_names.length - 1) { + output.print(","); + output.space(); + } + }); + output.space(); + output.print("}"); + } + if (self.imported_name || self.imported_names) { output.space(); output.print("from") output.space(); @@ -1050,6 +1069,18 @@ function OutputStream(options) { output.semicolon(); }); + DEFPRINT(AST_NameImport, function(self, output) { + if (self.foreign_name) { + self.foreign_name.print(output); + output.space(); + output.print("as"); + output.space(); + self.name.print(output); + } else { + self.name.print(output); + } + }); + function parenthesize_for_noin(node, output, noin) { if (!noin) node.print(output); else try { diff --git a/lib/parse.js b/lib/parse.js index 4e94f589..fd51eda2 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1613,8 +1613,28 @@ function parse($TEXT, options) { function import_() { var start = prev(); var imported_name; + var imported_names; if (is("name")) { imported_name = as_symbol(AST_SymbolImport); + } + + if (is("punc", ",")) { + next(); + } + + if (is("punc", "{")) { + next(); + imported_names = []; + while (!is("punc", "}")) { + imported_names.push(import_name()); + if (is("punc", ",")) { + next(); + } + } + next(); + } + + if (imported_names || imported_name) { expect_token("name", "from"); } var mod_str = S.token; @@ -1625,6 +1645,7 @@ function parse($TEXT, options) { return new AST_Import({ start: start, imported_name: imported_name, + imported_names: imported_names, module_name: new AST_String({ start: mod_str, value: mod_str.value, @@ -1635,6 +1656,25 @@ function parse($TEXT, options) { }); } + function import_name() { + var start = S.token; + var foreign_name; + var name; + + if (peek().value === "as" && peek().type === "name") { + foreign_name = as_symbol(AST_SymbolImportForeign); + next(); // The "as" word + } + name = as_symbol(AST_SymbolImport); + + return new AST_NameImport({ + start: start, + foreign_name: foreign_name, + name: name, + end: prev(), + }) + } + function as_property_name() { var tmp = S.token; next(); diff --git a/test/compress/harmony.js b/test/compress/harmony.js index dc1c2e4f..59c6238a 100644 --- a/test/compress/harmony.js +++ b/test/compress/harmony.js @@ -309,8 +309,11 @@ import_statement: { input: { import "mod-name"; import Foo from "bar"; + import { Bar, Baz } from 'lel'; + import Bar, { Foo } from 'lel'; + import { Bar as kex, Baz as food } from 'lel'; } - expect_exact: "import\"mod-name\";import Foo from\"bar\";" + expect_exact: "import\"mod-name\";import Foo from\"bar\";import{Bar,Baz}from\"lel\";import Bar,{Foo}from\"lel\";import{Bar as kex,Baz as food}from\"lel\";" } import_statement_mangling: {