In current prototype of the Async/Await downlevel support, we found a bug causes an erroneous exception to occur in code that should otherwise work.
Repro:
The gist of the issue is that having a “return” statement inside of a for loop in a function that has an await in it causes an error.
Run this code an you’ll see that whenever the “num” is > .5 (and the “return true” statement gets evaluated), you get the following error that comes from within the __generator code: “TypeError: Unable to get property '0' of undefined or null reference”
async functionitemExists(): Q.Promise<boolean>{var numTries =3;for(vari=0;i<numTries;i++){varnum=awaitQ.fcall(function(){returnMath.random()});console.log(num);if(num>.5){returntrue;}}returnfalse;}itemExists().then(function(val){console.log("All values greater than .5: "+val)}).catch(function(e){console.error("Error: "+e);});Analysis:
The problem is caused by the “return” statement within the loop. If I had modified itemExists() to set a local variable, for example, and then break out of the loop via a “break” statement, the code would work:
// With workaround (NOT short-circuiting the loop)
async functionitemExists(): Q.Promise<boolean>{var numTries =3;varresult=false;for(vari=0;i<numTries;i++){varnum=awaitQ.fcall(function(){returnMath.random()});console.log(num);if(num>.5){result=true;break;}}returnresult;}A quick analysis of the issue seems to be in the generated code. The exception is throw in here:
try{varoperation=body(state);opcode=operation[0],arg=operation[1];}catch(e){opcode=1/*throw*/,arg=e;}But the actual culprit seems to be in the fact that there is an inconsistency in the generated return and break statement (so far as I can tell). Namely, 3 looks like sometime a “break” and sometimes a “return”.
functionitemExists(){returnnewQ.Promise(function(_resolve){_resolve(__awaiter(__generator(function(_state){switch(_state.label){case0:
numTries=3;i=0;_state.label=1;case1:
if(!(i<numTries))return[3/*break*/,4];return[4/*yield*/,Q.fcall(function(){returnMath.random();})];case2:
num=_state.sent;console.log(num);if(num>.5){return[3/*return*/,true];}_state.label=3;case3:
i++;return[3/*break*/,1];case4:
return[2/*return*/,false];}})));});varnumTries,i,num;}itemExists().then(function(val){console.log("All values greater than .5: "+val);}).catch(function(e){console.error("Error: "+e);});
In current prototype of the Async/Await downlevel support, we found a bug causes an erroneous exception to occur in code that should otherwise work.
Repro:
The gist of the issue is that having a “return” statement inside of a for loop in a function that has an await in it causes an error.
Run this code an you’ll see that whenever the “num” is > .5 (and the “return true” statement gets evaluated), you get the following error that comes from within the __generator code: “TypeError: Unable to get property '0' of undefined or null reference”
Analysis:
The problem is caused by the “return” statement within the loop. If I had modified itemExists() to set a local variable, for example, and then break out of the loop via a “break” statement, the code would work:
A quick analysis of the issue seems to be in the generated code. The exception is throw in here:
But the actual culprit seems to be in the fact that there is an inconsistency in the generated return and break statement (so far as I can tell). Namely, 3 looks like sometime a “break” and sometimes a “return”.