@@ -304,25 +304,31 @@ namespace ts {
304304 if ( properties . length !== 1 ) {
305305 // For anything but a single element destructuring we need to generate a temporary
306306 // 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
308308 value = ensureIdentifier ( value , /*reuseIdentifierExpressions*/ true , location , emitTempVariableAssignment ) ;
309309 }
310310
311311 let bindingElements : ObjectLiteralElementLike [ ] = [ ] ;
312+ let computedTempVariables : Expression [ ] ;
312313 for ( let i = 0 ; i < properties . length ; i ++ ) {
313314 const p = properties [ i ] ;
314315 if ( p . kind === SyntaxKind . PropertyAssignment || p . kind === SyntaxKind . ShorthandPropertyAssignment ) {
315316 if ( ! transformRest ||
316317 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 ) ) {
318320 if ( bindingElements . length ) {
319321 emitRestAssignment ( bindingElements , value , location , target ) ;
320322 bindingElements = [ ] ;
321323 }
322324 const propName = < Identifier | LiteralExpression > ( < PropertyAssignment > p ) . name ;
323325 const bindingTarget = p . kind === SyntaxKind . ShorthandPropertyAssignment ? < ShorthandPropertyAssignment > p : ( < PropertyAssignment > p ) . initializer || propName ;
324326 // 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 ) ;
326332 }
327333 else {
328334 bindingElements . push ( p ) ;
@@ -336,7 +342,7 @@ namespace ts {
336342 bindingElements = [ ] ;
337343 }
338344 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 ) ;
340346 emitDestructuringAssignment ( propName , restCall , p ) ;
341347 }
342348 }
@@ -413,17 +419,28 @@ namespace ts {
413419
414420 /** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
415421 * `{ 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 [ ] = [ ] ;
418424 for ( let i = 0 ; i < elements . length - 1 ; i ++ ) {
419- if ( isOmittedExpression ( elements [ i ] ) ) {
425+ const element = elements [ i ] ;
426+ if ( isOmittedExpression ( element ) ) {
420427 continue ;
421428 }
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+ }
427444 }
428445 const args = createSynthesizedNodeArray ( [ value , createArrayLiteral ( propertyNames , location ) ] ) ;
429446 return createCall ( createIdentifier ( "__rest" ) , undefined , args ) ;
@@ -522,6 +539,7 @@ namespace ts {
522539 const elements = name . elements ;
523540 const numElements = elements . length ;
524541 let bindingElements : BindingElement [ ] = [ ] ;
542+ let computedTempVariables : Expression [ ] ;
525543 for ( let i = 0 ; i < numElements ; i ++ ) {
526544 const element = elements [ i ] ;
527545 if ( isOmittedExpression ( element ) ) {
@@ -533,12 +551,15 @@ namespace ts {
533551 bindingElements = [ ] ;
534552 }
535553 const restCall = createRestCall ( value ,
536- name . elements ,
554+ elements , // name.elements,
537555 element => ( element as BindingElement ) . propertyName || < Identifier > ( element as BindingElement ) . name ,
538- name ) ;
556+ name ,
557+ computedTempVariables ) ;
539558 emitBindingElement ( element , restCall ) ;
540559 }
541- else if ( transformRest && ! ( element . transformFlags & TransformFlags . ContainsSpreadExpression ) ) {
560+ else if ( transformRest &&
561+ ! ( element . transformFlags & TransformFlags . ContainsSpreadExpression ) &&
562+ ! isComputedPropertyName ( element . propertyName || element . name ) ) {
542563 // do not emit until we have a complete bundle of ES2015 syntax
543564 bindingElements . push ( element ) ;
544565 }
@@ -549,7 +570,11 @@ namespace ts {
549570 }
550571 // Rewrite element to a declaration with an initializer that fetches property
551572 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 ) ;
553578 }
554579 }
555580 if ( bindingElements . length ) {
0 commit comments