OLD | NEW |
1 /// <reference path="../typings/mocha/mocha.d.ts"/> | 1 /// <reference path="../typings/mocha/mocha.d.ts"/> |
2 import * as fs from 'fs'; | 2 import * as fs from 'fs'; |
3 import {expectTranslate, FAKE_MAIN, translateSource} from './test_support'; | 3 |
4 import chai = require('chai'); | 4 import {expectTranslate, FAKE_MAIN} from './test_support'; |
5 | 5 |
6 let es6RuntimeDeclarations = ` | 6 let es6RuntimeDeclarations = ` |
7 interface Iterable<T> {} | 7 interface Iterable<T> {} |
8 interface Symbol {} | 8 interface Symbol {} |
9 interface Map<K, V> { | 9 interface Map<K, V> { |
10 get(key: K): V; | 10 get(key: K): V; |
11 has(key: K): boolean; | 11 has(key: K): boolean; |
12 set(key: K, value: V): Map<K, V>; | 12 set(key: K, value: V): Map<K, V>; |
13 size: number; | 13 size: number; |
14 delete(key: K): boolean; | 14 delete(key: K): boolean; |
15 forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?
: any): void; | 15 forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?
: any): void; |
16 } | 16 } |
17 interface Array<T> { | 17 interface Array<T> { |
18 find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisA
rg?: any): T; | 18 find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisA
rg?: any): T; |
19 } | 19 } |
20 declare var Map: { | 20 declare var Map: { |
21 new<K, V>(): Map<any, any>; | 21 new<K, V>(): Map<any, any>; |
22 prototype: Map<any, any>; | 22 prototype: Map<any, any>; |
23 }; | 23 }; |
24 declare var Symbol; | 24 declare var Symbol; |
25 `; | 25 `; |
26 | 26 |
27 | 27 |
28 function getSources(str: string): {[k: string]: string} { | 28 function getSources(str: string): {[k: string]: string} { |
29 let srcs: {[k: string]: string} = { | 29 let srcs: {[k: string]: string} = { |
30 'some/path/to/typings/es6-shim/es6-shim': es6RuntimeDeclarations, | 30 'some/path/to/typings/es6-shim/es6-shim': es6RuntimeDeclarations, |
31 'angular2/src/core/di/forward_ref.d.ts': ` | |
32 export declare function forwardRef<T>(x: T): T;`, | |
33 'some/path/to/typings/es6-promise/es6-promise.d.ts': | 31 'some/path/to/typings/es6-promise/es6-promise.d.ts': |
34 fs.readFileSync('typings/es6-promise/es6-promise.d.ts', 'utf-8'), | 32 fs.readFileSync('typings/es6-promise/es6-promise.d.ts', 'utf-8'), |
35 'node_modules/rxjs/Observable.d.ts': ` | |
36 export declare class Observable {}`, | |
37 'angular2/src/facade/async.ts': ` | |
38 export {Observable} from 'rxjs/Observable';`, | |
39 'angular2/src/facade/collection.ts': ` | |
40 export declare var Map;`, | |
41 'angular2/src/facade/lang.d.ts': ` | |
42 interface List<T> extends Array<T> {} | |
43 export declare function CONST_EXPR<T>(x: T): T; | |
44 export declare var normalizeBlank: (x: Object) => any;`, | |
45 'other/file.ts': ` | 33 'other/file.ts': ` |
46 export class X { | 34 export class X { |
47 map(x: number): string { return String(x); } | 35 map(x: number): string { return String(x); } |
48 static get(m: any, k: string): number { return m[k]; } | 36 static get(m: any, k: string): number { return m[k]; } |
49 } | 37 } |
50 export class Promise {} | 38 export class Promise {} |
51 `, | 39 `, |
52 }; | 40 }; |
53 srcs[FAKE_MAIN] = str; | 41 srcs[FAKE_MAIN] = str; |
54 return srcs; | 42 return srcs; |
55 } | 43 } |
56 | 44 |
57 const COMPILE_OPTS = { | 45 const COMPILE_OPTS = { |
58 translateBuiltins: true, | 46 translateBuiltins: true, |
59 failFast: true, | 47 failFast: true, |
60 typingsRoot: 'some/path/to/typings/', | 48 typingsRoot: 'some/path/to/typings/', |
61 }; | 49 }; |
62 | 50 |
63 function expectWithTypes(str: string) { | 51 function expectWithTypes(str: string) { |
64 return expectTranslate(getSources(str), COMPILE_OPTS); | 52 return expectTranslate(getSources(str), COMPILE_OPTS); |
65 } | 53 } |
66 | 54 |
67 function expectErroneousWithType(str: string) { | |
68 return chai.expect(() => translateSource(getSources(str), COMPILE_OPTS)); | |
69 } | |
70 | |
71 describe('type based translation', () => { | 55 describe('type based translation', () => { |
72 describe('Dart type substitution', () => { | 56 describe('Dart type substitution', () => { |
73 it('finds registered substitutions', () => { | 57 it('finds registered substitutions', () => { |
74 expectWithTypes( | 58 expectWithTypes('const n: Node;').to.equal(`import "dart:html"; |
75 'import {Observable} from "angular2/src/facade/async"; var o: Observab
le<Date>;') | |
76 .to.equal(`import "package:angular2/src/facade/async.dart" show Stream
; | |
77 | 59 |
78 Stream<DateTime> o;`); | 60 @JS() |
79 expectWithTypes('var p: Promise<void> = x;').to.equal(`import "dart:async"
; | 61 external Node get n;`); |
| 62 expectWithTypes('const xhr: XMLHttpRequest;').to.equal(`import "dart:html"
; |
80 | 63 |
81 Future p = x;`); | 64 @JS() |
82 expectWithTypes('var y: Promise;').to.equal(`import "dart:async"; | 65 external HttpRequest get xhr;`); |
| 66 expectWithTypes('const intArray: Uint8Array;').to.equal(`import "dart:type
d_data"; |
83 | 67 |
84 Future y;`); | 68 @JS() |
85 expectWithTypes('var n: Node;').to.equal('dynamic n;'); | 69 external Uint8List get intArray;`); |
86 expectWithTypes('var xhr: XMLHttpRequest;').to.equal(`import "dart:html"; | 70 expectWithTypes('const buff: ArrayBuffer;').to.equal(`import "dart:typed_d
ata"; |
87 | 71 |
88 HttpRequest xhr;`); | 72 @JS() |
89 expectWithTypes('var intArray: Uint8Array;').to.equal(`import "dart:typed_
arrays"; | 73 external ByteBuffer get buff;`); |
90 | |
91 Uint8List intArray;`); | |
92 expectWithTypes('var buff: ArrayBuffer;').to.equal(`import "dart:typed_arr
ays"; | |
93 | |
94 ByteBuffer buff;`); | |
95 }); | 74 }); |
96 | 75 |
97 it('allows undeclared types', () => { expectWithTypes('var t: Thing;').to.eq
ual('Thing t;'); }); | 76 it('allows undeclared types', () => { |
98 | 77 expectWithTypes('const t: Thing;').to.equal(`@JS() |
99 it('does not substitute matching name from different file', () => { | 78 external Thing get t;`); |
100 expectWithTypes('import {Promise} from "other/file"; var y = x instanceof
Promise;') | |
101 .to.equal(`import "package:other/file.dart" show Promise; | |
102 | |
103 var y = x is Promise;`); | |
104 }); | |
105 | |
106 it('does not substitute all identifiers', | |
107 () => { expectWithTypes('let Promise = 1;').to.equal(`var Promise = 1;`);
}); | |
108 }); | |
109 | |
110 describe('collection façade', () => { | |
111 it('translates array operations to dartisms', () => { | |
112 expectWithTypes('function f() { var x: Array<number> = []; x.push(1); x.po
p(); }') | |
113 .to.equal(`f() { | |
114 List<num> x = []; | |
115 x.add(1); | |
116 x.removeLast(); | |
117 }`); | |
118 expectWithTypes('function f() { var x: Array<number> = []; x.map((e) => e)
; }') | |
119 .to.equal(`f() { | |
120 List<num> x = []; | |
121 x.map((e) => e).toList(); | |
122 }`); | |
123 expectWithTypes('function f() { var x: Array<number> = []; x.filter((e) =>
true); }') | |
124 .to.equal(`f() { | |
125 List<num> x = []; | |
126 x.where((e) => true).toList(); | |
127 }`); | |
128 expectWithTypes('function f() { var x: Array<number> = []; x.unshift(1, 2,
3); x.shift(); }') | |
129 .to.equal(`f() { | |
130 List<num> x = []; | |
131 (x..insertAll(0, [1, 2, 3])).length; | |
132 x.removeAt(0); | |
133 }`); | |
134 expectWithTypes('function f() { var x: Array<number> = []; x.unshift(1); }
').to.equal(`f() { | |
135 List<num> x = []; | |
136 (x..insert(0, 1)).length; | |
137 }`); | |
138 expectWithTypes('function f() { var x: Array<number> = []; x.concat([1], x
).length; }') | |
139 .to.equal(`f() { | |
140 List<num> x = []; | |
141 (new List.from(x)..addAll([1])..addAll(x)).length; | |
142 }`); | |
143 expectWithTypes('var x: Array<number> = []; var y: Array<number> = x.slice
(0);') | |
144 .to.equal(`List<num> x = []; | |
145 List<num> y = ListWrapper.slice(x, 0);`); | |
146 expectWithTypes('var x: Array<number> = []; var y: Array<number> = x.splic
e(0,1);') | |
147 .to.equal(`List<num> x = []; | |
148 List<num> y = ListWrapper.splice(x, 0, 1);`); | |
149 expectWithTypes('var x: Array<number> = []; var y: string = x.join("-");') | |
150 .to.equal(`List<num> x = []; | |
151 String y = x.join("-");`); | |
152 expectWithTypes('var x: Array<number> = []; var y: string = x.join();') | |
153 .to.equal(`List<num> x = []; | |
154 String y = x.join(",");`); | |
155 expectWithTypes('var x: Array<number> = []; var y: number = x.find((e) =>
e == 0);') | |
156 .to.equal(`List<num> x = []; | |
157 num y = x.firstWhere((e) => e == 0, orElse: () => null);`); | |
158 expectWithTypes('var x: Array<number> = []; var y: boolean = x.some((e) =>
e == 0);') | |
159 .to.equal(`List<num> x = []; | |
160 bool y = x.any((e) => e == 0);`); | |
161 expectWithTypes('var x: Array<number> = []; var y: number = x.reduce((a, b
) => a + b, 0);') | |
162 .to.equal(`List<num> x = []; | |
163 num y = x.fold(0, (a, b) => a + b);`); | |
164 expectWithTypes('var x: Array<number> = []; var y: number = x.reduce((a, b
) => a + b);') | |
165 .to.equal(`List<num> x = []; | |
166 num y = x.fold(null, (a, b) => a + b);`); | |
167 }); | |
168 | |
169 it('translates console.log', () => { | |
170 expectWithTypes(`console.log(1);`).to.equal('print(1);'); | |
171 expectWithTypes(`console.log(1, 2);`).to.equal('print([1, 2].join(" "));')
; | |
172 }); | |
173 | |
174 it('translates string methoids', | |
175 () => { expectErroneousWithType(`var x = 'asd'.substr(0, 1);`).to.throw(/
use substring/); }); | |
176 | |
177 it('translates map operations to dartisms', () => { | |
178 expectWithTypes('function f() { var x = new Map<string, string>(); x.set("
k", "v"); }') | |
179 .to.equal(`f() { | |
180 var x = new Map<String, String>(); | |
181 x["k"] = "v"; | |
182 }`); | |
183 expectWithTypes('function f() { var x = new Map<string, string>(); x.get("
k"); }') | |
184 .to.equal(`f() { | |
185 var x = new Map<String, String>(); | |
186 x["k"]; | |
187 }`); | |
188 expectWithTypes('function f() { var x = new Map<string, string>(); x.has("
k"); }') | |
189 .to.equal(`f() { | |
190 var x = new Map<String, String>(); | |
191 x.containsKey("k"); | |
192 }`); | |
193 expectWithTypes('function f() { var x = new Map<string, string>(); x.delet
e("k"); }') | |
194 .to.equal(`f() { | |
195 var x = new Map<String, String>(); | |
196 (x.containsKey("k") && (x.remove("k") != null || true)); | |
197 }`); | |
198 expectWithTypes( | |
199 'function f() { var x = new Map<string, string>(); x.forEach((v, k) =>
null); }') | |
200 .to.equal(`f() { | |
201 var x = new Map<String, String>(); | |
202 x.forEach((k, v) => null); | |
203 }`); | |
204 expectWithTypes( | |
205 'function f() { var x = new Map<string, string>(); x.forEach(function
(v, k) { return null; }); }') | |
206 .to.equal(`f() { | |
207 var x = new Map<String, String>(); | |
208 x.forEach((k, v) { | |
209 return null; | |
210 }); | |
211 }`); | |
212 expectWithTypes( | |
213 'function f() { var x = new Map<string, string>(); var y = x.forEach((
v, k) => { return null; }); }') | |
214 .to.equal(`f() { | |
215 var x = new Map<String, String>(); | |
216 var y = x.forEach((k, v) { | |
217 return null; | |
218 }); | |
219 }`); | |
220 | |
221 expectWithTypes('function f() { var x = new Map<string, string>(); x.forEa
ch(fn); }') | |
222 .to.equal(`f() { | |
223 var x = new Map<String, String>(); | |
224 x.forEach((k, v) => (fn)(v, k)); | |
225 }`); | |
226 }); | |
227 | |
228 it('translates map properties to dartisms', () => { | |
229 expectWithTypes('var x = new Map<string, string>();var y = x.size;') | |
230 .to.equal(`var x = new Map<String, String>(); | |
231 var y = x.length;`); | |
232 }); | 79 }); |
233 }); | 80 }); |
234 | 81 |
235 describe('regexp', () => { | 82 describe('skip top level calls', () => { |
236 expectWithTypes('function f() { var x = /a/g; x.test("a"); }').to.equal(`f()
{ | 83 it('console.log', () => { |
237 var x = new RegExp(r'a'); | 84 expectWithTypes(`console.log(1);`).to.equal(''); |
238 x.hasMatch("a"); | 85 expectWithTypes(`console.log(1, 2);`).to.equal(''); |
239 }`); | |
240 expectWithTypes('function f() { var result = /a(.)/g.exec("ab")[1]; }').to.e
qual(`f() { | |
241 var result = new RegExp(r'a(.)').firstMatch("ab")[1]; | |
242 }`); | |
243 expectWithTypes('function f() { let groups = /a(.)/g.exec("ab"); }').to.equa
l(`f() { | |
244 var groups = ((match) => new List.generate( | |
245 1 + match.groupCount, match.group))(new RegExp(r'a(.)').firstMatch("ab")); | |
246 }`); | |
247 expectErroneousWithType('function f() { var x = /a(.)/g; x.exec("ab")[1]; }'
) | |
248 .to.throw( | |
249 'exec is only supported on regexp literals, ' + | |
250 'to avoid side-effect of multiple calls on global regexps.'); | |
251 }); | |
252 | |
253 describe('promises', () => { | |
254 it('translates into Futures', () => { | |
255 expectWithTypes('let x: Promise = Promise.resolve(1);').to.equal(`import "
dart:async"; | |
256 | |
257 Future x = Future.value(1);`); | |
258 expectWithTypes('let x: Promise = Promise.reject(1);').to.equal(`import "d
art:async"; | |
259 | |
260 Future x = Future.error(1);`); | |
261 expectWithTypes('let x: Promise = new Promise((resolve) => {resolve(1);});
') | |
262 .to.equal(`import "dart:async"; | |
263 | |
264 Future x = (() { | |
265 Completer _completer$$ts2dart$0 = new Completer(); | |
266 var resolve = _completer$$ts2dart$0.complete; | |
267 (() { | |
268 resolve(1); | |
269 })(); | |
270 return _completer$$ts2dart$0.future; | |
271 })();`); | |
272 expectWithTypes('let x: Promise = new Promise((resolve, reject) => {resolv
e(1);});') | |
273 .to.equal(`import "dart:async"; | |
274 | |
275 Future x = (() { | |
276 Completer _completer$$ts2dart$0 = new Completer(); | |
277 var resolve = _completer$$ts2dart$0.complete; | |
278 var reject = _completer$$ts2dart$0.completeError; | |
279 (() { | |
280 resolve(1); | |
281 })(); | |
282 return _completer$$ts2dart$0.future; | |
283 })();`); | |
284 expectWithTypes('let x: Promise = new Promise((myParam1, myParam2) => {myP
aram1(1);});') | |
285 .to.equal(`import "dart:async"; | |
286 | |
287 Future x = (() { | |
288 Completer _completer$$ts2dart$0 = new Completer(); | |
289 var myParam1 = _completer$$ts2dart$0.complete; | |
290 var myParam2 = _completer$$ts2dart$0.completeError; | |
291 (() { | |
292 myParam1(1); | |
293 })(); | |
294 return _completer$$ts2dart$0.future; | |
295 })();`); | |
296 expectWithTypes( | |
297 'let x: Promise<any> = new Promise((resolve, reject) => {resolve(1);})
;' + | |
298 'function fn(): void { x.then((v) => { console.log(v) }).catch((err) =
> { console.log(err); }); }') | |
299 .to.equal(`import "dart:async"; | |
300 | |
301 Future<dynamic> x = (() { | |
302 Completer _completer$$ts2dart$0 = new Completer(); | |
303 var resolve = _completer$$ts2dart$0.complete; | |
304 var reject = _completer$$ts2dart$0.completeError; | |
305 (() { | |
306 resolve(1); | |
307 })(); | |
308 return _completer$$ts2dart$0.future; | |
309 })(); | |
310 void fn() { | |
311 x.then((v) { | |
312 print(v); | |
313 }).catchError((err) { | |
314 print(err); | |
315 }); | |
316 }`); | |
317 expectWithTypes( | |
318 'var fn: () => Promise<number>;' + | |
319 'function main() { fn().then((v) => { console.log(v) }).catch((err) =>
{ console.log(err); }); }') | |
320 .to.equal(`import "dart:async"; | |
321 | |
322 dynamic /* () => Promise<number> */ fn; | |
323 main() { | |
324 fn().then((v) { | |
325 print(v); | |
326 }).catchError((err) { | |
327 print(err); | |
328 }); | |
329 }`); | |
330 expectWithTypes( | |
331 'var fn: () => Promise<number>;' + | |
332 'function main() { fn().then((v) => { console.log(v) }, (err) => { con
sole.log(err); }); }') | |
333 .to.equal(`import "dart:async"; | |
334 | |
335 dynamic /* () => Promise<number> */ fn; | |
336 main() { | |
337 fn().then((v) { | |
338 print(v); | |
339 }).catchError((err) { | |
340 print(err); | |
341 }); | |
342 }`); | |
343 }); | 86 }); |
344 }); | 87 }); |
345 | 88 |
346 describe( | 89 describe('const', () => { |
347 'builtin functions', () => { | 90 it('simple', () => { |
348 it('translates CONST_EXPR(...) to const (...)', () => { | 91 expectWithTypes('const x = 1;').to.equal(`@JS() |
349 expectWithTypes( | 92 external get x;`); |
350 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + | 93 expectWithTypes('const x = [];').to.equal(`@JS() |
351 'const x = CONST_EXPR(1);') | 94 external get x;`); |
352 .to.equal('const x = 1;'); | 95 expectWithTypes( |
353 expectWithTypes( | 96 'class Person {}' + |
354 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + | 97 'const x = new Person();') |
355 'const x = CONST_EXPR([]);') | 98 .to.equal(`@JS() |
356 .to.equal('const x = const [];'); | 99 class Person { |
357 expectWithTypes( | 100 // @Ignore |
358 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + | 101 Person.fakeConstructor$(); |
359 'class Person {}' + | 102 } |
360 'const x = CONST_EXPR(new Person());') | |
361 .to.equal(`class Person {} | |
362 | 103 |
363 const x = const Person();`); | 104 @JS() |
364 expectWithTypes( | 105 external get x;`); |
365 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + | 106 }); |
366 'const x = CONST_EXPR({"one":1});') | 107 }); |
367 .to.equal('const x = const {"one": 1};'); | |
368 expectWithTypes( | |
369 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + | |
370 'import {Map} from "angular2/src/facade/collection";\n' + | |
371 'const x = CONST_EXPR(new Map());') | |
372 .to.equal(`import "package:angular2/src/facade/collection.dart" sh
ow Map; | |
373 | |
374 const x = const {};`); | |
375 expectWithTypes( | |
376 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + | |
377 'import {Map} from "angular2/src/facade/collection";\n' + | |
378 'const x = CONST_EXPR(new Map<number, string>());') | |
379 .to.equal(`import "package:angular2/src/facade/collection.dart" sh
ow Map; | |
380 | |
381 const x = const <num, String>{};`); | |
382 | |
383 expectWithTypes(` | |
384 import {CONST_EXPR} from "angular2/src/facade/lang"; | |
385 const _EMPTY_LIST = CONST_EXPR([]);`) | |
386 .to.equal(`const _EMPTY_LIST = const [];`); | |
387 expectWithTypes(` | |
388 import {CONST_EXPR} from "angular2/src/facade/lang"; | |
389 const _EMPTY_LIST = CONST_EXPR(<string[]>[]);`) | |
390 .to.equal(`const _EMPTY_LIST = const <String>[];`); | |
391 expectWithTypes(` | |
392 import {CONST_EXPR} from "angular2/src/facade/lang"; | |
393 const MY_MAP = CONST_EXPR(<{[k: string]: number}>{});`) | |
394 .to.equal(`const MY_MAP = const <String, num>{};`); | |
395 }); | |
396 | |
397 it('translates forwardRef(() => T) to T', | |
398 () => { | |
399 expectWithTypes( | |
400 'import {forwardRef} from "angular2/src/core/di/forward_ref";\n
' + | |
401 'var SomeType = 1;\n' + | |
402 'var x = forwardRef(() => SomeType);') | |
403 .to.equal(`var SomeType = 1; | |
404 var x = SomeType;`); | |
405 expectErroneousWithType(`import {forwardRef} from "angular2/src/cor
e/di/forward_ref"; | |
406 forwardRef(1)`).to.throw(/only arrow functions/); | |
407 }); | |
408 | |
409 it('erases calls to normalizeBlank', () => { | |
410 expectWithTypes( | |
411 'import {normalizeBlank} from "angular2/src/facade/lang";\n' + | |
412 'var x = normalizeBlank([]);') | |
413 .to.equal('var x = [];'); | |
414 }); | |
415 }); | |
416 | 108 |
417 it('translates array façades', () => { | 109 it('translates array façades', () => { |
418 expectWithTypes('function f() { var x = []; Array.isArray(x); }').to.equal(`
f() { | 110 expectWithTypes('function f() : string[] {}').to.equal(`@JS() |
419 var x = []; | 111 external List<String> f();`); |
420 ((x) is List); | |
421 }`); | |
422 }); | 112 }); |
423 | 113 |
424 describe('error detection', () => { | 114 describe('error detection', () => { |
425 describe('Map', () => { | 115 it('support imports', () => { |
426 it('.forEach() should report an error when the callback doesn\'t have 2 ar
gs', () => { | |
427 expectErroneousWithType('var x = new Map<string, string>(); x.forEach((v
, k, m) => null);') | |
428 .to.throw('Map.forEach callback requires exactly two arguments'); | |
429 }); | |
430 }); | |
431 | |
432 describe('Array', () => { | |
433 it('.concat() should report an error if any arg is not an Array', () => { | |
434 expectErroneousWithType('var x: Array<number> = []; x.concat(1);') | |
435 .to.throw('Array.concat only takes Array arguments'); | |
436 }); | |
437 }); | |
438 | |
439 it('for untyped symbols matching special cased fns', () => { | |
440 expectErroneousWithType('forwardRef(1)').to.throw(/Untyped property access
to "forwardRef"/); | |
441 }); | |
442 | |
443 it('for untyped symbols matching special cased methods', () => { | |
444 expectErroneousWithType('x.push(1)').to.throw(/Untyped property access to
"push"/); | |
445 }); | |
446 | |
447 it('allows unrelated methods', () => { | |
448 expectWithTypes( | 116 expectWithTypes( |
449 'import {X} from "other/file";\n' + | 117 'import {X} from "other/file";\n' + |
450 'var y = new X().map(1)') | 118 'let x:X;') |
451 .to.equal(`import "package:other/file.dart" show X; | 119 .to.equal(`import "package:other/file.dart" show X; |
452 | 120 |
453 var y = new X().map(1);`); | 121 @JS() |
454 expectWithTypes(`import {X} from "other/file"; | 122 external X get x; |
455 var y = X.get({"a": 1}, "a");`) | 123 @JS() |
456 .to.equal(`import "package:other/file.dart" show X; | 124 external set x(X v);`); |
457 | |
458 var y = X.get({"a": 1}, "a");`); | |
459 expectWithTypes('["a", "b"].map((x) => x);').to.equal('["a", "b"].map((x)
=> x).toList();'); | |
460 }); | 125 }); |
461 }); | 126 }); |
462 }); | 127 }); |
OLD | NEW |