Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

emit top level classes as class expressions when target=ES6 and module=System #7559

Merged
merged 1 commit into from
Mar 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5278,9 +5278,11 @@ const _super = (function (geti, seti) {

function emitClassLikeDeclarationForES6AndHigher(node: ClassLikeDeclaration) {
let decoratedClassAlias: string;
const thisNodeIsDecorated = nodeIsDecorated(node);
const isHoistedDeclarationInSystemModule = shouldHoistDeclarationInSystemJsModule(node);
const isDecorated = nodeIsDecorated(node);
const rewriteAsClassExpression = isDecorated || isHoistedDeclarationInSystemModule;
if (node.kind === SyntaxKind.ClassDeclaration) {
if (thisNodeIsDecorated) {
if (rewriteAsClassExpression) {
// When we emit an ES6 class that has a class decorator, we must tailor the
// emit to certain specific cases.
//
Expand Down Expand Up @@ -5361,7 +5363,10 @@ const _super = (function (geti, seti) {
// [Example 4]
//

if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithBodyScopedClassBinding) {
// NOTE: we reuse the same rewriting logic for cases when targeting ES6 and module kind is System.
// Because of hoisting top level class declaration need to be emitted as class expressions.
// Double bind case is only required if node is decorated.
if (isDecorated && resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithBodyScopedClassBinding) {
decoratedClassAlias = unescapeIdentifier(makeUniqueName(node.name ? node.name.text : "default"));
decoratedClassAliases[getNodeId(node)] = decoratedClassAlias;
write(`let ${decoratedClassAlias};`);
Expand All @@ -5372,7 +5377,9 @@ const _super = (function (geti, seti) {
write("export ");
}

write("let ");
if (!isHoistedDeclarationInSystemModule) {
write("let ");
}
emitDeclarationName(node);
if (decoratedClassAlias !== undefined) {
write(` = ${decoratedClassAlias}`);
Expand Down Expand Up @@ -5416,7 +5423,7 @@ const _super = (function (geti, seti) {
// emit name if
// - node has a name
// - this is default export with static initializers
if (node.name || (node.flags & NodeFlags.Default && (staticProperties.length > 0 || modulekind !== ModuleKind.ES6) && !thisNodeIsDecorated)) {
if (node.name || (node.flags & NodeFlags.Default && (staticProperties.length > 0 || modulekind !== ModuleKind.ES6) && !rewriteAsClassExpression)) {
write(" ");
emitDeclarationName(node);
}
Expand All @@ -5436,7 +5443,7 @@ const _super = (function (geti, seti) {
writeLine();
emitToken(SyntaxKind.CloseBraceToken, node.members.end);

if (thisNodeIsDecorated) {
if (rewriteAsClassExpression) {
decoratedClassAliases[getNodeId(node)] = undefined;
write(";");
}
Expand Down Expand Up @@ -5476,7 +5483,7 @@ const _super = (function (geti, seti) {
// module), export it
if (node.flags & NodeFlags.Default) {
// if this is a top level default export of decorated class, write the export after the declaration.
if (thisNodeIsDecorated) {
if (isDecorated) {
writeLine();
write("export default ");
emitDeclarationName(node);
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/anonymousDefaultExportsSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ System.register([], function(exports_1, context_1) {
return {
setters:[],
execute: function() {
class default_1 {
}
default_1 = class {
};
exports_1("default", default_1);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ System.register([], function(exports_1, context_1) {
return {
setters:[],
execute: function() {
let Foo = class Foo {
Foo = class Foo {
};
Foo = __decorate([
decorator
Expand All @@ -49,7 +49,7 @@ System.register([], function(exports_1, context_1) {
return {
setters:[],
execute: function() {
let default_1 = class {
default_1 = class {
};
default_1 = __decorate([
decorator
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/defaultExportsGetExportedSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ System.register([], function(exports_1, context_1) {
return {
setters:[],
execute: function() {
class Foo {
}
Foo = class Foo {
};
exports_1("default", Foo);
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/outFilerootDirModuleNamesSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ System.register("a", ["b"], function(exports_2, context_2) {
b_1 = b_1_1;
}],
execute: function() {
class Foo {
}
Foo = class Foo {
};
exports_2("default", Foo);
b_1.default();
}
Expand Down
42 changes: 42 additions & 0 deletions tests/baselines/reference/systemModuleTargetES6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//// [systemModuleTargetES6.ts]
export class MyClass { }
export class MyClass2 {
static value = 42;
static getInstance() { return MyClass2.value; }
}

export function myFunction() {
return new MyClass();
}

export function myFunction2() {
return new MyClass2();
}

//// [systemModuleTargetES6.js]
System.register([], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var MyClass, MyClass2;
function myFunction() {
return new MyClass();
}
exports_1("myFunction", myFunction);
function myFunction2() {
return new MyClass2();
}
exports_1("myFunction2", myFunction2);
return {
setters:[],
execute: function() {
MyClass = class MyClass {
};
exports_1("MyClass", MyClass);
MyClass2 = class MyClass2 {
static getInstance() { return MyClass2.value; }
};
MyClass2.value = 42;
exports_1("MyClass2", MyClass2);
}
}
});
30 changes: 30 additions & 0 deletions tests/baselines/reference/systemModuleTargetES6.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
=== tests/cases/compiler/systemModuleTargetES6.ts ===
export class MyClass { }
>MyClass : Symbol(MyClass, Decl(systemModuleTargetES6.ts, 0, 0))

export class MyClass2 {
>MyClass2 : Symbol(MyClass2, Decl(systemModuleTargetES6.ts, 0, 24))

static value = 42;
>value : Symbol(MyClass2.value, Decl(systemModuleTargetES6.ts, 1, 23))

static getInstance() { return MyClass2.value; }
>getInstance : Symbol(MyClass2.getInstance, Decl(systemModuleTargetES6.ts, 2, 22))
>MyClass2.value : Symbol(MyClass2.value, Decl(systemModuleTargetES6.ts, 1, 23))
>MyClass2 : Symbol(MyClass2, Decl(systemModuleTargetES6.ts, 0, 24))
>value : Symbol(MyClass2.value, Decl(systemModuleTargetES6.ts, 1, 23))
}

export function myFunction() {
>myFunction : Symbol(myFunction, Decl(systemModuleTargetES6.ts, 4, 1))

return new MyClass();
>MyClass : Symbol(MyClass, Decl(systemModuleTargetES6.ts, 0, 0))
}

export function myFunction2() {
>myFunction2 : Symbol(myFunction2, Decl(systemModuleTargetES6.ts, 8, 1))

return new MyClass2();
>MyClass2 : Symbol(MyClass2, Decl(systemModuleTargetES6.ts, 0, 24))
}
33 changes: 33 additions & 0 deletions tests/baselines/reference/systemModuleTargetES6.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
=== tests/cases/compiler/systemModuleTargetES6.ts ===
export class MyClass { }
>MyClass : MyClass

export class MyClass2 {
>MyClass2 : MyClass2

static value = 42;
>value : number
>42 : number

static getInstance() { return MyClass2.value; }
>getInstance : () => number
>MyClass2.value : number
>MyClass2 : typeof MyClass2
>value : number
}

export function myFunction() {
>myFunction : () => MyClass

return new MyClass();
>new MyClass() : MyClass
>MyClass : typeof MyClass
}

export function myFunction2() {
>myFunction2 : () => MyClass2

return new MyClass2();
>new MyClass2() : MyClass2
>MyClass2 : typeof MyClass2
}
15 changes: 15 additions & 0 deletions tests/cases/compiler/systemModuleTargetES6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// @target: ES6
// @module: System
export class MyClass { }
export class MyClass2 {
static value = 42;
static getInstance() { return MyClass2.value; }
}

export function myFunction() {
return new MyClass();
}

export function myFunction2() {
return new MyClass2();
}