From ce84a706a3eab73589d0723bf8e03f8d4cbd776e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Santos?= Date: Sat, 27 Feb 2016 12:24:18 +0000 Subject: [PATCH] Implement the export statement --- lib/ast.js | 9 +++++++++ lib/output.js | 15 +++++++++++++++ lib/parse.js | 35 ++++++++++++++++++++++++++++++++++- test/compress/harmony.js | 12 ++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/lib/ast.js b/lib/ast.js index 6a814e35..e6867205 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -738,6 +738,15 @@ var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", { } }); +var AST_Export = DEFNODE("Export", "exported_definition exported_value is_default", { + $documentation: "An `export` statement", + $propdoc: { + exported_definition: "[AST_Defun|AST_Definitions|AST_DefClass?] An exported definition", + exported_value: "[AST_Node?] An exported value", + is_default: "[Boolean] Whether this is the default exported value of this module" + }, +}, AST_Statement); + var AST_VarDef = DEFNODE("VarDef", "name value", { $documentation: "A variable declaration; only appears in a AST_Definitions node", $propdoc: { diff --git a/lib/output.js b/lib/output.js index e755ec04..0dd5dcb9 100644 --- a/lib/output.js +++ b/lib/output.js @@ -1085,6 +1085,21 @@ function OutputStream(options) { } }); + DEFPRINT(AST_Export, function(self, output) { + output.print("export"); + output.space(); + if (self.is_default) { + output.print("default"); + output.space(); + } + if (self.exported_value) { + self.exported_value.print(output); + } else if (self.exported_definition) { + self.exported_definition.print(output); + } + output.semicolon(); + }); + 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 134b3f19..5463576d 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -44,7 +44,7 @@ "use strict"; -var KEYWORDS = 'break case catch class const continue debugger default delete do else extends finally for function if in instanceof new return switch throw try typeof var let void while with import'; +var KEYWORDS = 'break case catch class const continue debugger default delete do else extends finally for function if in instanceof new return switch throw try typeof var let void while with import export'; var KEYWORDS_ATOM = 'false null true'; var RESERVED_WORDS = 'abstract boolean byte char double enum export final float goto implements int interface long native package private protected public short static super synchronized this throws transient volatile yield' + " " + KEYWORDS_ATOM + " " + KEYWORDS; @@ -912,6 +912,9 @@ function parse($TEXT, options) { case "import": return tmp = import_(), semicolon(), tmp; + case "export": + return tmp = export_(), semicolon(), tmp; + default: unexpected(); } @@ -1683,6 +1686,36 @@ function parse($TEXT, options) { }) } + function export_() { + var start = S.token; + var is_default; + var exported_value; + var exported_definition; + + if (is("keyword", "default")) { + is_default = true; + next(); + } + + var is_definition = + is("keyword", "var") || is("keyword", "let") || is("keyword", "const") || + is("keyword", "class") || is("keyword", "function"); + + if (is_definition) { + exported_definition = statement(); + } else { + exported_value = expression(); + } + + return new AST_Export({ + start: start, + is_default: is_default, + exported_value: exported_value, + exported_definition: exported_definition, + end: prev(), + }); + } + function as_property_name() { var tmp = S.token; next(); diff --git a/test/compress/harmony.js b/test/compress/harmony.js index 5ef1416e..d27d903b 100644 --- a/test/compress/harmony.js +++ b/test/compress/harmony.js @@ -316,6 +316,18 @@ import_statement: { 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\";" } +export_statement: { + input: { + export default 1; + export var foo = 4; + export let foo = 6; + export const foo = 6; + export function foo() {}; + export class foo { }; + } + expect_exact: "export default 1;export var foo=4;export let foo=6;export const foo=6;export function foo(){};export class foo{};" +} + import_statement_mangling: { mangle = { }; input: {