@@ -3210,22 +3210,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
32103210 }
32113211 }
32123212
3213- function ensureIdentifier ( expr : Expression ) : Expression {
3214- if ( expr . kind !== SyntaxKind . Identifier ) {
3215- let identifier = createTempVariable ( TempFlags . Auto ) ;
3216- if ( ! canDefineTempVariablesInPlace ) {
3217- recordTempDeclaration ( identifier ) ;
3218- }
3219- emitAssignment ( identifier , expr ) ;
3220- expr = identifier ;
3213+ /**
3214+ * Ensures that there exists a declared identifier whose value holds the given expression.
3215+ * This function is useful to ensure that the expression's value can be read from in subsequent expressions.
3216+ * Unless 'reuseIdentifierExpressions' is false, 'expr' will be returned if it is just an identifier.
3217+ *
3218+ * @param expr the expression whose value needs to be bound.
3219+ * @param reuseIdentifierExpressions true if identifier expressions can simply be returned;
3220+ * false if it is necessary to always emit an identifier.
3221+ */
3222+ function ensureIdentifier ( expr : Expression , reuseIdentifierExpressions : boolean ) : Expression {
3223+ if ( expr . kind === SyntaxKind . Identifier && reuseIdentifierExpressions ) {
3224+ return expr ;
3225+ }
3226+
3227+ let identifier = createTempVariable ( TempFlags . Auto ) ;
3228+ if ( ! canDefineTempVariablesInPlace ) {
3229+ recordTempDeclaration ( identifier ) ;
32213230 }
3222- return expr ;
3231+ emitAssignment ( identifier , expr ) ;
3232+ return identifier ;
32233233 }
32243234
32253235 function createDefaultValueCheck ( value : Expression , defaultValue : Expression ) : Expression {
32263236 // The value expression will be evaluated twice, so for anything but a simple identifier
32273237 // we need to generate a temporary variable
3228- value = ensureIdentifier ( value ) ;
3238+ value = ensureIdentifier ( value , /*reuseIdentifierExpressions*/ true ) ;
32293239 // Return the expression 'value === void 0 ? defaultValue : value'
32303240 let equals = < BinaryExpression > createSynthesizedNode ( SyntaxKind . BinaryExpression ) ;
32313241 equals . left = value ;
@@ -3276,7 +3286,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
32763286 if ( properties . length !== 1 ) {
32773287 // For anything but a single element destructuring we need to generate a temporary
32783288 // to ensure value is evaluated exactly once.
3279- value = ensureIdentifier ( value ) ;
3289+ value = ensureIdentifier ( value , /*reuseIdentifierExpressions*/ true ) ;
32803290 }
32813291 for ( let p of properties ) {
32823292 if ( p . kind === SyntaxKind . PropertyAssignment || p . kind === SyntaxKind . ShorthandPropertyAssignment ) {
@@ -3291,7 +3301,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
32913301 if ( elements . length !== 1 ) {
32923302 // For anything but a single element destructuring we need to generate a temporary
32933303 // to ensure value is evaluated exactly once.
3294- value = ensureIdentifier ( value ) ;
3304+ value = ensureIdentifier ( value , /*reuseIdentifierExpressions*/ true ) ;
32953305 }
32963306 for ( let i = 0 ; i < elements . length ; i ++ ) {
32973307 let e = elements [ i ] ;
@@ -3336,7 +3346,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
33363346 if ( root . parent . kind !== SyntaxKind . ParenthesizedExpression ) {
33373347 write ( "(" ) ;
33383348 }
3339- value = ensureIdentifier ( value ) ;
3349+ value = ensureIdentifier ( value , /*reuseIdentifierExpressions*/ true ) ;
33403350 emitDestructuringAssignment ( target , value ) ;
33413351 write ( ", " ) ;
33423352 emit ( value ) ;
@@ -3346,7 +3356,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
33463356 }
33473357 }
33483358
3349- function emitBindingElement ( target : BindingElement , value : Expression ) {
3359+ function emitBindingElement ( target : BindingElement | VariableDeclaration , value : Expression ) {
33503360 if ( target . initializer ) {
33513361 // Combine value and initializer
33523362 value = value ? createDefaultValueCheck ( value , target . initializer ) : target . initializer ;
@@ -3356,14 +3366,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
33563366 value = createVoidZero ( ) ;
33573367 }
33583368 if ( isBindingPattern ( target . name ) ) {
3359- let pattern = < BindingPattern > target . name ;
3360- let elements = pattern . elements ;
3361- if ( elements . length !== 1 ) {
3362- // For anything but a single element destructuring we need to generate a temporary
3363- // to ensure value is evaluated exactly once.
3364- value = ensureIdentifier ( value ) ;
3365- }
3366- for ( let i = 0 ; i < elements . length ; i ++ ) {
3369+ const pattern = < BindingPattern > target . name ;
3370+ const elements = pattern . elements ;
3371+ const numElements = elements . length ;
3372+
3373+ if ( numElements !== 1 ) {
3374+ // For anything other than a single-element destructuring we need to generate a temporary
3375+ // to ensure value is evaluated exactly once. Additionally, if we have zero elements
3376+ // we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
3377+ // so in that case, we'll intentionally create that temporary.
3378+ value = ensureIdentifier ( value , /*reuseIdentifierExpressions*/ numElements !== 0 ) ;
3379+ }
3380+
3381+ for ( let i = 0 ; i < numElements ; i ++ ) {
33673382 let element = elements [ i ] ;
33683383 if ( pattern . kind === SyntaxKind . ObjectBindingPattern ) {
33693384 // Rewrite element to a declaration with an initializer that fetches property
@@ -3375,7 +3390,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
33753390 // Rewrite element to a declaration that accesses array element at index i
33763391 emitBindingElement ( element , createElementAccessExpression ( value , createNumericLiteral ( i ) ) ) ;
33773392 }
3378- else if ( i === elements . length - 1 ) {
3393+ else if ( i === numElements - 1 ) {
33793394 emitBindingElement ( element , createSliceCall ( value , i ) ) ;
33803395 }
33813396 }
0 commit comments