Skip to content

Commit 7562a34

Browse files
Add support for emitting static properties in class expressions in ES6.
1 parent 105936f commit 7562a34

File tree

4 files changed

+81
-12
lines changed

4 files changed

+81
-12
lines changed

src/compiler/emitter.ts

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3216,22 +3216,30 @@ module ts {
32163216
}
32173217
}
32183218

3219-
function emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration) {
3219+
function emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver?: Identifier, isExpression?: boolean) {
32203220
writeLine();
32213221
emitLeadingComments(property);
32223222
emitStart(property);
32233223
emitStart(property.name);
3224-
if (property.flags & NodeFlags.Static) {
3225-
emitDeclarationName(node);
3224+
if (receiver) {
3225+
emit(receiver);
32263226
}
32273227
else {
3228-
write("this");
3228+
if (property.flags & NodeFlags.Static) {
3229+
emitDeclarationName(node);
3230+
}
3231+
else {
3232+
write("this");
3233+
}
32293234
}
32303235
emitMemberAccessForPropertyName(property.name);
32313236
emitEnd(property.name);
32323237
write(" = ");
32333238
emit(property.initializer);
3234-
write(";");
3239+
if (!isExpression) {
3240+
write(";");
3241+
}
3242+
32353243
emitEnd(property);
32363244
emitTrailingComments(property);
32373245
}
@@ -3351,6 +3359,14 @@ module ts {
33513359
tempVariables = undefined;
33523360
tempParameters = undefined;
33533361

3362+
emitConstructorWorker(node, baseTypeElement);
3363+
3364+
tempFlags = saveTempFlags;
3365+
tempVariables = saveTempVariables;
3366+
tempParameters = saveTempParameters;
3367+
}
3368+
3369+
function emitConstructorWorker(node: ClassLikeDeclaration, baseTypeElement: HeritageClauseElement) {
33543370
// Check if we have property assignment inside class declaration.
33553371
// If there is property assignment, we need to emit constructor whether users define it or not
33563372
// If there is no property assignment, we can omit constructor if users do not define it
@@ -3458,10 +3474,6 @@ module ts {
34583474
if (ctor) {
34593475
emitTrailingComments(ctor);
34603476
}
3461-
3462-
tempFlags = saveTempFlags;
3463-
tempVariables = saveTempVariables;
3464-
tempParameters = saveTempParameters;
34653477
}
34663478

34673479
function emitClassExpression(node: ClassExpression) {
@@ -3553,6 +3565,29 @@ module ts {
35533565
}
35543566
}
35553567

3568+
// If the class has static properties, and it's a class expression, then we'll need
3569+
// to specialize the emit a bit. for a class expression of the form:
3570+
//
3571+
// class C { static a = 1; static b = 2; ... }
3572+
//
3573+
// We'll emit:
3574+
//
3575+
// (_temp = class C { ... }, _temp.a = 1, _temp.b = 2, _temp)
3576+
//
3577+
// This keeps the expression as an expression, while ensuring that the static parts
3578+
// of it have been initialized by the time it is used.
3579+
let staticProperties = getInitializedProperties(node, /*static:*/ true);
3580+
let isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression;
3581+
let tempVariable: Identifier;
3582+
3583+
if (isClassExpressionWithStaticProperties) {
3584+
tempVariable = createAndRecordTempVariable(TempFlags.Auto);
3585+
write("(");
3586+
increaseIndent();
3587+
emit(tempVariable);
3588+
write(" = ")
3589+
}
3590+
35563591
write("class");
35573592

35583593
// check if this is an "export default class" as it may not have a name. Do not emit the name if the class is decorated.
@@ -3603,9 +3638,24 @@ module ts {
36033638
// From ES6 specification:
36043639
// HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
36053640
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
3606-
writeLine();
3607-
emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ true));
3608-
emitDecoratorsOfClass(node);
3641+
3642+
if (isClassExpressionWithStaticProperties) {
3643+
for (var property of staticProperties) {
3644+
write(",");
3645+
writeLine();
3646+
emitPropertyDeclaration(node, property, /*receiver:*/ tempVariable, /*isExpression:*/ true);
3647+
}
3648+
write(",");
3649+
writeLine();
3650+
emit(tempVariable);
3651+
decreaseIndent();
3652+
write(")");
3653+
}
3654+
else {
3655+
writeLine();
3656+
emitPropertyDeclarations(node, staticProperties);
3657+
emitDecoratorsOfClass(node);
3658+
}
36093659

36103660
// If this is an exported class, but not on the top level (i.e. on an internal
36113661
// module), export it
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
tests/cases/compiler/classExpressionWithStaticPropertiesES61.ts(1,15): error TS9003: 'class' expressions are not currently supported.
2+
3+
4+
==== tests/cases/compiler/classExpressionWithStaticPropertiesES61.ts (1 errors) ====
5+
var v = class C { static a = 1; static b = 2 };
6+
~
7+
!!! error TS9003: 'class' expressions are not currently supported.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//// [classExpressionWithStaticPropertiesES61.ts]
2+
var v = class C { static a = 1; static b = 2 };
3+
4+
//// [classExpressionWithStaticPropertiesES61.js]
5+
var v = (_a = class C {
6+
},
7+
_a.a = 1,
8+
_a.b = 2,
9+
_a);
10+
var _a;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
//@target: es6
2+
var v = class C { static a = 1; static b = 2 };

0 commit comments

Comments
 (0)