@@ -304,25 +304,31 @@ namespace ts {
304
304
if ( properties . length !== 1 ) {
305
305
// For anything but a single element destructuring we need to generate a temporary
306
306
// to ensure value is evaluated exactly once.
307
- // When doing so we want to hightlight the passed in source map node since thats the one needing this temp assignment
307
+ // When doing so we want to highlight the passed in source map node since that's the one needing this temp assignment
308
308
value = ensureIdentifier ( value , /*reuseIdentifierExpressions*/ true , location , emitTempVariableAssignment ) ;
309
309
}
310
310
311
311
let bindingElements : ObjectLiteralElementLike [ ] = [ ] ;
312
+ let computedTempVariables : Expression [ ] ;
312
313
for ( let i = 0 ; i < properties . length ; i ++ ) {
313
314
const p = properties [ i ] ;
314
315
if ( p . kind === SyntaxKind . PropertyAssignment || p . kind === SyntaxKind . ShorthandPropertyAssignment ) {
315
316
if ( ! transformRest ||
316
317
p . transformFlags & TransformFlags . ContainsSpreadExpression ||
317
- ( p . kind === SyntaxKind . PropertyAssignment && p . initializer . transformFlags & TransformFlags . ContainsSpreadExpression ) ) {
318
+ ( p . kind === SyntaxKind . PropertyAssignment && p . initializer . transformFlags & TransformFlags . ContainsSpreadExpression ) ||
319
+ isComputedPropertyName ( p . name ) ) {
318
320
if ( bindingElements . length ) {
319
321
emitRestAssignment ( bindingElements , value , location , target ) ;
320
322
bindingElements = [ ] ;
321
323
}
322
324
const propName = < Identifier | LiteralExpression > ( < PropertyAssignment > p ) . name ;
323
325
const bindingTarget = p . kind === SyntaxKind . ShorthandPropertyAssignment ? < ShorthandPropertyAssignment > p : ( < PropertyAssignment > p ) . initializer || propName ;
324
326
// Assignment for bindingTarget = value.propName should highlight whole property, hence use p as source map node
325
- emitDestructuringAssignment ( bindingTarget , createDestructuringPropertyAccess ( value , propName ) , p ) ;
327
+ const propAccess = createDestructuringPropertyAccess ( value , propName ) ;
328
+ if ( isComputedPropertyName ( propName ) ) {
329
+ computedTempVariables = append ( computedTempVariables , ( propAccess as ElementAccessExpression ) . argumentExpression ) ;
330
+ }
331
+ emitDestructuringAssignment ( bindingTarget , propAccess , p ) ;
326
332
}
327
333
else {
328
334
bindingElements . push ( p ) ;
@@ -336,7 +342,7 @@ namespace ts {
336
342
bindingElements = [ ] ;
337
343
}
338
344
const propName = ( p as SpreadAssignment ) . expression as Identifier ;
339
- const restCall = createRestCall ( value , target . properties , p => p . name , target ) ;
345
+ const restCall = createRestCall ( value , target . properties , p => p . name , target , computedTempVariables ) ;
340
346
emitDestructuringAssignment ( propName , restCall , p ) ;
341
347
}
342
348
}
@@ -413,17 +419,28 @@ namespace ts {
413
419
414
420
/** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
415
421
* `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`*/
416
- function createRestCall < T extends Node > ( value : Expression , elements : T [ ] , getPropertyName : ( element : T ) => PropertyName , location : TextRange ) : Expression {
417
- const propertyNames : LiteralExpression [ ] = [ ] ;
422
+ function createRestCall < T extends Node > ( value : Expression , elements : T [ ] , getPropertyName : ( element : T ) => PropertyName , location : TextRange , computedTempVariables : Expression [ ] ) : Expression {
423
+ const propertyNames : Expression [ ] = [ ] ;
418
424
for ( let i = 0 ; i < elements . length - 1 ; i ++ ) {
419
- if ( isOmittedExpression ( elements [ i ] ) ) {
425
+ const element = elements [ i ] ;
426
+ if ( isOmittedExpression ( element ) ) {
420
427
continue ;
421
428
}
422
- const str = < StringLiteral > createSynthesizedNode ( SyntaxKind . StringLiteral ) ;
423
- str . pos = location . pos ;
424
- str . end = location . end ;
425
- str . text = getTextOfPropertyName ( getPropertyName ( elements [ i ] ) ) ;
426
- propertyNames . push ( str ) ;
429
+ if ( isComputedPropertyName ( getPropertyName ( element ) ) ) {
430
+ // get the temp name and put that in there instead, like `_tmp + ""`
431
+ const temp = computedTempVariables . shift ( ) ;
432
+ propertyNames . push ( createConditional ( createBinary ( createTypeOf ( temp ) ,
433
+ SyntaxKind . EqualsEqualsEqualsToken ,
434
+ createLiteral ( "symbol" ) ) ,
435
+ createToken ( SyntaxKind . QuestionToken ) ,
436
+ temp ,
437
+ createToken ( SyntaxKind . ColonToken ) ,
438
+ createBinary ( temp , SyntaxKind . PlusToken , createLiteral ( "" ) ) ) ) ;
439
+ }
440
+ else {
441
+ const propName = getTextOfPropertyName ( getPropertyName ( element ) ) ;
442
+ propertyNames . push ( createLiteral ( propName , location ) ) ;
443
+ }
427
444
}
428
445
const args = createSynthesizedNodeArray ( [ value , createArrayLiteral ( propertyNames , location ) ] ) ;
429
446
return createCall ( createIdentifier ( "__rest" ) , undefined , args ) ;
@@ -522,6 +539,7 @@ namespace ts {
522
539
const elements = name . elements ;
523
540
const numElements = elements . length ;
524
541
let bindingElements : BindingElement [ ] = [ ] ;
542
+ let computedTempVariables : Expression [ ] ;
525
543
for ( let i = 0 ; i < numElements ; i ++ ) {
526
544
const element = elements [ i ] ;
527
545
if ( isOmittedExpression ( element ) ) {
@@ -533,12 +551,15 @@ namespace ts {
533
551
bindingElements = [ ] ;
534
552
}
535
553
const restCall = createRestCall ( value ,
536
- name . elements ,
554
+ elements , // name.elements,
537
555
element => ( element as BindingElement ) . propertyName || < Identifier > ( element as BindingElement ) . name ,
538
- name ) ;
556
+ name ,
557
+ computedTempVariables ) ;
539
558
emitBindingElement ( element , restCall ) ;
540
559
}
541
- else if ( transformRest && ! ( element . transformFlags & TransformFlags . ContainsSpreadExpression ) ) {
560
+ else if ( transformRest &&
561
+ ! ( element . transformFlags & TransformFlags . ContainsSpreadExpression ) &&
562
+ ! isComputedPropertyName ( element . propertyName || element . name ) ) {
542
563
// do not emit until we have a complete bundle of ES2015 syntax
543
564
bindingElements . push ( element ) ;
544
565
}
@@ -549,7 +570,11 @@ namespace ts {
549
570
}
550
571
// Rewrite element to a declaration with an initializer that fetches property
551
572
const propName = element . propertyName || < Identifier > element . name ;
552
- emitBindingElement ( element , createDestructuringPropertyAccess ( value , propName ) ) ;
573
+ const propAccess = createDestructuringPropertyAccess ( value , propName ) ;
574
+ if ( isComputedPropertyName ( propName ) ) {
575
+ computedTempVariables = append ( computedTempVariables , ( propAccess as ElementAccessExpression ) . argumentExpression ) ;
576
+ }
577
+ emitBindingElement ( element , propAccess ) ;
553
578
}
554
579
}
555
580
if ( bindingElements . length ) {
0 commit comments