From fa667386d9c5743ef6d6310cfa72465d34a54760 Mon Sep 17 00:00:00 2001 From: dcode Date: Tue, 4 Jun 2019 08:55:22 +0200 Subject: [PATCH] Initial support for default imports/exports, see #98 Does not implement combinations like 'import theDefault, *' yet --- lib/lint/base.json | 3 - src/ast.ts | 19 ++++ src/compiler.ts | 6 +- src/diagnosticMessages.generated.ts | 2 + src/diagnosticMessages.json | 1 + src/extra/ast.ts | 74 +++++++++++++--- src/parser.ts | 97 ++++++++++++++++++--- src/program.ts | 87 ++++++++++++++---- tests/compiler/empty.json | 2 +- tests/compiler/export-default.json | 5 ++ tests/compiler/export-default.optimized.wat | 10 +++ tests/compiler/export-default.ts | 1 + tests/compiler/export-default.untouched.wat | 14 +++ tests/compiler/export.optimized.wat | 1 + tests/compiler/export.ts | 2 + tests/compiler/export.untouched.wat | 1 + tests/compiler/import.ts | 8 ++ tests/compiler/import.untouched.wat | 11 ++- tests/parser/export-default.ts | 6 ++ tests/parser/export-default.ts.fixture.ts | 7 ++ 20 files changed, 310 insertions(+), 47 deletions(-) create mode 100644 tests/compiler/export-default.json create mode 100644 tests/compiler/export-default.optimized.wat create mode 100644 tests/compiler/export-default.ts create mode 100644 tests/compiler/export-default.untouched.wat create mode 100644 tests/parser/export-default.ts create mode 100644 tests/parser/export-default.ts.fixture.ts diff --git a/lib/lint/base.json b/lib/lint/base.json index 74938c6e1b..7c9f781f0c 100644 --- a/lib/lint/base.json +++ b/lib/lint/base.json @@ -39,9 +39,6 @@ "no-debugger": { "severity": "error" }, - "no-default-export": { - "severity": "error" - }, "no-duplicate-super": { "severity": "error" }, diff --git a/src/ast.ts b/src/ast.ts index ca1840920f..c6868ccbfd 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -67,6 +67,7 @@ export enum NodeKind { DO, EMPTY, EXPORT, + EXPORTDEFAULT, EXPORTIMPORT, EXPRESSION, FOR, @@ -701,6 +702,16 @@ export abstract class Node { return stmt; } + static createExportDefaultStatement( + declaration: DeclarationStatement, + range: Range + ): ExportDefaultStatement { + var stmt = new ExportDefaultStatement(); + stmt.declaration = declaration; + stmt.range = range; + return stmt; + } + static createExportImportStatement( name: IdentifierExpression, externalName: IdentifierExpression, @@ -1775,6 +1786,14 @@ export class ExportStatement extends Statement { isDeclare: bool; } +/** Represents an `export default` statement. */ +export class ExportDefaultStatement extends Statement { + kind = NodeKind.EXPORTDEFAULT; + + /** Declaration being exported as default. */ + declaration: DeclarationStatement; +} + /** Represents an expression that is used as a statement. */ export class ExpressionStatement extends Statement { kind = NodeKind.EXPRESSION; diff --git a/src/compiler.ts b/src/compiler.ts index 8f3666ee61..21f0ee1322 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -156,7 +156,8 @@ import { nodeIsConstantValue, findDecorator, - isTypeOmitted + isTypeOmitted, + ExportDefaultStatement } from "./ast"; import { @@ -1619,6 +1620,9 @@ export class Compiler extends DiagnosticEmitter { // === Statements =============================================================================== compileTopLevelStatement(statement: Statement, body: ExpressionRef[]): void { + if (statement.kind == NodeKind.EXPORTDEFAULT) { + statement = (statement).declaration; + } switch (statement.kind) { case NodeKind.CLASSDECLARATION: { let memberStatements = (statement).members; diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index d2dbab9b54..4542f564f1 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -66,6 +66,7 @@ export enum DiagnosticCode { Type_expected = 1110, A_default_clause_cannot_appear_more_than_once_in_a_switch_statement = 1113, Duplicate_label_0 = 1114, + An_export_assignment_cannot_have_modifiers = 1120, Octal_literals_are_not_allowed_in_strict_mode = 1121, Digit_expected = 1124, Hexadecimal_digit_expected = 1125, @@ -204,6 +205,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 1110: return "Type expected."; case 1113: return "A 'default' clause cannot appear more than once in a 'switch' statement."; case 1114: return "Duplicate label '{0}'."; + case 1120: return "An export assignment cannot have modifiers."; case 1121: return "Octal literals are not allowed in strict mode."; case 1124: return "Digit expected."; case 1125: return "Hexadecimal digit expected."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 3502ae4669..673ebe2e1e 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -59,6 +59,7 @@ "Type expected.": 1110, "A 'default' clause cannot appear more than once in a 'switch' statement.": 1113, "Duplicate label '{0}'.": 1114, + "An export assignment cannot have modifiers.": 1120, "Octal literals are not allowed in strict mode.": 1121, "Digit expected.": 1124, "Hexadecimal digit expected.": 1125, diff --git a/src/extra/ast.ts b/src/extra/ast.ts index 04c7ceeba8..0f843af63e 100644 --- a/src/extra/ast.ts +++ b/src/extra/ast.ts @@ -52,6 +52,7 @@ import { EmptyStatement, ExportImportStatement, ExportStatement, + ExportDefaultStatement, ExpressionStatement, ForStatement, IfStatement, @@ -230,6 +231,10 @@ export class ASTBuilder { this.visitExportStatement(node); break; } + case NodeKind.EXPORTDEFAULT: { + this.visitExportDefaultStatement(node); + break; + } case NodeKind.EXPORTIMPORT: { this.visitExportImportStatement(node); break; @@ -851,15 +856,19 @@ export class ASTBuilder { } } - visitClassDeclaration(node: ClassDeclaration): void { + visitClassDeclaration(node: ClassDeclaration, isDefault: bool = false): void { var decorators = node.decorators; if (decorators) { for (let i = 0, k = decorators.length; i < k; ++i) { this.serializeDecorator(decorators[i]); } } - this.serializeExternalModifiers(node); var sb = this.sb; + if (isDefault) { + sb.push("export default "); + } else { + this.serializeExternalModifiers(node); + } if (node.is(CommonFlags.ABSTRACT)) sb.push("abstract "); if (node.name.text.length) { sb.push("class "); @@ -931,9 +940,13 @@ export class ASTBuilder { visitEmptyStatement(node: EmptyStatement): void { } - visitEnumDeclaration(node: EnumDeclaration): void { + visitEnumDeclaration(node: EnumDeclaration, isDefault: bool = false): void { var sb = this.sb; - this.serializeExternalModifiers(node); + if (isDefault) { + sb.push("export default "); + } else { + this.serializeExternalModifiers(node); + } if (node.is(CommonFlags.CONST)) sb.push("const "); sb.push("enum "); this.visitIdentifierExpression(node.name); @@ -1011,6 +1024,33 @@ export class ASTBuilder { sb.push(";"); } + visitExportDefaultStatement(node: ExportDefaultStatement): void { + var declaration = node.declaration; + switch (declaration.kind) { + case NodeKind.ENUMDECLARATION: { + this.visitEnumDeclaration(declaration, true); + break; + } + case NodeKind.FUNCTIONDECLARATION: { + this.visitFunctionDeclaration(declaration, true); + break; + } + case NodeKind.CLASSDECLARATION: { + this.visitClassDeclaration(declaration, true); + break; + } + case NodeKind.INTERFACEDECLARATION: { + this.visitInterfaceDeclaration(declaration, true); + break; + } + case NodeKind.NAMESPACEDECLARATION: { + this.visitNamespaceDeclaration(declaration, true); + break; + } + default: assert(false); + } + } + visitExpressionStatement(node: ExpressionStatement): void { this.visitNode(node.expression); } @@ -1065,7 +1105,7 @@ export class ASTBuilder { this.visitNode(node.statement); } - visitFunctionDeclaration(node: FunctionDeclaration): void { + visitFunctionDeclaration(node: FunctionDeclaration, isDefault: bool = false): void { var sb = this.sb; var decorators = node.decorators; if (decorators) { @@ -1073,8 +1113,12 @@ export class ASTBuilder { this.serializeDecorator(decorators[i]); } } - this.serializeExternalModifiers(node); - this.serializeAccessModifiers(node); + if (isDefault) { + sb.push("export default "); + } else { + this.serializeExternalModifiers(node); + this.serializeAccessModifiers(node); + } if (node.name.text.length) { sb.push("function "); } else { @@ -1230,15 +1274,19 @@ export class ASTBuilder { this.visitTypeNode(node.valueType); } - visitInterfaceDeclaration(node: InterfaceDeclaration): void { + visitInterfaceDeclaration(node: InterfaceDeclaration, isDefault: bool = false): void { var decorators = node.decorators; if (decorators) { for (let i = 0, k = decorators.length; i < k; ++i) { this.serializeDecorator(decorators[i]); } } - this.serializeExternalModifiers(node); var sb = this.sb; + if (isDefault) { + sb.push("export default "); + } else { + this.serializeExternalModifiers(node); + } sb.push("interface "); this.visitIdentifierExpression(node.name); var typeParameters = node.typeParameters; @@ -1284,15 +1332,19 @@ export class ASTBuilder { this.visitFunctionCommon(node); } - visitNamespaceDeclaration(node: NamespaceDeclaration): void { + visitNamespaceDeclaration(node: NamespaceDeclaration, isDefault: bool = false): void { var decorators = node.decorators; if (decorators) { for (let i = 0, k = decorators.length; i < k; ++i) { this.serializeDecorator(decorators[i]); } } - this.serializeExternalModifiers(node); var sb = this.sb; + if (isDefault) { + sb.push("export default "); + } else { + this.serializeExternalModifiers(node); + } sb.push("namespace "); this.visitIdentifierExpression(node.name); var members = node.members; diff --git a/src/parser.ts b/src/parser.ts index 95939e11d2..f5202993bc 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -171,31 +171,34 @@ export class Parser extends DiagnosticEmitter { // check modifiers var exportStart: i32 = 0; var exportEnd: i32 = 0; + var defaultStart: i32 = 0; + var defaultEnd: i32 = 0; if (tn.skip(Token.EXPORT)) { - if (tn.skip(Token.DEFAULT)) { - this.error( - DiagnosticCode.Operation_not_supported, - tn.range() - ); - } if (startPos < 0) startPos = tn.tokenPos; flags |= CommonFlags.EXPORT; exportStart = tn.tokenPos; exportEnd = tn.pos; + if (tn.skip(Token.DEFAULT)) { + defaultStart = tn.tokenPos; + defaultEnd = tn.pos; + } } var declareStart: i32 = 0; var declareEnd: i32 = 0; var contextIsAmbient = namespace != null && namespace.is(CommonFlags.AMBIENT); if (tn.skip(Token.DECLARE)) { - if (startPos < 0) startPos = tn.tokenPos; if (contextIsAmbient) { this.error( DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context, tn.range() ); // recoverable + } else { + if (startPos < 0) startPos = tn.tokenPos; + declareStart = startPos; + declareEnd = tn.pos; + flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT; } - flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT; } else if (contextIsAmbient) { flags |= CommonFlags.AMBIENT; } @@ -297,7 +300,18 @@ export class Parser extends DiagnosticEmitter { // handle plain exports if (flags & CommonFlags.EXPORT) { - statement = this.parseExport(tn, startPos, (flags & CommonFlags.DECLARE) != 0); + if (defaultEnd && tn.skipIdentifier(IdentifierHandling.PREFER)) { + if (declareEnd) { + this.error( + DiagnosticCode.An_export_assignment_cannot_have_modifiers, + tn.range(declareStart, declareEnd) + ); + } + statement = this.parseExportDefaultAlias(tn, startPos, defaultStart, defaultEnd); + defaultStart = defaultEnd = 0; // consume + } else { + statement = this.parseExport(tn, startPos, (flags & CommonFlags.DECLARE) != 0); + } // handle non-declaration statements } else { @@ -330,6 +344,25 @@ export class Parser extends DiagnosticEmitter { ); } } + + // check if this an `export default` declaration + if (defaultEnd && statement !== null) { + switch (statement.kind) { + case NodeKind.ENUMDECLARATION: + case NodeKind.FUNCTIONDECLARATION: + case NodeKind.CLASSDECLARATION: + case NodeKind.INTERFACEDECLARATION: + case NodeKind.NAMESPACEDECLARATION: { + return Node.createExportDefaultStatement(statement, tn.range(startPos, tn.pos)); + } + default: { + this.error( + DiagnosticCode._0_modifier_cannot_be_used_here, + tn.range(defaultStart, defaultEnd), "default" + ); + } + } + } return statement; } @@ -2318,6 +2351,28 @@ export class Parser extends DiagnosticEmitter { return null; } + parseExportDefaultAlias( + tn: Tokenizer, + startPos: i32, + defaultStart: i32, + defaultEnd: i32 + ): ExportStatement { + + // at 'export' 'default': [Known-To-Be-]Identifier + + var name = tn.readIdentifier(); + var range = tn.range(); + var ret = Node.createExportStatement([ + Node.createExportMember( + Node.createIdentifierExpression(name, range), + Node.createIdentifierExpression("default", tn.range(defaultStart, defaultEnd)), + range + ) + ], null, false, tn.range(startPos, tn.pos)); + tn.skip(Token.SEMICOLON); + return ret; + } + parseImport( tn: Tokenizer ): ImportStatement | null { @@ -2330,7 +2385,7 @@ export class Parser extends DiagnosticEmitter { var members: ImportDeclaration[] | null = null; var namespaceName: IdentifierExpression | null = null; var skipFrom = false; - if (tn.skip(Token.OPENBRACE)) { + if (tn.skip(Token.OPENBRACE)) { // import { ... } from "file" members = new Array(); while (!tn.skip(Token.CLOSEBRACE)) { let member = this.parseImportDeclaration(tn); @@ -2348,7 +2403,7 @@ export class Parser extends DiagnosticEmitter { } } } - } else if (tn.skip(Token.ASTERISK)) { + } else if (tn.skip(Token.ASTERISK)) { // import * from "file" if (tn.skip(Token.AS)) { if (tn.skipIdentifier()) { namespaceName = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); @@ -2366,7 +2421,25 @@ export class Parser extends DiagnosticEmitter { ); return null; } - } else { + } else if (tn.skip(Token.IDENTIFIER, IdentifierHandling.PREFER)) { // import Name from "file" + let name = tn.readIdentifier(); + let range = tn.range(); + members = [ + Node.createImportDeclaration( + Node.createIdentifierExpression("default", range), + Node.createIdentifierExpression(name, range), + range + ) + ]; + if (tn.skip(Token.COMMA)) { + // TODO: default + star, default + members + this.error( + DiagnosticCode.Operation_not_supported, + tn.range() + ); + return null; + } + } else { // import "file" skipFrom = true; } diff --git a/src/program.ts b/src/program.ts index 70a4ec96f0..9186d16959 100644 --- a/src/program.ts +++ b/src/program.ts @@ -75,7 +75,8 @@ import { VariableStatement, decoratorNameToKind, - findDecorator + findDecorator, + ExportDefaultStatement } from "./ast"; import { @@ -100,10 +101,6 @@ import { Flow } from "./flow"; -import { - BuiltinSymbols -} from "./builtins"; - /** Represents a yet unresolved `import`. */ class QueuedImport { constructor( @@ -616,6 +613,10 @@ export class Program extends DiagnosticEmitter { this.initializeExports(statement, file, queuedExports, queuedExportsStar); break; } + case NodeKind.EXPORTDEFAULT: { + this.initializeExportDefault(statement, file, queuedExtends, queuedImplements); + break; + } case NodeKind.IMPORT: { this.initializeImports(statement, file, queuedImports, queuedExports); break; @@ -1117,7 +1118,7 @@ export class Program extends DiagnosticEmitter { queuedExtends: ClassPrototype[], /** So far queued `implements` clauses. */ queuedImplements: ClassPrototype[] - ): void { + ): ClassPrototype | null { var name = declaration.name.text; var element = new ClassPrototype( name, @@ -1129,7 +1130,7 @@ export class Program extends DiagnosticEmitter { DecoratorFlags.UNMANAGED ) ); - if (!parent.add(name, element)) return; + if (!parent.add(name, element)) return null; var implementsTypes = declaration.implementsTypes; if (implementsTypes) { @@ -1180,6 +1181,7 @@ export class Program extends DiagnosticEmitter { default: assert(false); // class member expected } } + return element; } /** Initializes a field of a class or interface. */ @@ -1396,7 +1398,7 @@ export class Program extends DiagnosticEmitter { declaration: EnumDeclaration, /** Parent element, usually a file or namespace. */ parent: Element - ): void { + ): Enum | null { var name = declaration.name.text; var element = new Enum( name, @@ -1408,11 +1410,12 @@ export class Program extends DiagnosticEmitter { DecoratorFlags.LAZY ) ); - if (!parent.add(name, element)) return; + if (!parent.add(name, element)) return null; var values = declaration.values; for (let i = 0, k = values.length; i < k; ++i) { this.initializeEnumValue(values[i], element); } + return element; } /** Initializes an enum value. */ @@ -1523,6 +1526,55 @@ export class Program extends DiagnosticEmitter { } } + private initializeExportDefault( + /** The statement to initialize. */ + statement: ExportDefaultStatement, + /** Parent file. */ + parent: File, + /** So far queued `extends` clauses. */ + queuedExtends: Array, + /** So far queued `implements` clauses. */ + queuedImplements: ClassPrototype[] + ): void { + var declaration = statement.declaration; + var element: DeclaredElement | null = null; + switch (declaration.kind) { + case NodeKind.ENUMDECLARATION: { + element = this.initializeEnum(declaration, parent); + break; + } + case NodeKind.FUNCTIONDECLARATION: { + element = this.initializeFunction(declaration, parent); + break; + } + case NodeKind.CLASSDECLARATION: { + element = this.initializeClass(declaration, parent, queuedExtends, queuedImplements); + break; + } + case NodeKind.INTERFACEDECLARATION: { + element = this.initializeInterface(declaration, parent); + break; + } + case NodeKind.NAMESPACEDECLARATION: { + element = this.initializeNamespace(declaration, parent, queuedExtends, queuedImplements); + break; + } + default: assert(false); + } + if (element) { + let exports = parent.exports; + if (!exports) parent.exports = exports = new Map(); + else if (exports.has("default")) { + this.error( + DiagnosticCode.Duplicate_identifier_0, + declaration.name.range, "default" + ) + return; + } + exports.set("default", element); + } + } + /** Initializes an `import` statement. */ private initializeImports( /** The statement to initialize. */ @@ -1531,7 +1583,7 @@ export class Program extends DiagnosticEmitter { parent: File, /** So far queued `import`s. */ queuedImports: QueuedImport[], - /** SO far queued `export`s. */ + /** So far queued `export`s. */ queuedExports: Map> ): void { var declarations = statement.declarations; @@ -1598,7 +1650,7 @@ export class Program extends DiagnosticEmitter { declaration: FunctionDeclaration, /** Parent element, usually a file or namespace. */ parent: Element - ): void { + ): FunctionPrototype | null { var name = declaration.name.text; var validDecorators = DecoratorFlags.UNSAFE | DecoratorFlags.BUILTIN; if (declaration.is(CommonFlags.AMBIENT)) { @@ -1622,7 +1674,7 @@ export class Program extends DiagnosticEmitter { declaration, this.checkDecorators(declaration.decorators, validDecorators) ); - if (!parent.add(name, element)) return; + if (!parent.add(name, element)) return null; if (element.hasDecorator(DecoratorFlags.START)) { if (this.explicitStartFunction) { this.error( @@ -1631,6 +1683,7 @@ export class Program extends DiagnosticEmitter { ); } else this.explicitStartFunction = element; } + return element; } /** Initializes an interface. */ @@ -1639,7 +1692,7 @@ export class Program extends DiagnosticEmitter { declaration: InterfaceDeclaration, /** Parent element, usually a file or namespace. */ parent: Element - ): void { + ): InterfacePrototype | null { var name = declaration.name.text; var element = new InterfacePrototype( name, @@ -1649,7 +1702,7 @@ export class Program extends DiagnosticEmitter { DecoratorFlags.GLOBAL ) ); - if (!parent.add(name, element)) return; + if (!parent.add(name, element)) return null; var memberDeclarations = declaration.members; for (let i = 0, k = memberDeclarations.length; i < k; ++i) { let memberDeclaration = memberDeclarations[i]; @@ -1669,6 +1722,7 @@ export class Program extends DiagnosticEmitter { default: assert(false); // interface member expected } } + return element; } /** Initializes a namespace. */ @@ -1681,7 +1735,7 @@ export class Program extends DiagnosticEmitter { queuedExtends: ClassPrototype[], /** So far queued `implements` clauses. */ queuedImplements: ClassPrototype[] - ): void { + ): Namespace | null { var name = declaration.name.text; var original = new Namespace( name, @@ -1689,7 +1743,7 @@ export class Program extends DiagnosticEmitter { declaration, this.checkDecorators(declaration.decorators, DecoratorFlags.GLOBAL) ); - if (!parent.add(name, original)) return; + if (!parent.add(name, original)) return null; var element = assert(parent.lookupInSelf(name)); // possibly merged var members = declaration.members; for (let i = 0, k = members.length; i < k; ++i) { @@ -1727,6 +1781,7 @@ export class Program extends DiagnosticEmitter { } } if (original != element) copyMembers(original, element); // retain original parent + return element; } /** Initializes a `type` definition. */ diff --git a/tests/compiler/empty.json b/tests/compiler/empty.json index fc976a8b77..8ee35e6e7f 100644 --- a/tests/compiler/empty.json +++ b/tests/compiler/empty.json @@ -1,6 +1,6 @@ { "asc_flags": [ - "--runtime none", + "--runtime half", "--use ASC_RTRACE=1" ] } diff --git a/tests/compiler/export-default.json b/tests/compiler/export-default.json new file mode 100644 index 0000000000..b1da366ff4 --- /dev/null +++ b/tests/compiler/export-default.json @@ -0,0 +1,5 @@ +{ + "asc_flags": [ + "--runtime none" + ] +} \ No newline at end of file diff --git a/tests/compiler/export-default.optimized.wat b/tests/compiler/export-default.optimized.wat new file mode 100644 index 0000000000..fbdbee4154 --- /dev/null +++ b/tests/compiler/export-default.optimized.wat @@ -0,0 +1,10 @@ +(module + (type $FUNCSIG$v (func)) + (memory $0 0) + (export "memory" (memory $0)) + (export "theDefault" (func $export-default/theDefault)) + (export "default" (func $export-default/theDefault)) + (func $export-default/theDefault (; 0 ;) (type $FUNCSIG$v) + nop + ) +) diff --git a/tests/compiler/export-default.ts b/tests/compiler/export-default.ts new file mode 100644 index 0000000000..71b0a13ae6 --- /dev/null +++ b/tests/compiler/export-default.ts @@ -0,0 +1 @@ +export default function theDefault(): void {} diff --git a/tests/compiler/export-default.untouched.wat b/tests/compiler/export-default.untouched.wat new file mode 100644 index 0000000000..f367647567 --- /dev/null +++ b/tests/compiler/export-default.untouched.wat @@ -0,0 +1,14 @@ +(module + (type $FUNCSIG$v (func)) + (memory $0 0) + (table $0 1 funcref) + (elem (i32.const 0) $null) + (export "memory" (memory $0)) + (export "theDefault" (func $export-default/theDefault)) + (export "default" (func $export-default/theDefault)) + (func $export-default/theDefault (; 0 ;) (type $FUNCSIG$v) + nop + ) + (func $null (; 1 ;) (type $FUNCSIG$v) + ) +) diff --git a/tests/compiler/export.optimized.wat b/tests/compiler/export.optimized.wat index 4bb092470c..b5b3be4fa2 100644 --- a/tests/compiler/export.optimized.wat +++ b/tests/compiler/export.optimized.wat @@ -13,6 +13,7 @@ (export "b" (global $export/b)) (export "renamed_c" (global $export/c)) (export "ns.two" (func $export/ns.one)) + (export "default.two" (func $export/ns.one)) (func $export/add (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) local.get $0 local.get $1 diff --git a/tests/compiler/export.ts b/tests/compiler/export.ts index ef50645fb4..b1ac15ac2f 100644 --- a/tests/compiler/export.ts +++ b/tests/compiler/export.ts @@ -28,3 +28,5 @@ export namespace ns { function one(): void {} export function two(): void {} } + +export default ns; diff --git a/tests/compiler/export.untouched.wat b/tests/compiler/export.untouched.wat index 9da32dc4fa..fb06dd5c75 100644 --- a/tests/compiler/export.untouched.wat +++ b/tests/compiler/export.untouched.wat @@ -15,6 +15,7 @@ (export "b" (global $export/b)) (export "renamed_c" (global $export/c)) (export "ns.two" (func $export/ns.two)) + (export "default.two" (func $export/ns.two)) (func $export/add (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) local.get $0 local.get $1 diff --git a/tests/compiler/import.ts b/tests/compiler/import.ts index 35e127c8e7..ca6c73650c 100644 --- a/tests/compiler/import.ts +++ b/tests/compiler/import.ts @@ -21,3 +21,11 @@ other.sub(other.b, other.renamed_c) + other.renamed_mul(other.renamed_c, other.a); other.ns.two(); + +import theDefault from "./export"; + +theDefault.two(); + +import theOtherDefault from "./export-default"; + +theOtherDefault(); diff --git a/tests/compiler/import.untouched.wat b/tests/compiler/import.untouched.wat index 58a39afa2d..e47595b19f 100644 --- a/tests/compiler/import.untouched.wat +++ b/tests/compiler/import.untouched.wat @@ -27,7 +27,10 @@ (func $export/ns.two (; 3 ;) (type $FUNCSIG$v) nop ) - (func $start:import (; 4 ;) (type $FUNCSIG$v) + (func $export-default/theDefault (; 4 ;) (type $FUNCSIG$v) + nop + ) + (func $start:import (; 5 ;) (type $FUNCSIG$v) global.get $export/a global.get $export/b call $export/add @@ -54,10 +57,12 @@ i32.add drop call $export/ns.two + call $export/ns.two + call $export-default/theDefault ) - (func $start (; 5 ;) (type $FUNCSIG$v) + (func $start (; 6 ;) (type $FUNCSIG$v) call $start:import ) - (func $null (; 6 ;) (type $FUNCSIG$v) + (func $null (; 7 ;) (type $FUNCSIG$v) ) ) diff --git a/tests/parser/export-default.ts b/tests/parser/export-default.ts new file mode 100644 index 0000000000..5c00aae7af --- /dev/null +++ b/tests/parser/export-default.ts @@ -0,0 +1,6 @@ +export default function theFunction(): void {} +export default class TheClass {} +// not so ts-y: +export default enum TheEnum {} +export default namespace theNamespace {} +export default something; diff --git a/tests/parser/export-default.ts.fixture.ts b/tests/parser/export-default.ts.fixture.ts new file mode 100644 index 0000000000..d2832910ba --- /dev/null +++ b/tests/parser/export-default.ts.fixture.ts @@ -0,0 +1,7 @@ +export default function theFunction(): void {} +export default class TheClass {} +export default enum TheEnum {} +export default namespace theNamespace {} +export { + something as default +};