@@ -402,6 +402,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
402402 */
403403 argumentsName ?: string ;
404404
405+ /*
406+ * alias for 'this' from the calling code stack frame in case if this was used inside the converted loop
407+ */
408+ thisName ?: string ;
409+
405410 /*
406411 * list of non-block scoped variable declarations that appear inside converted loop
407412 * such variable declarations should be moved outside the loop body
@@ -549,7 +554,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
549554 [ ModuleKind . CommonJS ] ( ) { } ,
550555 } ;
551556
552-
557+
553558 return doEmit ;
554559
555560 function doEmit ( jsFilePath : string , sourceMapFilePath : string , sourceFiles : SourceFile [ ] , isBundledEmit : boolean ) {
@@ -1992,6 +1997,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
19921997 if ( resolver . getNodeCheckFlags ( node ) & NodeCheckFlags . LexicalThis ) {
19931998 write ( "_this" ) ;
19941999 }
2000+ else if ( convertedLoopState ) {
2001+ write ( convertedLoopState . thisName || ( convertedLoopState . thisName = makeUniqueName ( "this" ) ) ) ;
2002+ }
19952003 else {
19962004 write ( "this" ) ;
19972005 }
@@ -3322,6 +3330,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
33223330 convertedLoopState . argumentsName = convertedOuterLoopState . argumentsName ;
33233331 }
33243332
3333+ if ( convertedOuterLoopState . thisName ) {
3334+ // outer loop has already used 'this' so we've already have some name to alias it
3335+ // use the same name in all nested loops
3336+ convertedLoopState . thisName = convertedOuterLoopState . thisName ;
3337+ }
3338+
33253339 if ( convertedOuterLoopState . hoistedLocalVariables ) {
33263340 // we've already collected some non-block scoped variable declarations in enclosing loop
33273341 // use the same storage in nested loop
@@ -3351,6 +3365,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
33513365 writeLine ( ) ;
33523366 }
33533367 }
3368+ if ( convertedLoopState . thisName ) {
3369+ // if alias for this is set
3370+ if ( convertedOuterLoopState ) {
3371+ // pass it to outer converted loop
3372+ convertedOuterLoopState . thisName = convertedLoopState . thisName ;
3373+ }
3374+ else {
3375+ // this is top level converted loop so we need to create an alias for 'this' here
3376+ // NOTE:
3377+ // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set.
3378+ // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'.
3379+ write ( `var ${ convertedLoopState . thisName } = this;` ) ;
3380+ writeLine ( ) ;
3381+ }
3382+ }
33543383
33553384 if ( convertedLoopState . hoistedLocalVariables ) {
33563385 // if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later
@@ -5987,9 +6016,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
59876016 }
59886017
59896018 // Clone the type name and parent it to a location outside of the current declaration.
5990- const typeName = cloneEntityName ( node . typeName ) ;
5991- typeName . parent = location ;
5992-
6019+ const typeName = cloneEntityName ( node . typeName , location ) ;
59936020 const result = resolver . getTypeReferenceSerializationKind ( typeName ) ;
59946021 switch ( result ) {
59956022 case TypeReferenceSerializationKind . Unknown :
@@ -7352,7 +7379,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
73527379 write ( `], function(${ exportFunctionForFile } ) {` ) ;
73537380 writeLine ( ) ;
73547381 increaseIndent ( ) ;
7355- const startIndex = emitDirectivePrologues ( node . statements , /*startWithNewLine*/ true ) ;
7382+ const startIndex = emitDirectivePrologues ( node . statements , /*startWithNewLine*/ true , /*ensureUseStrict*/ true ) ;
73567383 emitEmitHelpers ( node ) ;
73577384 emitCaptureThisForNodeIfNecessary ( node ) ;
73587385 emitSystemModuleBody ( node , dependencyGroups , startIndex ) ;
@@ -7462,7 +7489,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
74627489 writeModuleName ( node , emitRelativePathAsModuleName ) ;
74637490 emitAMDDependencies ( node , /*includeNonAmdDependencies*/ true , emitRelativePathAsModuleName ) ;
74647491 increaseIndent ( ) ;
7465- const startIndex = emitDirectivePrologues ( node . statements , /*startWithNewLine*/ true ) ;
7492+ const startIndex = emitDirectivePrologues ( node . statements , /*startWithNewLine*/ true , /*ensureUseStrict*/ true ) ;
74667493 emitExportStarHelper ( ) ;
74677494 emitCaptureThisForNodeIfNecessary ( node ) ;
74687495 emitLinesStartingAt ( node . statements , startIndex ) ;
@@ -7474,7 +7501,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
74747501 }
74757502
74767503 function emitCommonJSModule ( node : SourceFile ) {
7477- const startIndex = emitDirectivePrologues ( node . statements , /*startWithNewLine*/ false ) ;
7504+ const startIndex = emitDirectivePrologues ( node . statements , /*startWithNewLine*/ false , /*ensureUseStrict*/ true ) ;
74787505 emitEmitHelpers ( node ) ;
74797506 collectExternalModuleInfo ( node ) ;
74807507 emitExportStarHelper ( ) ;
@@ -7503,7 +7530,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
75037530})(` ) ;
75047531 emitAMDFactoryHeader ( dependencyNames ) ;
75057532 increaseIndent ( ) ;
7506- const startIndex = emitDirectivePrologues ( node . statements , /*startWithNewLine*/ true ) ;
7533+ const startIndex = emitDirectivePrologues ( node . statements , /*startWithNewLine*/ true , /*ensureUseStrict*/ true ) ;
75077534 emitExportStarHelper ( ) ;
75087535 emitCaptureThisForNodeIfNecessary ( node ) ;
75097536 emitLinesStartingAt ( node . statements , startIndex ) ;
@@ -7645,19 +7672,38 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
76457672 }
76467673 }
76477674
7648- function emitDirectivePrologues ( statements : Node [ ] , startWithNewLine : boolean ) : number {
7675+ function isUseStrictPrologue ( node : ExpressionStatement ) : boolean {
7676+ return ! ! ( node . expression as StringLiteral ) . text . match ( / u s e s t r i c t / ) ;
7677+ }
7678+
7679+ function ensureUseStrictPrologue ( startWithNewLine : boolean , writeUseStrict : boolean ) {
7680+ if ( writeUseStrict ) {
7681+ if ( startWithNewLine ) {
7682+ writeLine ( ) ;
7683+ }
7684+ write ( "\"use strict\";" ) ;
7685+ }
7686+ }
7687+
7688+ function emitDirectivePrologues ( statements : Node [ ] , startWithNewLine : boolean , ensureUseStrict ?: boolean ) : number {
7689+ let foundUseStrict = false ;
76497690 for ( let i = 0 ; i < statements . length ; ++ i ) {
76507691 if ( isPrologueDirective ( statements [ i ] ) ) {
7692+ if ( isUseStrictPrologue ( statements [ i ] as ExpressionStatement ) ) {
7693+ foundUseStrict = true ;
7694+ }
76517695 if ( startWithNewLine || i > 0 ) {
76527696 writeLine ( ) ;
76537697 }
76547698 emit ( statements [ i ] ) ;
76557699 }
76567700 else {
7701+ ensureUseStrictPrologue ( startWithNewLine || i > 0 , ! foundUseStrict && ensureUseStrict ) ;
76577702 // return index of the first non prologue directive
76587703 return i ;
76597704 }
76607705 }
7706+ ensureUseStrictPrologue ( startWithNewLine , ! foundUseStrict && ensureUseStrict ) ;
76617707 return statements . length ;
76627708 }
76637709
0 commit comments