@@ -271,7 +271,7 @@ module ts {
271
271
} ) ;
272
272
}
273
273
274
- function getAllAccessorDeclarations ( node : ClassDeclaration , accessor : AccessorDeclaration ) {
274
+ function getAllAccessorDeclarations ( declarations : NodeArray < Declaration > , accessor : AccessorDeclaration ) {
275
275
var firstAccessor : AccessorDeclaration ;
276
276
var getAccessor : AccessorDeclaration ;
277
277
var setAccessor : AccessorDeclaration ;
@@ -288,7 +288,7 @@ module ts {
288
288
}
289
289
}
290
290
else {
291
- forEach ( node . members , ( member : Declaration ) => {
291
+ forEach ( declarations , ( member : Declaration ) => {
292
292
if ( ( member . kind === SyntaxKind . GetAccessor || member . kind === SyntaxKind . SetAccessor ) &&
293
293
( < Identifier > member . name ) . text === ( < Identifier > accessor . name ) . text &&
294
294
( member . flags & NodeFlags . Static ) === ( accessor . flags & NodeFlags . Static ) ) {
@@ -1116,8 +1116,8 @@ module ts {
1116
1116
if ( hasDynamicName ( node ) ) {
1117
1117
return ;
1118
1118
}
1119
-
1120
- var accessors = getAllAccessorDeclarations ( < ClassDeclaration > node . parent , node ) ;
1119
+
1120
+ var accessors = getAllAccessorDeclarations ( ( < ClassDeclaration > node . parent ) . members , node ) ;
1121
1121
if ( node === accessors . firstAccessor ) {
1122
1122
emitJsDocComments ( accessors . getAccessor ) ;
1123
1123
emitJsDocComments ( accessors . setAccessor ) ;
@@ -2220,7 +2220,10 @@ module ts {
2220
2220
2221
2221
// This function specifically handles numeric/string literals for enum and accessor 'identifiers'.
2222
2222
// In a sense, it does not actually emit identifiers as much as it declares a name for a specific property.
2223
+ // For example, this is utilized when feeding in a result to Object.defineProperty.
2223
2224
function emitExpressionForPropertyName ( node : DeclarationName ) {
2225
+ Debug . assert ( node . kind !== SyntaxKind . BindingElement ) ;
2226
+
2224
2227
if ( node . kind === SyntaxKind . StringLiteral ) {
2225
2228
emitLiteral ( < LiteralExpression > node ) ;
2226
2229
}
@@ -2417,22 +2420,167 @@ module ts {
2417
2420
}
2418
2421
}
2419
2422
2420
- function emitObjectLiteral ( node : ObjectLiteralExpression ) {
2423
+ function emitObjectLiteralBody ( node : ObjectLiteralExpression , numElements : number ) {
2421
2424
write ( "{" ) ;
2422
- var properties = node . properties ;
2423
- if ( properties . length ) {
2425
+
2426
+ if ( numElements > 0 ) {
2427
+ var properties = node . properties ;
2424
2428
var multiLine = ( node . flags & NodeFlags . MultiLine ) !== 0 ;
2425
2429
if ( ! multiLine ) {
2426
2430
write ( " " ) ;
2427
2431
}
2428
- emitList ( properties , 0 , properties . length , /*multiLine*/ multiLine ,
2432
+ emitList ( properties , 0 , numElements , /*multiLine*/ multiLine ,
2429
2433
/*trailingComma*/ properties . hasTrailingComma && languageVersion >= ScriptTarget . ES5 ) ;
2430
2434
if ( ! multiLine ) {
2431
2435
write ( " " ) ;
2432
2436
}
2433
2437
}
2438
+
2434
2439
write ( "}" ) ;
2435
2440
}
2441
+
2442
+ function emitDownlevelObjectLiteralWithComputedProperties ( node : ObjectLiteralExpression , firstComputedPropertyIndex : number ) {
2443
+ var multiLine = ( node . flags & NodeFlags . MultiLine ) !== 0 ;
2444
+ var properties = node . properties ;
2445
+
2446
+ write ( "(" ) ;
2447
+
2448
+ // For computed properties, we need to create a unique handle to the object
2449
+ // literal so we can modify it without risking internal assignments tainting the object.
2450
+ var tempVar = createTempVariable ( node ) ;
2451
+ recordTempDeclaration ( tempVar ) ;
2452
+
2453
+ // Write out the first non-computed properties
2454
+ // (or all properties if none of them are computed),
2455
+ // then emit the rest through indexing on the temp variable.
2456
+ emit ( tempVar )
2457
+ write ( " = " ) ;
2458
+ emitObjectLiteralBody ( node , firstComputedPropertyIndex ) ;
2459
+
2460
+ if ( multiLine ) {
2461
+ increaseIndent ( ) ;
2462
+ }
2463
+
2464
+ for ( var i = firstComputedPropertyIndex , n = properties . length ; i < n ; i ++ ) {
2465
+ writeSeparator ( ) ;
2466
+
2467
+ var property = properties [ i ] ;
2468
+
2469
+ emitStart ( property )
2470
+ if ( property . kind === SyntaxKind . GetAccessor || property . kind === SyntaxKind . SetAccessor ) {
2471
+ // TODO (drosen): Reconcile with 'emitMemberFunctions'.
2472
+ var accessors = getAllAccessorDeclarations ( node . properties , < AccessorDeclaration > property ) ;
2473
+ write ( "Object.defineProperty(" ) ;
2474
+ emit ( tempVar ) ;
2475
+ write ( ", " ) ;
2476
+ emitStart ( node . name ) ;
2477
+ emitExpressionForPropertyName ( property . name ) ;
2478
+ emitEnd ( property . name ) ;
2479
+ write ( ", {" ) ;
2480
+ increaseIndent ( ) ;
2481
+ if ( accessors . getAccessor ) {
2482
+ writeLine ( )
2483
+ emitLeadingComments ( accessors . getAccessor ) ;
2484
+ write ( "get: " ) ;
2485
+ emitStart ( accessors . getAccessor ) ;
2486
+ write ( "function " ) ;
2487
+ emitSignatureAndBody ( accessors . getAccessor ) ;
2488
+ emitEnd ( accessors . getAccessor ) ;
2489
+ emitTrailingComments ( accessors . getAccessor ) ;
2490
+ write ( "," ) ;
2491
+ }
2492
+ if ( accessors . setAccessor ) {
2493
+ writeLine ( ) ;
2494
+ emitLeadingComments ( accessors . setAccessor ) ;
2495
+ write ( "set: " ) ;
2496
+ emitStart ( accessors . setAccessor ) ;
2497
+ write ( "function " ) ;
2498
+ emitSignatureAndBody ( accessors . setAccessor ) ;
2499
+ emitEnd ( accessors . setAccessor ) ;
2500
+ emitTrailingComments ( accessors . setAccessor ) ;
2501
+ write ( "," ) ;
2502
+ }
2503
+ writeLine ( ) ;
2504
+ write ( "enumerable: true," ) ;
2505
+ writeLine ( ) ;
2506
+ write ( "configurable: true" ) ;
2507
+ decreaseIndent ( ) ;
2508
+ writeSeparator ( ) ;
2509
+ write ( "})" ) ;
2510
+ emitEnd ( property ) ;
2511
+ }
2512
+ else {
2513
+ emitLeadingComments ( property ) ;
2514
+ emitStart ( property . name ) ;
2515
+ emit ( tempVar ) ;
2516
+ emitMemberAccessForPropertyName ( property . name ) ;
2517
+ emitEnd ( property . name ) ;
2518
+
2519
+ write ( " = " ) ;
2520
+
2521
+ if ( property . kind === SyntaxKind . PropertyAssignment ) {
2522
+ emit ( ( < PropertyAssignment > property ) . initializer ) ;
2523
+ }
2524
+ else if ( property . kind === SyntaxKind . ShorthandPropertyAssignment ) {
2525
+ emitExpressionIdentifier ( ( < ShorthandPropertyAssignment > property ) . name ) ;
2526
+ }
2527
+ else if ( property . kind === SyntaxKind . MethodDeclaration ) {
2528
+ emitFunctionDeclaration ( < MethodDeclaration > property ) ;
2529
+ }
2530
+ else {
2531
+ Debug . fail ( "ObjectLiteralElement type not accounted for: " + property . kind ) ;
2532
+ }
2533
+ }
2534
+
2535
+ emitEnd ( property ) ;
2536
+ }
2537
+
2538
+ writeSeparator ( ) ;
2539
+ emit ( tempVar ) ;
2540
+
2541
+ write ( ")" ) ;
2542
+
2543
+ if ( multiLine ) {
2544
+ decreaseIndent ( ) ;
2545
+ }
2546
+
2547
+ function writeSeparator ( ) {
2548
+ if ( multiLine ) {
2549
+ write ( "," ) ;
2550
+ writeLine ( ) ;
2551
+ }
2552
+ else {
2553
+ write ( ", " ) ;
2554
+ }
2555
+ }
2556
+ }
2557
+
2558
+ function emitObjectLiteral ( node : ObjectLiteralExpression ) {
2559
+ if ( languageVersion >= ScriptTarget . ES6 ) {
2560
+ emitObjectLiteralBody ( node , node . properties . length ) ;
2561
+ return ;
2562
+ }
2563
+
2564
+ var properties = node . properties ;
2565
+
2566
+ // Find the first computed property.
2567
+ // Everything until that point can be emitted as part of the initial object literal.
2568
+ var numInitialNonComputedProperties = properties . length ;
2569
+ forEach ( properties , ( property , i ) => {
2570
+ if ( hasDynamicName ( properties [ i ] ) ) {
2571
+ numInitialNonComputedProperties = i ;
2572
+ return true ;
2573
+ }
2574
+ } ) ;
2575
+
2576
+ var hasComputedProperty = numInitialNonComputedProperties !== properties . length ;
2577
+ if ( hasComputedProperty ) {
2578
+ emitDownlevelObjectLiteralWithComputedProperties ( node , numInitialNonComputedProperties ) ;
2579
+ }
2580
+ else {
2581
+ emitObjectLiteralBody ( node , properties . length ) ;
2582
+ }
2583
+ }
2436
2584
2437
2585
function emitComputedPropertyName ( node : ComputedPropertyName ) {
2438
2586
write ( "[" ) ;
@@ -2464,7 +2612,7 @@ module ts {
2464
2612
// export var obj = { y };
2465
2613
// }
2466
2614
// The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version
2467
- if ( languageVersion < ScriptTarget . ES6 || resolver . getExpressionNamePrefix ( node . name ) ) {
2615
+ if ( languageVersion <= ScriptTarget . ES5 || resolver . getExpressionNamePrefix ( node . name ) ) {
2468
2616
// Emit identifier as an identifier
2469
2617
write ( ": " ) ;
2470
2618
// Even though this is stored as identifier treat it as an expression
@@ -3446,6 +3594,7 @@ module ts {
3446
3594
}
3447
3595
3448
3596
function emitMemberAccessForPropertyName ( memberName : DeclarationName ) {
3597
+ // TODO: (jfreeman,drosen): comment on why this is emitNode instead of emit here.
3449
3598
if ( memberName . kind === SyntaxKind . StringLiteral || memberName . kind === SyntaxKind . NumericLiteral ) {
3450
3599
write ( "[" ) ;
3451
3600
emitNode ( memberName ) ;
@@ -3495,13 +3644,14 @@ module ts {
3495
3644
emitLeadingComments ( member ) ;
3496
3645
emitStart ( member ) ;
3497
3646
emitStart ( ( < MethodDeclaration > member ) . name ) ;
3498
- emitNode ( node . name ) ;
3647
+ emitNode ( node . name ) ; // TODO (shkamat,drosen): comment for why emitNode instead of emit.
3499
3648
if ( ! ( member . flags & NodeFlags . Static ) ) {
3500
3649
write ( ".prototype" ) ;
3501
3650
}
3502
3651
emitMemberAccessForPropertyName ( ( < MethodDeclaration > member ) . name ) ;
3503
3652
emitEnd ( ( < MethodDeclaration > member ) . name ) ;
3504
3653
write ( " = " ) ;
3654
+ // TODO (drosen): Should we performing emitStart twice on emitStart(member)?
3505
3655
emitStart ( member ) ;
3506
3656
emitFunctionDeclaration ( < MethodDeclaration > member ) ;
3507
3657
emitEnd ( member ) ;
@@ -3510,7 +3660,7 @@ module ts {
3510
3660
emitTrailingComments ( member ) ;
3511
3661
}
3512
3662
else if ( member . kind === SyntaxKind . GetAccessor || member . kind === SyntaxKind . SetAccessor ) {
3513
- var accessors = getAllAccessorDeclarations ( node , < AccessorDeclaration > member ) ;
3663
+ var accessors = getAllAccessorDeclarations ( node . members , < AccessorDeclaration > member ) ;
3514
3664
if ( member === accessors . firstAccessor ) {
3515
3665
writeLine ( ) ;
3516
3666
emitStart ( member ) ;
@@ -3521,6 +3671,7 @@ module ts {
3521
3671
write ( ".prototype" ) ;
3522
3672
}
3523
3673
write ( ", " ) ;
3674
+ // TODO: Shouldn't emitStart on name occur *here*?
3524
3675
emitExpressionForPropertyName ( ( < AccessorDeclaration > member ) . name ) ;
3525
3676
emitEnd ( ( < AccessorDeclaration > member ) . name ) ;
3526
3677
write ( ", {" ) ;
0 commit comments