This may sound like a silly report -- please bear with me (:
I'm the author of synchronous-promise, an A+ Promise-like implementation which doesn't defer (and allows pausing and resuming), so makes testing certain scenarios clearer / easier. Mostly, it's worked well with TypeScript because of how awesome TypeScript's async/await logic is.
The problem is very specific is this: if SynchronousPromise is installed globally (overriding Promise -- and we could do this so that client code returning a Promise actually returns a SynchronousPromise, during test-time), and a SynchronousPromise resolution happens in a setTimeout, the TS generator function also makes use of SynchronousPromise and doesn't complete awaiting the following:
import{SynchronousPromise}from"./index";import{expect}from'chai';// install SynchronousPromise globallyglobal.Promise=SynchronousPromise;describe("typescript async/await",()=>{it("should not hang",asyncfunction(){// Arrange// ActawaitnewSynchronousPromise(function(resolve,reject){setTimeout(()=>{resolve("done!");},0);});})});The problem seems to track down to the generated generator code which expects a P (short-handed global Promise) to defer. If I comment out the line:
// global.Promise = SynchronousPromise;
then the test completes, as expected.
Now, I realise that there is a valid argument that SynchronousPromise, being not async in nature, violates the A+ specification and that this whole issue shouldn't be the problem of TypeScript at all. This is a fair argument, which has a counter-argument: that all TypeScript is a super-set of Javascript. The following Javascript works fine:
"use strict";varexpect=require("chai").expect,sut=require("./index"),SynchronousPromise=sut.SynchronousPromise,describe("with timeout in ctor",()=>{it("should complete when the timeout does",(done)=>{// Arrangevarcaptured,sut=newSynchronousPromise(function(resolve,reject){setTimeout(function(){resolve("moo");},0);}).then(function(result){captured=result;});// Act// AssertsetTimeout(function(){expect(captured).to.equal("moo");done();},500);});});And debugging the prior snippet has shown that all promises (even the TS-generated / wrapper ones created for async/await) are resolved. Execution is simply not continued by the generator.
Expected behavior:
The first snippet (TypeScript) should complete like the second snippet (Javascript)
Actual behavior:
The Javascript completes where the TypeScript does not
Proposed solutions.
- Since the generator function requires deferral, perhaps use
setTimeout -- however, this is subject to the same problems as testing frameworks like jasmine can install a testing clock which has to be manually advanced by the test code. - "var off" the global Promise implementation before allowing client code to run and use that version inside the generator code. This seems to be the lowest-hanging fruit for solving this problem, from my point of view.
Of course, the response could also be that this is just an issue with synchronous-promise, but it also highlights that TS compiled execution can be interfered with by client code -- which may not be optimal.
This may sound like a silly report -- please bear with me (:
I'm the author of synchronous-promise, an A+ Promise-like implementation which doesn't defer (and allows pausing and resuming), so makes testing certain scenarios clearer / easier. Mostly, it's worked well with TypeScript because of how awesome TypeScript's async/await logic is.
The problem is very specific is this: if
SynchronousPromiseis installed globally (overridingPromise-- and we could do this so that client code returning aPromiseactually returns aSynchronousPromise, during test-time), and aSynchronousPromiseresolution happens in asetTimeout, the TS generator function also makes use ofSynchronousPromiseand doesn't complete awaiting the following:The problem seems to track down to the generated
generatorcode which expects aP(short-handed globalPromise) to defer. If I comment out the line:// global.Promise = SynchronousPromise;then the test completes, as expected.
Now, I realise that there is a valid argument that
SynchronousPromise, being not async in nature, violates the A+ specification and that this whole issue shouldn't be the problem of TypeScript at all. This is a fair argument, which has a counter-argument: that all TypeScript is a super-set of Javascript. The following Javascript works fine:And debugging the prior snippet has shown that all promises (even the TS-generated / wrapper ones created for async/await) are resolved. Execution is simply not continued by the generator.
Expected behavior:
The first snippet (TypeScript) should complete like the second snippet (Javascript)
Actual behavior:
The Javascript completes where the TypeScript does not
Proposed solutions.
setTimeout-- however, this is subject to the same problems as testing frameworks likejasminecan install a testing clock which has to be manually advanced by the test code.Of course, the response could also be that this is just an issue with
synchronous-promise, but it also highlights that TS compiled execution can be interfered with by client code -- which may not be optimal.