1+ /// <reference path="..\harness.ts" />
2+
3+ namespace ts {
4+ declare var Symbol : SymbolConstructor ;
5+
6+ describe ( "forAwaitOfEvaluation" , ( ) => {
7+ const sourceFile = vpath . combine ( vfs . srcFolder , "source.ts" ) ;
8+
9+ function compile ( sourceText : string , options ?: CompilerOptions ) {
10+ const fs = vfs . createFromFileSystem ( Harness . IO , /*ignoreCase*/ false ) ;
11+ fs . writeFileSync ( sourceFile , sourceText ) ;
12+ const compilerOptions : CompilerOptions = { target : ScriptTarget . ES5 , module : ModuleKind . CommonJS , lib : [ "lib.esnext.d.ts" ] , ...options } ;
13+ const host = new fakes . CompilerHost ( fs , compilerOptions ) ;
14+ return compiler . compileFiles ( host , [ sourceFile ] , compilerOptions ) ;
15+ }
16+
17+ function noRequire ( id : string ) {
18+ throw new Error ( `Module '${ id } ' could not be found.` ) ;
19+ }
20+
21+ // Define a custom "Symbol" constructor to attach missing built-in symbols without
22+ // modifying the global "Symbol" constructor
23+ // tslint:disable-next-line:variable-name
24+ const FakeSymbol : SymbolConstructor = ( ( description ?: string ) => Symbol ( description ) ) as any ;
25+ ( < any > FakeSymbol ) . prototype = Symbol . prototype ;
26+ for ( const key of Object . getOwnPropertyNames ( Symbol ) ) {
27+ Object . defineProperty ( FakeSymbol , key , Object . getOwnPropertyDescriptor ( Symbol , key ) ! ) ;
28+ }
29+
30+ // Add "asyncIterator" if missing
31+ if ( ! hasProperty ( FakeSymbol , "asyncIterator" ) ) Object . defineProperty ( FakeSymbol , "asyncIterator" , { value : Symbol . for ( "Symbol.asyncIterator" ) , configurable : true } ) ;
32+
33+ function evaluate ( result : compiler . CompilationResult ) {
34+ const output = result . getOutput ( sourceFile , "js" ) ! ;
35+ assert . isDefined ( output ) ;
36+
37+ const evaluateText = `(function (module, exports, require, __dirname, __filename, Symbol) { ${ output . text } })` ;
38+ const evaluateThunk = eval ( evaluateText ) as ( module : any , exports : any , require : ( id : string ) => any , dirname : string , filename : string , symbolConstructor : SymbolConstructor ) => void ;
39+ const module : { exports : any ; } = { exports : { } } ;
40+ evaluateThunk ( module , module . exports , noRequire , vpath . dirname ( output . file ) , output . file , FakeSymbol ) ;
41+ return module ;
42+ }
43+
44+ it ( "sync (es5)" , async ( ) => {
45+ const module = evaluate ( compile ( `
46+ let i = 0;
47+ const iterator = {
48+ [Symbol.iterator]() { return this; },
49+ next() {
50+ switch (i++) {
51+ case 0: return { value: 1, done: false };
52+ case 1: return { value: Promise.resolve(2), done: false };
53+ case 2: return { value: new Promise<number>(resolve => setTimeout(resolve, 100, 3)), done: false };
54+ default: return { value: undefined: done: true };
55+ }
56+ }
57+ };
58+ export const output: any[] = [];
59+ export async function main() {
60+ for await (const item of iterator) {
61+ output.push(item);
62+ }
63+ }` ) ) ;
64+ await module . exports . main ( ) ;
65+ assert . strictEqual ( module . exports . output [ 0 ] , 1 ) ;
66+ assert . strictEqual ( module . exports . output [ 1 ] , 2 ) ;
67+ assert . strictEqual ( module . exports . output [ 2 ] , 3 ) ;
68+ } ) ;
69+
70+ it ( "sync (es2015)" , async ( ) => {
71+ const module = evaluate ( compile ( `
72+ let i = 0;
73+ const iterator = {
74+ [Symbol.iterator]() { return this; },
75+ next() {
76+ switch (i++) {
77+ case 0: return { value: 1, done: false };
78+ case 1: return { value: Promise.resolve(2), done: false };
79+ case 2: return { value: new Promise<number>(resolve => setTimeout(resolve, 100, 3)), done: false };
80+ default: return { value: undefined: done: true };
81+ }
82+ }
83+ };
84+ export const output: any[] = [];
85+ export async function main() {
86+ for await (const item of iterator) {
87+ output.push(item);
88+ }
89+ }` , { target : ScriptTarget . ES2015 } ) ) ;
90+ await module . exports . main ( ) ;
91+ assert . strictEqual ( module . exports . output [ 0 ] , 1 ) ;
92+ assert . strictEqual ( module . exports . output [ 1 ] , 2 ) ;
93+ assert . strictEqual ( module . exports . output [ 2 ] , 3 ) ;
94+ } ) ;
95+
96+ it ( "async (es5)" , async ( ) => {
97+ const module = evaluate ( compile ( `
98+ let i = 0;
99+ const iterator = {
100+ [Symbol.asyncIterator]() { return this; },
101+ async next() {
102+ switch (i++) {
103+ case 0: return { value: 1, done: false };
104+ case 1: return { value: Promise.resolve(2), done: false };
105+ case 2: return { value: new Promise<number>(resolve => setTimeout(resolve, 100, 3)), done: false };
106+ default: return { value: undefined: done: true };
107+ }
108+ }
109+ };
110+ export const output: any[] = [];
111+ export async function main() {
112+ for await (const item of iterator) {
113+ output.push(item);
114+ }
115+ }` ) ) ;
116+ await module . exports . main ( ) ;
117+ assert . strictEqual ( module . exports . output [ 0 ] , 1 ) ;
118+ assert . instanceOf ( module . exports . output [ 1 ] , Promise ) ;
119+ assert . instanceOf ( module . exports . output [ 2 ] , Promise ) ;
120+ } ) ;
121+
122+ it ( "async (es2015)" , async ( ) => {
123+ const module = evaluate ( compile ( `
124+ let i = 0;
125+ const iterator = {
126+ [Symbol.asyncIterator]() { return this; },
127+ async next() {
128+ switch (i++) {
129+ case 0: return { value: 1, done: false };
130+ case 1: return { value: Promise.resolve(2), done: false };
131+ case 2: return { value: new Promise<number>(resolve => setTimeout(resolve, 100, 3)), done: false };
132+ default: return { value: undefined: done: true };
133+ }
134+ }
135+ };
136+ export const output: any[] = [];
137+ export async function main() {
138+ for await (const item of iterator) {
139+ output.push(item);
140+ }
141+ }` , { target : ScriptTarget . ES2015 } ) ) ;
142+ await module . exports . main ( ) ;
143+ assert . strictEqual ( module . exports . output [ 0 ] , 1 ) ;
144+ assert . instanceOf ( module . exports . output [ 1 ] , Promise ) ;
145+ assert . instanceOf ( module . exports . output [ 2 ] , Promise ) ;
146+ } ) ;
147+ } ) ;
148+ }
0 commit comments