| 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 {FAKE_MAIN, expectTranslate} 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 |