@@ -1237,55 +1237,29 @@ export class LuaTransformer {
12371237 return undefined ;
12381238 }
12391239
1240- const bodyWithFieldInitializers : tstl . Statement [ ] = this . transformClassInstanceFields (
1241- classDeclaration ,
1242- instanceFields
1243- ) ;
1244-
1245- // Check for field declarations in constructor
1246- const constructorFieldsDeclarations = statement . parameters . filter ( p => p . modifiers !== undefined ) ;
1247-
1248- // Add in instance field declarations
1249- for ( const declaration of constructorFieldsDeclarations ) {
1250- const declarationName = this . transformIdentifier ( declaration . name as ts . Identifier ) ;
1251- if ( declaration . initializer ) {
1252- // self.declarationName = declarationName or initializer
1253- const assignment = tstl . createAssignmentStatement (
1254- tstl . createTableIndexExpression (
1255- this . createSelfIdentifier ( ) ,
1256- tstl . createStringLiteral ( declarationName . text )
1257- ) ,
1258- tstl . createBinaryExpression (
1259- declarationName ,
1260- this . transformExpression ( declaration . initializer ) ,
1261- tstl . SyntaxKind . OrOperator
1262- )
1263- ) ;
1264- bodyWithFieldInitializers . push ( assignment ) ;
1265- } else {
1266- // self.declarationName = declarationName
1267- const assignment = tstl . createAssignmentStatement (
1268- tstl . createTableIndexExpression (
1269- this . createSelfIdentifier ( ) ,
1270- tstl . createStringLiteral ( declarationName . text )
1271- ) ,
1272- declarationName
1273- ) ;
1274- bodyWithFieldInitializers . push ( assignment ) ;
1275- }
1276- }
1277-
1278- // function className.constructor(self, params) ... end
1240+ // Transform body
1241+ const [ body , scope ] = this . transformFunctionBodyStatements ( statement . body ) ;
12791242
12801243 const [ params , dotsLiteral , restParamName ] = this . transformParameters (
12811244 statement . parameters ,
12821245 this . createSelfIdentifier ( )
12831246 ) ;
12841247
1285- const [ body ] = this . transformFunctionBody ( statement . parameters , statement . body , restParamName ) ;
1248+ // Make sure default parameters are assigned before fields are initialized
1249+ const bodyWithFieldInitializers = this . transformFunctionBodyHeader ( scope , statement . parameters , restParamName ) ;
12861250
1287- // If there are field initializers and the first statement is a super call, hoist the super call to the top
1288- if ( bodyWithFieldInitializers . length > 0 && statement . body && statement . body . statements . length > 0 ) {
1251+ // Check for field declarations in constructor
1252+ const constructorFieldsDeclarations = statement . parameters . filter ( p => p . modifiers !== undefined ) ;
1253+
1254+ const classInstanceFields = this . transformClassInstanceFields ( classDeclaration , instanceFields ) ;
1255+
1256+ // If there are field initializers and the first statement is a super call,
1257+ // move super call between default assignments and initializers
1258+ if (
1259+ ( constructorFieldsDeclarations . length > 0 || classInstanceFields . length > 0 ) &&
1260+ statement . body &&
1261+ statement . body . statements . length > 0
1262+ ) {
12891263 const firstStatement = statement . body . statements [ 0 ] ;
12901264 if (
12911265 ts . isExpressionStatement ( firstStatement ) &&
@@ -1294,11 +1268,27 @@ export class LuaTransformer {
12941268 ) {
12951269 const superCall = body . shift ( ) ;
12961270 if ( superCall ) {
1297- bodyWithFieldInitializers . unshift ( superCall ) ;
1271+ bodyWithFieldInitializers . push ( superCall ) ;
12981272 }
12991273 }
13001274 }
13011275
1276+ // Add in instance field declarations
1277+ for ( const declaration of constructorFieldsDeclarations ) {
1278+ const declarationName = this . transformIdentifier ( declaration . name as ts . Identifier ) ;
1279+ // self.declarationName = declarationName
1280+ const assignment = tstl . createAssignmentStatement (
1281+ tstl . createTableIndexExpression (
1282+ this . createSelfIdentifier ( ) ,
1283+ tstl . createStringLiteral ( declarationName . text )
1284+ ) ,
1285+ declarationName
1286+ ) ;
1287+ bodyWithFieldInitializers . push ( assignment ) ;
1288+ }
1289+
1290+ bodyWithFieldInitializers . push ( ...classInstanceFields ) ;
1291+
13021292 bodyWithFieldInitializers . push ( ...body ) ;
13031293
13041294 const block : tstl . Block = tstl . createBlock ( bodyWithFieldInitializers ) ;
@@ -1490,16 +1480,19 @@ export class LuaTransformer {
14901480 ) ;
14911481 }
14921482
1493- protected transformFunctionBody (
1494- parameters : ts . NodeArray < ts . ParameterDeclaration > ,
1495- body : ts . Block ,
1496- spreadIdentifier ?: tstl . Identifier
1497- ) : [ tstl . Statement [ ] , Scope ] {
1483+ protected transformFunctionBodyStatements ( body : ts . Block ) : [ tstl . Statement [ ] , Scope ] {
14981484 this . pushScope ( ScopeType . Function ) ;
14991485 const bodyStatements = this . performHoisting ( this . transformStatements ( body . statements ) ) ;
15001486 const scope = this . popScope ( ) ;
1487+ return [ bodyStatements , scope ] ;
1488+ }
15011489
1502- const headerStatements = [ ] ;
1490+ protected transformFunctionBodyHeader (
1491+ bodyScope : Scope ,
1492+ parameters : ts . NodeArray < ts . ParameterDeclaration > ,
1493+ spreadIdentifier ?: tstl . Identifier
1494+ ) : tstl . Statement [ ] {
1495+ const headerStatements : tstl . Statement [ ] = [ ] ;
15031496
15041497 // Add default parameters and object binding patterns
15051498 const bindingPatternDeclarations : tstl . Statement [ ] = [ ] ;
@@ -1530,14 +1523,24 @@ export class LuaTransformer {
15301523 }
15311524
15321525 // Push spread operator here
1533- if ( spreadIdentifier && this . isRestParameterReferenced ( spreadIdentifier , scope ) ) {
1526+ if ( spreadIdentifier && this . isRestParameterReferenced ( spreadIdentifier , bodyScope ) ) {
15341527 const spreadTable = this . wrapInTable ( tstl . createDotsLiteral ( ) ) ;
15351528 headerStatements . push ( tstl . createVariableDeclarationStatement ( spreadIdentifier , spreadTable ) ) ;
15361529 }
15371530
15381531 // Binding pattern statements need to be after spread table is declared
15391532 headerStatements . push ( ...bindingPatternDeclarations ) ;
15401533
1534+ return headerStatements ;
1535+ }
1536+
1537+ protected transformFunctionBody (
1538+ parameters : ts . NodeArray < ts . ParameterDeclaration > ,
1539+ body : ts . Block ,
1540+ spreadIdentifier ?: tstl . Identifier
1541+ ) : [ tstl . Statement [ ] , Scope ] {
1542+ const [ bodyStatements , scope ] = this . transformFunctionBodyStatements ( body ) ;
1543+ const headerStatements = this . transformFunctionBodyHeader ( scope , parameters , spreadIdentifier ) ;
15411544 return [ headerStatements . concat ( bodyStatements ) , scope ] ;
15421545 }
15431546
0 commit comments