| // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| define(['dart_sdk'], function(dart_sdk) { | |
| const assert = chai.assert; | |
| const async = dart_sdk.async; | |
| const core = dart_sdk.core; | |
| const collection = dart_sdk.collection; | |
| const dart = dart_sdk.dart; | |
| const dartx = dart.dartx; | |
| dart.trapRuntimeErrors(false); | |
| suite('ignore', () => { | |
| "use strict"; | |
| let FutureOr = async.FutureOr$; | |
| let Future = async.Future$; | |
| let List = core.List$; | |
| setup(() => { | |
| dart_sdk.dart.ignoreWhitelistedErrors(false); | |
| }); | |
| teardown(() => { | |
| dart_sdk.dart.ignoreWhitelistedErrors(false); | |
| }); | |
| test('FutureOr', () => { | |
| let f = Future(dart.dynamic).value(42); | |
| let l = [1, 2, 3]; | |
| assert.throws(() => { dart.as(f, FutureOr(core.int)); }); | |
| assert.throws(() => { dart.as(l, FutureOr(List(core.int)))}); | |
| dart_sdk.dart.ignoreWhitelistedErrors(true); | |
| assert.equal(f, dart.as(f, FutureOr(core.int))); | |
| assert.equal(l, dart.as(l, FutureOr(List(core.int)))); | |
| }); | |
| }); | |
| suite('generic', () => { | |
| "use strict"; | |
| let generic = dart.generic; | |
| test('zero arguments is not allowed', () => { | |
| assert.throws(() => { generic(function(){}); }); | |
| }); | |
| test('dcall noSuchMethod has correct error target', () => { | |
| assert.throws(() => dart.dcall(42), | |
| new RegExp('NoSuchMethodError.*\nReceiver: 42', 'm'), | |
| 'Calls with non-function receiver should throw a NoSuchMethodError' + | |
| ' with correct target'); | |
| // TODO(jmesserly): we should show the name "print" in there somewhere. | |
| assert.throws(() => dart.dcall(core.print, 1, 2, 3), | |
| new RegExp('NoSuchMethodError.*\n' + | |
| "Receiver: Instance of '\\(Object\\) -> void'", 'm'), | |
| 'Calls with incorrect argument types should throw a NoSuchMethodError' + | |
| ' with correct target'); | |
| }); | |
| test('can throw number', () => { | |
| try { | |
| dart.throw(42); | |
| } catch (e) { | |
| assert.equal(e, 42); | |
| } | |
| }); | |
| test('argument count cannot change', () => { | |
| let SomeType = generic(function(x) { return {x: x}; }); | |
| assert.throws(() => { SomeType(1,2) }); | |
| let obj = {}; | |
| assert.equal(SomeType(obj).x, obj); | |
| assert.equal(SomeType(obj).x, obj); | |
| assert.equal(SomeType().x, dart.dynamic); | |
| }); | |
| test('undefined/null are not allowed', () => { | |
| let SomeType = generic(function(x) {}); | |
| assert.throws(() => { SomeType(void 0) }); | |
| SomeType(1); | |
| assert.throws(() => { SomeType(void 0) }); | |
| SomeType(1); | |
| assert.throws(() => { SomeType(null) }); | |
| }); | |
| test('result is memoized', () => { | |
| let t1 = Object.create(null); | |
| let t2 = Object.create(null); | |
| let count = 0; | |
| let SomeType = generic(function(x, y) { | |
| count++; | |
| return Object.create(null); | |
| }); | |
| let x12 = SomeType(1, 2); | |
| assert.strictEqual(SomeType(1, 2), x12); | |
| assert.strictEqual(SomeType(1, 2), x12); | |
| assert.strictEqual(count, 1); | |
| let x11 = SomeType(1, 1); | |
| assert.strictEqual(count, 2); | |
| assert.strictEqual(SomeType(1, 1), x11); | |
| assert.strictEqual(count, 2); | |
| count = 0; | |
| let t1t2 = SomeType(t1, t2); | |
| assert.strictEqual(count, 1); | |
| let t2t1 = SomeType(t2, t1); | |
| assert.strictEqual(count, 2); | |
| assert.notStrictEqual(t1t2, t2t1); | |
| assert.strictEqual(SomeType(t1, t2), t1t2); | |
| assert.strictEqual(SomeType(t2, t1), t2t1); | |
| assert.strictEqual(SomeType(t1, t2), t1t2); | |
| count = 0; | |
| // Nothing has been stored on the object | |
| assert.strictEqual(Object.keys(t1).length, 0); | |
| assert.strictEqual(Object.keys(t2).length, 0); | |
| }); | |
| test('type constructor is reflectable', () => { | |
| let SomeType = generic(function(x, y) { return Object.create(null); }); | |
| let someValue = SomeType('hi', 123); | |
| assert.equal(dart.getGenericClass(someValue), SomeType); | |
| assert.deepEqual(dart.getGenericArgs(someValue), ['hi', 123]); | |
| }); | |
| test('proper type constructor is called', () => { | |
| // This tests https://github.com/dart-lang/dev_compiler/issues/178 | |
| let l = dart_sdk._interceptors.JSArray$(core.int).of([1, 2, 3]); | |
| let s = l[dartx.join](); | |
| assert.equal(s, '123'); | |
| }); | |
| }); | |
| suite('instanceOf', () => { | |
| "use strict"; | |
| let expect = assert.equal; | |
| let generic = dart.generic; | |
| let intIsNonNullable = false; | |
| let cast = dart.as; | |
| let instanceOf = dart.is; | |
| let strongInstanceOf = dart.strongInstanceOf; | |
| let getReifiedType = dart.getReifiedType; | |
| let fnTypeFuzzy = dart.fnTypeFuzzy; | |
| let typedef = dart.typedef; | |
| let isSubtype = dart.isSubtype; | |
| let Object = core.Object; | |
| let String = core.String; | |
| let dynamic = dart.dynamic; | |
| let List = core.List; | |
| let Map = core.Map; | |
| let Map$ = core.Map$; | |
| let double = core.double; | |
| let int = core.int; | |
| let num = core.num; | |
| let bool = core.bool; | |
| class A {} | |
| class B extends A {} | |
| class C extends B {} | |
| let AA$ = generic((T, U) => { | |
| class AA extends core.Object {} | |
| (AA.new = function() {}).prototype = AA.prototype; | |
| return AA; | |
| }); | |
| let AA = AA$(); | |
| let BB$ = generic((T, U) => { | |
| class BB extends AA$(U, T) {} | |
| (BB.new = function() {}).prototype = BB.prototype; | |
| return BB; | |
| }); | |
| let BB = BB$(); | |
| class CC extends BB$(String, List) {} | |
| (CC.new = function() {}).prototype = CC.prototype; | |
| let Func2 = typedef('Func2', () => fnTypeFuzzy(dynamic, [dynamic, dynamic])); | |
| let Foo = typedef('Foo', () => fnTypeFuzzy(B, [B, String])); | |
| let FuncG$ = generic((T, U) => typedef('FuncG', () => fnTypeFuzzy(T, [T, U]))) | |
| let FuncG = FuncG$(); | |
| // TODO(vsm): Revisit when we encode types on functions properly. | |
| // A bar1(C c, String s) => null; | |
| function bar1(c, s) { return null; } | |
| dart.fn(bar1, dart.fnType(A, [C, String])); | |
| // bar2(B b, String s) => null; | |
| function bar2(b, s) { return null; } | |
| dart.fn(bar2, dart.fnType(dynamic, [B, String])); | |
| // B bar3(B b, Object o) => null; | |
| function bar3(b, o) { return null; } | |
| dart.fn(bar3, dart.fnType(B, [B, Object])); | |
| // B bar4(B b, o) => null; | |
| function bar4(b, o) { return null; } | |
| dart.fn(bar4, dart.fnType(B, [B, dynamic])); | |
| // C bar5(A a, Object o) => null; | |
| function bar5(a, o) { return null; } | |
| dart.fn(bar5, dart.fnType(C, [A, Object])); | |
| // B bar6(B b, String s, String o) => null; | |
| function bar6(b, s, o) { return null; } | |
| dart.fn(bar6, dart.fnType(B, [B, String, String])); | |
| // B bar7(B b, String s, [Object o]) => null; | |
| function bar7(b, s, o) { return null; } | |
| dart.fn(bar7, dart.fnType(B, [B, String], [Object])); | |
| // B bar8(B b, String s, {Object p}) => null; | |
| function bar8(b, s, o) { return null; } | |
| dart.fn(bar8, dart.fnType(B, [B, String], {p: Object})); | |
| let cls1 = dart.fn((c, s) => { return null; }, | |
| dart.fnType(A, [C, String])); | |
| let cls2 = dart.fn((b, s) => { return null; }, | |
| dart.fnType(dynamic, [B, String])); | |
| let cls3 = dart.fn((b, o) => { return null; }, | |
| dart.fnType(B, [B, Object])); | |
| let cls4 = dart.fn((b, o) => { return null; }, | |
| dart.fnType(B, [B, dynamic])); | |
| let cls5 = dart.fn((a, o) => { return null; }, | |
| dart.fnType(C, [A, Object])); | |
| let cls6 = dart.fn((b, s, o) => { return null; }, | |
| dart.fnType(B, [B, String, String])); | |
| let cls7 = dart.fn((b, s, o) => { return null; }, | |
| dart.fnType(B, [B, String], [Object])); | |
| let cls8 = | |
| dart.fn((b, s, o) => { return null; }, | |
| dart.fnType(B, [B, String], {p: Object})); | |
| function checkType(x, type, expectedTrue) { | |
| if (expectedTrue === undefined) expectedTrue = true; | |
| expect(instanceOf(x, type), expectedTrue, | |
| '"' + x + '" ' + | |
| (expectedTrue ? 'should' : 'should not') + | |
| ' be an instance of "' + dart.typeName(type) + '"'); | |
| } | |
| test('int', () => { | |
| checkType(5, int); | |
| checkType(5, dynamic); | |
| checkType(5, Object); | |
| checkType(5, num); | |
| checkType(5, bool, false); | |
| checkType(5, String, false); | |
| expect(cast(5, int), 5); | |
| if (intIsNonNullable) { | |
| expect(() => cast(null, int), throws); | |
| } else { | |
| expect(cast(null, int), null); | |
| } | |
| }); | |
| test('dynamic', () => { | |
| checkType(new Object.new(), dynamic); | |
| checkType(null, dynamic); | |
| expect(cast(null, dynamic), null); | |
| }); | |
| test('Object', () => { | |
| checkType(new Object.new(), dynamic); | |
| checkType(null, Object); | |
| expect(cast(null, Object), null); | |
| }); | |
| test('null', () => { | |
| // Object, dynamic cases are already handled above. | |
| checkType(null, core.Null); | |
| checkType(null, core.String, false); | |
| checkType(null, core.int, false); | |
| checkType(null, Map, false); | |
| checkType(void 0, core.Null); | |
| checkType(void 0, core.Object); | |
| checkType(void 0, dart.dynamic); | |
| }); | |
| test('String', () => { | |
| checkType("foo", String); | |
| checkType("foo", Object); | |
| checkType("foo", dynamic); | |
| expect(cast(null, String), null); | |
| }); | |
| test('FutureOr', () => { | |
| let FutureOr = async.FutureOr$; | |
| assert.equal(dart.as(3, FutureOr(int)), 3); | |
| assert.equal(dart.as(3, FutureOr(double)), 3); | |
| assert.throws(() => dart.as(3.5, FutureOr(int))); | |
| assert.equal(dart.as(3.5, FutureOr(double)), 3.5); | |
| assert.isTrue(dart.is(3, FutureOr(int))); | |
| assert.isTrue(dart.is(3, FutureOr(double))); | |
| assert.isFalse(dart.is(3.5, FutureOr(int))); | |
| assert.isTrue(dart.is(3.5, FutureOr(double))); | |
| assert.equal(dart.as(3, FutureOr(FutureOr(double))), 3); | |
| assert.isTrue(dart.is(3, FutureOr(FutureOr(double)))); | |
| }); | |
| test('Map', () => { | |
| let m1 = Map$(String, String).new(); | |
| let m2 = Map$(Object, Object).new(); | |
| let m3 = Map.new(); | |
| let m4 = collection.HashMap$(dart.dynamic, dart.dynamic).new(); | |
| let m5 = collection.LinkedHashMap.new(); | |
| let m6 = Map$(String, dart.dynamic).new(); | |
| // Map<T1,T2> <: Map | |
| checkType(m1, Map); | |
| checkType(m1, Object); | |
| // Instance of self | |
| checkType(m1, getReifiedType(m1)); | |
| checkType(m1, Map$(String, String)); | |
| // Covariance on generics | |
| checkType(m1, getReifiedType(m2)); | |
| checkType(m1, Map$(Object, Object)); | |
| // No contravariance on generics. | |
| checkType(m2, getReifiedType(m1), false); | |
| checkType(m2, Map$(String, String), false); | |
| // null is! Map | |
| checkType(null, Map, false); | |
| // Raw generic types | |
| checkType(m5, Map); | |
| checkType(m4, Map); | |
| // Is checks | |
| assert.isFalse(dart.is(m3, Map$(String, String))); | |
| assert.isFalse(dart.is(m6, Map$(String, String))); | |
| assert.isTrue(dart.is(m1, Map$(String, String))); | |
| assert.isFalse(dart.is(m2, Map$(String, String))); | |
| // As checks | |
| // TODO(vsm): Enable these. We're currently only logging warnings on | |
| // StrongModeErrors. | |
| // assert.throws(() => dart.as(m3, Map$(String, String)), | |
| // dart.StrongModeError); | |
| // assert.throws(() => dart.as(m6, Map$(String, String)), | |
| // dart.StrongModeError); | |
| assert.equal(dart.as(m1, Map$(String, String)), m1); | |
| // assert.throws(() => dart.as(m2, Map$(String, String)), | |
| // dart.StrongModeError); | |
| }); | |
| test('constructors', () => { | |
| class C extends core.Object { | |
| } | |
| (C.new = function(x) {}).prototype = C.prototype; | |
| (C.named = function(x, y) {}).prototype = C.prototype; | |
| dart.setSignature(C, { | |
| constructors: () => ({ | |
| new: dart.fnType(C, [core.int]), | |
| named: dart.fnType(C, [core.int, core.int]) | |
| }) | |
| }); | |
| let getType = dart.classGetConstructorType; | |
| isSubtype(getType(C), dart.fnTypeFuzzy(C, [core.int])); | |
| isSubtype(getType(C), dart.fnTypeFuzzy(C, [core.String]), false); | |
| isSubtype(getType(C, 'new'), dart.fnTypeFuzzy(C, [core.int])); | |
| isSubtype(getType(C, 'new'), dart.fnTypeFuzzy(C, [core.String]), false); | |
| isSubtype(getType(C, 'named'), dart.fnTypeFuzzy(C, [core.int, core.int])); | |
| isSubtype(getType(C, 'named'), | |
| dart.fnTypeFuzzy(C, [core.int, core.String]), false); | |
| }); | |
| test('generic and inheritance', () => { | |
| let aaraw = new AA.new(); | |
| let aarawtype = getReifiedType(aaraw); | |
| let aadynamic = new (AA$(dynamic, dynamic).new)(); | |
| let aadynamictype = getReifiedType(aadynamic); | |
| let aa = new (AA$(String, List).new)(); | |
| let aatype = getReifiedType(aa); | |
| let bb = new (BB$(String, List).new)(); | |
| let bbtype = getReifiedType(bb); | |
| let cc = new CC.new(); | |
| let cctype = getReifiedType(cc); | |
| // We don't allow constructing bad types. | |
| // This was AA<String> in Dart (wrong number of type args). | |
| let aabad = new (AA$(dart.dynamic, dart.dynamic).new)(); | |
| let aabadtype = getReifiedType(aabad); | |
| checkType(cc, aatype, false); | |
| checkType(cc, AA$(String, List), false); | |
| checkType(cc, bbtype); | |
| checkType(cc, BB$(String, List)); | |
| checkType(aa, cctype, false); | |
| checkType(aa, CC, false); | |
| checkType(aa, bbtype, false); | |
| checkType(aa, BB$(String, List), false); | |
| checkType(bb, cctype, false); | |
| checkType(bb, CC, false); | |
| checkType(aa, aabadtype); | |
| checkType(aa, dynamic); | |
| checkType(aabad, aatype, false); | |
| checkType(aabad, AA$(String, List), false); | |
| checkType(aabad, aarawtype); | |
| checkType(aabad, AA); | |
| checkType(aaraw, aabadtype); | |
| checkType(aaraw, AA$(dart.dynamic, dart.dynamic)); | |
| checkType(aaraw, aadynamictype); | |
| checkType(aaraw, AA$(dynamic, dynamic)); | |
| checkType(aadynamic, aarawtype); | |
| checkType(aadynamic, AA); | |
| }); | |
| test('void', () => { | |
| //checkType((x) => x, type((void _(x)) {})); | |
| }); | |
| test('mixins', () => { | |
| let c = collection; | |
| var s1 = new (c.SplayTreeSet$(String).new)(); | |
| checkType(s1, c.IterableMixin); | |
| checkType(s1, c.IterableMixin$(String)); | |
| checkType(s1, c.IterableMixin$(int), false); | |
| checkType(s1, c.SetMixin); | |
| checkType(s1, c.SetMixin$(String)); | |
| checkType(s1, c.SetMixin$(int), false); | |
| }); | |
| test('Type', () => { | |
| checkType(int, core.Type, true); | |
| checkType(num, core.Type, true); | |
| checkType(bool, core.Type, true); | |
| checkType(String, core.Type, true); | |
| checkType(dynamic, core.Type, true); | |
| checkType(Object, core.Type, true); | |
| checkType(List, core.Type, true); | |
| checkType(Map, core.Type, true); | |
| checkType(Map$(int, String), core.Type, true); | |
| checkType(Func2, core.Type, true); | |
| checkType(fnTypeFuzzy(dynamic, [dynamic]), core.Type, true); | |
| checkType(core.Type, core.Type, true); | |
| checkType(3, core.Type, false); | |
| checkType("hello", core.Type, false); | |
| }) | |
| test('Functions', () => { | |
| // - return type: Dart is bivariant. We're covariant. | |
| // - param types: Dart is bivariant. We're contravariant. | |
| checkType(bar1, Foo, false); | |
| checkType(cls1, Foo, false); | |
| checkType(bar1, fnTypeFuzzy(B, [B, String]), false); | |
| checkType(cls1, fnTypeFuzzy(B, [B, String]), false); | |
| checkType(bar2, Foo, false); | |
| checkType(cls2, Foo, false); | |
| checkType(bar2, fnTypeFuzzy(B, [B, String]), false); | |
| checkType(cls2, fnTypeFuzzy(B, [B, String]), false); | |
| checkType(bar3, Foo); | |
| checkType(cls3, Foo); | |
| checkType(bar3, fnTypeFuzzy(B, [B, String])); | |
| checkType(cls3, fnTypeFuzzy(B, [B, String])); | |
| checkType(bar4, Foo, true); | |
| checkType(cls4, Foo, true); | |
| checkType(bar4, fnTypeFuzzy(B, [B, String]), true); | |
| checkType(cls4, fnTypeFuzzy(B, [B, String]), true); | |
| checkType(bar5, Foo); | |
| checkType(cls5, Foo); | |
| checkType(bar5, fnTypeFuzzy(B, [B, String])); | |
| checkType(cls5, fnTypeFuzzy(B, [B, String])); | |
| checkType(bar6, Foo, false); | |
| checkType(cls6, Foo, false); | |
| checkType(bar6, fnTypeFuzzy(B, [B, String]), false); | |
| checkType(cls6, fnTypeFuzzy(B, [B, String]), false); | |
| checkType(bar7, Foo); | |
| checkType(cls7, Foo); | |
| checkType(bar7, fnTypeFuzzy(B, [B, String])); | |
| checkType(cls7, fnTypeFuzzy(B, [B, String])); | |
| checkType(bar7, getReifiedType(bar6)); | |
| checkType(cls7, getReifiedType(bar6)); | |
| checkType(bar8, Foo); | |
| checkType(cls8, Foo); | |
| checkType(bar8, fnTypeFuzzy(B, [B, String])); | |
| checkType(cls8, fnTypeFuzzy(B, [B, String])); | |
| checkType(bar8, getReifiedType(bar6), false); | |
| checkType(cls8, getReifiedType(bar6), false); | |
| checkType(bar7, getReifiedType(bar8), false); | |
| checkType(cls7, getReifiedType(bar8), false); | |
| checkType(bar8, getReifiedType(bar7), false); | |
| checkType(cls8, getReifiedType(bar7), false); | |
| // Parameterized typedefs | |
| checkType(bar1, FuncG$(B, String), false); | |
| checkType(cls1, FuncG$(B, String), false); | |
| checkType(bar3, FuncG$(B, String)); | |
| checkType(cls3, FuncG$(B, String)); | |
| }); | |
| test('dcall', () => { | |
| function dd2d(x, y) {return x}; | |
| dart.fn(dd2d); | |
| function ii2i(x, y) {return x}; | |
| dart.fn(ii2i, dart.fnType(core.int, [core.int, core.int])); | |
| function ii_2i(x, y) {return x}; | |
| dart.fn(ii_2i, dart.fnType(core.int, [core.int], [core.int])); | |
| function i_i2i(x, opts) {return x}; | |
| dart.fn(i_i2i, | |
| dart.fnType(core.int, [core.int], {extra: core.int})); | |
| assert.equal(dart.dcall(dd2d, 0, 1), 0); | |
| assert.equal(dart.dcall(dd2d, "hello", "world"), "hello"); | |
| assert.throws(() => dart.dcall(dd2d, 0)); | |
| assert.throws(() => dart.dcall(dd2d, 0, 1, 2)); | |
| assert.throws(() => dart.dcall(dd2d, 0, 1, {extra : 3})); | |
| // This should throw but currently doesn't. | |
| // assert.throws(() => dart.dcall(dd2d, 0, {extra:3})); | |
| assert.equal(dart.dcall(ii2i, 0, 1), 0); | |
| assert.throws(() => dart.dcall(ii2i, "hello", "world")); | |
| assert.throws(() => dart.dcall(ii2i, 0)); | |
| assert.throws(() => dart.dcall(ii2i, 0, 1, 2)); | |
| assert.equal(dart.dcall(ii_2i, 0, 1), 0); | |
| assert.throws(() => dart.dcall(ii_2i, "hello", "world")); | |
| assert.equal(dart.dcall(ii_2i, 0), 0); | |
| assert.throws(() => dart.dcall(ii_2i, 0, 1, 2)); | |
| assert.throws(() => dart.dcall(i_i2i, 0, 1)); | |
| assert.throws(() => dart.dcall(i_i2i, "hello", "world")); | |
| assert.equal(dart.dcall(i_i2i, 0), 0); | |
| assert.throws(() => dart.dcall(i_i2i, 0, 1, 2)); | |
| assert.equal(dart.dcall(i_i2i, 0, {extra: 3}), 0); | |
| }); | |
| test('dsend', () => { | |
| class Tester extends core.Object { | |
| m(x, y) {return x;} | |
| call(x) {return x;} | |
| static s(x, y) { return x;} | |
| } | |
| (Tester.new = function() { | |
| this.f = dart.fn(x => x, | |
| dart.fnType(core.int, [core.int])); | |
| this.me = this; | |
| }).prototype = Tester.prototype; | |
| dart.setSignature(Tester, { | |
| methods: () => ({ | |
| m: dart.fnType(core.int, [core.int, core.int]), | |
| call: dart.fnType(core.int, [core.int]) | |
| }), | |
| statics: () => ({ | |
| s: dart.fnType(core.String, [core.String]) | |
| }), | |
| names: ['s'] | |
| }) | |
| let o = new Tester.new(); | |
| // Method send | |
| assert.equal(dart.dsend(o, 'm', 3, 4), 3); | |
| assert.equal(dart.dsend(o, 'm', null, 4), null); | |
| assert.throws(() => dart.dsend(o, 'm', 3)); | |
| assert.throws(() => dart.dsend(o, 'm', "hello", "world")); | |
| assert.throws(() => dart.dsend(o, 'q', 3)); | |
| // Method send through a field | |
| assert.equal(dart.dsend(o, 'f', 3), 3); | |
| assert.equal(dart.dsend(o, 'f', null), null); | |
| assert.throws(() => dart.dsend(o, 'f', "hello")); | |
| assert.throws(() => dart.dsend(o, 'f', 3, 4)); | |
| // Static method call | |
| assert.equal(dart.dcall(Tester.s, "hello"), "hello"); | |
| assert.equal(dart.dcall(Tester.s, null), null); | |
| assert.throws(() => dart.dcall(Tester.s, "hello", "world")); | |
| assert.throws(() => dart.dcall(Tester.s, 0, 1)); | |
| // Calling an object with a call method | |
| assert.equal(dart.dcall(o, 3), 3); | |
| assert.equal(dart.dcall(o, null), null); | |
| assert.throws(() => dart.dcall(o, "hello")); | |
| assert.throws(() => dart.dcall(o, 3, 4)); | |
| // Calling through a field containing an object with a call method | |
| assert.equal(dart.dsend(o, 'me', 3), 3); | |
| assert.equal(dart.dsend(o, 'me', null), null); | |
| assert.throws(() => dart.dsend(o, 'me', "hello")); | |
| assert.throws(() => dart.dsend(o, 'me', 3, 4)); | |
| }); | |
| test('Types on top level functions', () => { | |
| // Test some generated code | |
| // Test the lazy path | |
| checkType(core.identityHashCode, | |
| dart.fnTypeFuzzy(core.int, [core.Object])); | |
| // Test the normal path | |
| checkType(core.identical, | |
| dart.fnTypeFuzzy(core.bool, | |
| [core.Object, core.Object])); | |
| // Hand crafted tests | |
| // All dynamic | |
| function dd2d(x, y) {return x}; | |
| dart.fn(dd2d); | |
| checkType(dd2d, dart.fnTypeFuzzy(dart.dynamic, | |
| [dart.dynamic, dart.dynamic])); | |
| // Set the type eagerly | |
| function ii2i(x, y) {return x}; | |
| dart.fn(ii2i, dart.fnType(core.int, [core.int, core.int])); | |
| checkType(ii2i, dart.fnTypeFuzzy(core.int, | |
| [core.int, core.int])); | |
| // Set the type lazily | |
| function ss2s(x, y) {return x}; | |
| var coreString; | |
| dart.lazyFn(ss2s, | |
| () => dart.fnType(coreString, | |
| [coreString, coreString])); | |
| coreString = core.String; | |
| checkType(ss2s, dart.fnTypeFuzzy(core.String, | |
| [core.String, core.String])); | |
| // Optional types | |
| function ii_2i(x, y) {return x}; | |
| dart.fn(ii_2i, dart.fnType(core.int, [core.int], [core.int])); | |
| checkType(ii_2i, dart.fnTypeFuzzy(core.int, [core.int], | |
| [core.int])); | |
| checkType(ii_2i, dart.fnTypeFuzzy(core.int, [core.int, | |
| core.int])); | |
| checkType(ii_2i, dart.fnTypeFuzzy(core.int, [], [core.int, | |
| core.int]), | |
| false); | |
| checkType(ii_2i, dart.fnTypeFuzzy(core.int, [core.int], | |
| {extra: core.int}), false); | |
| // Named types | |
| function i_i2i(x, opts) {return x}; | |
| dart.fn(i_i2i, dart.fnType(core.int, [core.int], | |
| {extra: core.int})); | |
| checkType(i_i2i, dart.fnTypeFuzzy(core.int, [core.int], | |
| {extra: core.int})); | |
| checkType(i_i2i, dart.fnTypeFuzzy(core.int, | |
| [core.int, core.int]), false); | |
| checkType(i_i2i, dart.fnTypeFuzzy(core.int, [core.int], {})); | |
| checkType(i_i2i, | |
| dart.fnTypeFuzzy(core.int, [], {extra: core.int, | |
| also: core.int}), false); | |
| checkType(i_i2i, | |
| dart.fnTypeFuzzy(core.int, [core.int], [core.int]), false); | |
| }); | |
| test('Method tearoffs', () => { | |
| let c = collection; | |
| // Tear off of an inherited method | |
| let map = Map$(core.int, core.String).new(); | |
| checkType(dart.bind(map, 'toString'), | |
| dart.fnTypeFuzzy(String, [])); | |
| checkType(dart.bind(map, 'toString'), | |
| dart.fnTypeFuzzy(int, []), false, true); | |
| // Tear off of a method directly on the object | |
| let smap = new (c.SplayTreeMap$(core.int, core.String).new)(); | |
| checkType(dart.bind(smap, 'forEach'), | |
| dart.fnTypeFuzzy(dart.void, | |
| [dart.fnTypeFuzzy(dart.void, [core.int, core.String])])); | |
| checkType(dart.bind(smap, 'forEach'), | |
| dart.fnTypeFuzzy(dart.void, | |
| [dart.fnTypeFuzzy(dart.void, | |
| [core.String, core.String])]), false, true); | |
| // Tear off of a mixed in method | |
| let mapB = new (c.MapBase$(core.int, core.int).new)(); | |
| checkType(dart.bind(mapB, 'forEach'), | |
| dart.fnTypeFuzzy(dart.void, [ | |
| dart.fnTypeFuzzy(dart.void, [core.int, core.int])])); | |
| checkType(dart.bind(mapB, 'forEach'), | |
| dart.fnTypeFuzzy(dart.void, [ | |
| dart.fnTypeFuzzy(dart.void, [core.int, core.String])]), | |
| false, true); | |
| // Tear off of a method with a symbol name | |
| let listB = new (c.ListBase$(core.int).new)(); | |
| // List.add is reified as taking Object | |
| checkType(dart.bind(listB, dartx.add), | |
| dart.fnTypeFuzzy(dart.void, [core.int])); | |
| checkType(dart.bind(listB, dartx.add), | |
| dart.fnTypeFuzzy(dart.void, [core.String]), true); | |
| checkType(dart.bind(listB, dartx.removeAt), | |
| dart.fnTypeFuzzy(dart.void, [core.String]), false); | |
| // Tear off of a static method | |
| checkType(c.ListBase.listToString, | |
| dart.fnTypeFuzzy(core.String, [core.List])); | |
| checkType(c.ListBase.listToString, | |
| dart.fnTypeFuzzy(core.String, [core.String]), false); | |
| // Tear-off of extension methods on primitives | |
| checkType(dart.bind(3.0, dartx.floor), | |
| dart.fnTypeFuzzy(core.int, [])); | |
| checkType(dart.bind(3.0, dartx.floor), | |
| dart.fnTypeFuzzy(core.String, []), false); | |
| checkType(dart.bind("", dartx.endsWith), | |
| dart.fnTypeFuzzy(core.bool, [core.String])); | |
| checkType(dart.bind("", dartx.endsWith), | |
| dart.fnTypeFuzzy(core.bool, [core.int]), false); | |
| // Tear off a mixin method | |
| class Base { | |
| m(x) {return x;} | |
| }; | |
| dart.setSignature(Base, { | |
| methods: () => ({ | |
| m: dart.fnType(core.int, [core.int]), | |
| }) | |
| }); | |
| class M1 { | |
| m(x) {return x;} | |
| }; | |
| dart.setSignature(M1, { | |
| methods: () => ({ | |
| m: dart.fnType(core.num, [core.int]), | |
| }) | |
| }); | |
| class M2 { | |
| m(x) {return x;} | |
| }; | |
| dart.setSignature(M2, { | |
| methods: () => ({ | |
| m: dart.fnType(core.Object, [core.int]), | |
| }) | |
| }); | |
| class O extends dart.mixin(Base, M1, M2) {} | |
| (O.new = function() {}).prototype = O.prototype; | |
| dart.setSignature(O, {}); | |
| var obj = new O.new(); | |
| var m = dart.bind(obj, 'm'); | |
| checkType(m, dart.fnTypeFuzzy(core.Object, [core.int])); | |
| checkType(m, dart.fnTypeFuzzy(core.int, [core.int]), false); | |
| // Test inherited signatures | |
| class P extends O { | |
| m(x) {return x;}; | |
| }; | |
| (P.new = function() {}).prototype = P.prototype; | |
| dart.setSignature(P, {}); | |
| var obj = new P.new(); | |
| var m = dart.bind(obj, 'm'); | |
| checkType(m, dart.fnTypeFuzzy(core.Object, [core.int])); | |
| checkType(m, dart.fnTypeFuzzy(core.int, [core.int]), false); | |
| }); | |
| test('Object members', () => { | |
| let nullHash = dart.hashCode(null); | |
| assert.equal(nullHash, 0); | |
| let nullString = dart.toString(null); | |
| assert.equal(nullString, 'null'); | |
| let map = Map.new(); | |
| let mapHash = dart.hashCode(map); | |
| checkType(mapHash, core.int); | |
| assert.equal(mapHash, map.hashCode); | |
| let mapString = dart.toString(map); | |
| assert.equal(mapString, map.toString()); | |
| checkType(mapString, core.String); | |
| let str = "A string"; | |
| let strHash = dart.hashCode(str); | |
| checkType(strHash, core.int); | |
| let strString = dart.toString(str); | |
| checkType(strString, core.String); | |
| assert.equal(str, strString); | |
| let n = 42; | |
| let intHash = dart.hashCode(n); | |
| checkType(intHash, core.int); | |
| let intString = dart.toString(n); | |
| assert.equal(intString, '42'); | |
| }); | |
| }); | |
| suite('subtyping', function() { | |
| 'use strict'; | |
| let fnTypeFuzzy = dart.fnTypeFuzzy; | |
| let fnType = dart.fnType; | |
| let typedef = dart.typedef; | |
| let isSubtype = dart.isSubtype; | |
| let int = core.int; | |
| let num = core.num; | |
| let dyn = dart.dynamic; | |
| function always(t1, t2) { | |
| assert.equal(isSubtype(t1, t2), true, | |
| dart.toString(t1) + | |
| " should always be a subtype of " + | |
| dart.toString(t2)); | |
| } | |
| function never(t1, t2) { | |
| assert.equal(isSubtype(t1, t2), false, | |
| dart.toString(t1) + | |
| " should never be a subtype of " + | |
| dart.toString(t2)); | |
| } | |
| function maybe(t1, t2) { | |
| assert.equal(isSubtype(t1, t2), null, | |
| dart.toString(t1) + | |
| " should maybe be a subtype of " + | |
| dart.toString(t2)); | |
| } | |
| function always2(t1, t2) { | |
| always(t1, t2); | |
| always(fnTypeFuzzy(t1, [t2]), fnTypeFuzzy(t2, [t1])); | |
| } | |
| function never2(t1, t2) { | |
| never(t1, t2); | |
| maybe(fnTypeFuzzy(t1, [t2]), fnTypeFuzzy(t2, [t1])); | |
| } | |
| function maybe2(t1, t2) { | |
| maybe(t1, t2); | |
| maybe(fnTypeFuzzy(t1, [t2]), fnTypeFuzzy(t2, [t1])); | |
| } | |
| function run_test(func1, func2, func2opt, func1extra, func2extra) { | |
| always2(func2(int, int), func2(int, int)); | |
| always2(func2(int, num), func2(int, int)); | |
| always2(func2(int, int), func2(num, int)); | |
| always2(func2opt(int, int), func2opt(int, int)); | |
| always2(func2opt(int, num), func2opt(int, int)); | |
| always2(func2opt(int, int), func2opt(num, int)); | |
| always2(func2opt(int, int), func2(int, int)); | |
| always2(func2opt(int, num), func2(int, int)); | |
| always2(func2opt(int, int), func2(num, int)); | |
| always2(func2opt(int, int), func1(int)); | |
| always2(func2opt(int, num), func1(int)); | |
| always2(func2opt(int, int), func1(num)); | |
| always2(func2extra(int, int), func2(int, int)); | |
| always2(func2extra(int, num), func2(int, int)); | |
| always2(func2extra(int, int), func2(num, int)); | |
| maybe2(func2(int, int), func2(int, num)); | |
| maybe2(func2(num, int), func2(int, int)); | |
| maybe2(func2opt(num, num), func1(int)); | |
| maybe2(func2opt(int, int), func2opt(int, num)); | |
| maybe2(func2opt(num, int), func2opt(int, int)); | |
| maybe2(func2opt(int, int), func2(int, num)); | |
| maybe2(func2opt(num, int), func2(int, int)); | |
| maybe2(func2extra(int, int), func2(int, num)); | |
| maybe2(func2extra(num, int), func2(int, int)); | |
| never2(func1(int), func2(int, num)); | |
| never2(func1(num), func2(int, int)); | |
| never2(func1(num), func2(num, num)); | |
| never2(func2(int, int), func1(int)); | |
| never2(func2(num, int), func1(int)); | |
| never2(func2(num, num), func1(num)); | |
| never2(func1(int), func2opt(int, num)); | |
| never2(func1(num), func2opt(int, int)); | |
| never2(func1(num), func2opt(num, num)); | |
| never2(func2(int, int), func2opt(int, num)); | |
| never2(func2(num, int), func2opt(int, int)); | |
| never2(func2(num, num), func2opt(num, num)); | |
| never2(func1extra(int), func2(int, num)); | |
| never2(func1extra(num), func2(int, int)); | |
| never2(func1extra(num), func2(num, num)); | |
| never2(func1extra(int), func2opt(int, num)); | |
| never2(func1extra(num), func2opt(int, int)); | |
| never2(func1extra(num), func2opt(num, num)); | |
| never2(func1(int), func1extra(int)); | |
| never2(func1(num), func1extra(int)); | |
| never2(func1(num), func1extra(num)); | |
| never2(func2(int, int), func1extra(int)); | |
| never2(func2(num, int), func1extra(int)); | |
| never2(func2(num, num), func1extra(num)); | |
| never2(func2(int, int), func2extra(int, int)); | |
| never2(func2(num, int), func2extra(int, int)); | |
| never2(func2(num, num), func2extra(num, num)); | |
| }; | |
| test('basic function types', () => { | |
| function func1(S) { | |
| return fnTypeFuzzy(S, []); | |
| } | |
| function func2(S, T) { | |
| return fnTypeFuzzy(S, [T]); | |
| } | |
| function func2opt(S, T) { | |
| return fnTypeFuzzy(S, [], [T]); | |
| } | |
| function func1extra(S) { | |
| return fnTypeFuzzy(S, [], {extra: int}); | |
| } | |
| function func2extra(S, T) { | |
| return fnTypeFuzzy(S, [T], {extra: int}); | |
| } | |
| run_test(func1, func2, func2opt, func1extra, func2extra); | |
| }); | |
| test('top and bottom types', () => { | |
| let FutureOr = async.FutureOr$; | |
| let tops = [ | |
| dart.dynamic, | |
| core.Object, | |
| dart.void, | |
| FutureOr(dart.dynamic), | |
| FutureOr(core.Object), | |
| FutureOr(dart.void), | |
| FutureOr(FutureOr(core.Object)), | |
| // ... skip the (infinite) rest of the top types :D | |
| ]; | |
| let bottoms = [dart.bottom, core.Null]; | |
| for (let top of tops) { | |
| for (let bottom of bottoms) { | |
| always(bottom, top); | |
| always( | |
| fnType(bottom, [top]), | |
| fnType(top, [bottom])); | |
| } | |
| } | |
| for (let equalTypes of [tops, bottoms]) { | |
| for (let t1 of equalTypes) { | |
| for (let t2 of equalTypes) { | |
| always(t1, t2); | |
| always(t2, t1); | |
| let t11 = fnType(t1, [t1]); | |
| let t22 = fnType(t2, [t2]); | |
| always(t11, t22); | |
| always(t22, t11); | |
| } | |
| } | |
| } | |
| }); | |
| test('basic typedefs', () => { | |
| function func1(S) { | |
| return dart.typedef('Func1', () => fnTypeFuzzy(S, [])) | |
| } | |
| function func2(S, T) { | |
| return dart.typedef('Func2', () => fnTypeFuzzy(S, [T])) | |
| } | |
| function func2opt(S, T) { | |
| return dart.typedef('Func2', () => fnTypeFuzzy(S, [], [T])) | |
| } | |
| function func1extra(S) { | |
| return dart.typedef('Func1', () => fnTypeFuzzy(S, [], {extra: int})) | |
| } | |
| function func2extra(S, T) { | |
| return dart.typedef('Func2', () => fnTypeFuzzy(S, [T], {extra: int})) | |
| } | |
| run_test(func1, func2, func2opt, func1extra, func2extra); | |
| }); | |
| test('basic generic typedefs', () => { | |
| let func1 = dart.generic( | |
| (S) => dart.typedef('Func1', () => fnTypeFuzzy(S, []))); | |
| let func2 = dart.generic( | |
| (S, T) => dart.typedef('Func2', () => fnTypeFuzzy(S, [T]))); | |
| let func2opt = dart.generic( | |
| (S, T) => dart.typedef('Func2', () => fnTypeFuzzy(S, [], [T]))); | |
| let func1extra = dart.generic( | |
| (S) => dart.typedef('Func1', () => fnTypeFuzzy(S, [], {extra: int}))); | |
| let func2extra = dart.generic( | |
| (S, T) => dart.typedef('Func2', | |
| () => fnTypeFuzzy(S, [T], {extra: int}))); | |
| run_test(func1, func2, func2opt, func1extra, func2extra); | |
| }); | |
| test('fuzzy function types', () => { | |
| always(fnTypeFuzzy(int, [int]), fnTypeFuzzy(dyn, [dyn])); | |
| always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dyn, [], [dyn])); | |
| always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dyn, [dyn])); | |
| always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dyn, [])); | |
| always(fnTypeFuzzy(int, [int], {extra: int}), fnTypeFuzzy(dyn, [dyn])); | |
| always(fnTypeFuzzy(dyn, [dyn]), fnTypeFuzzy(dyn, [dyn])); | |
| always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dyn, [], [dyn])); | |
| always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dyn, [dyn])); | |
| always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dyn, [])); | |
| always(fnTypeFuzzy(dyn, [dyn], {extra: dyn}), fnTypeFuzzy(dyn, [dyn])); | |
| }); | |
| test('void function types', () => { | |
| always(fnTypeFuzzy(int, [int]), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dart.void, [], [dyn])); | |
| always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dart.void, [])); | |
| always(fnTypeFuzzy(int, [int], {extra: int}), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [int]), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dart.void, [], [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dart.void, [])); | |
| always(fnTypeFuzzy(dart.void, [int], {extra: int}), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dyn, [dyn]), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dart.void, [], [dyn])); | |
| always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dart.void, [])); | |
| always(fnTypeFuzzy(dyn, [dyn], {extra: dyn}), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [dyn]), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [dyn]), fnTypeFuzzy(dart.void, [], [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [dyn]), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [dyn]), fnTypeFuzzy(dart.void, [])); | |
| always(fnTypeFuzzy(dart.void, [dyn], {extra: dyn}), fnTypeFuzzy(dart.void, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [int]), fnTypeFuzzy(dyn, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dyn, [], [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dyn, [dyn])); | |
| always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dyn, [])); | |
| always(fnTypeFuzzy(dart.void, [int], {extra: int}), fnTypeFuzzy(dyn, [dyn])); | |
| never(fnTypeFuzzy(dart.void, [int]), fnTypeFuzzy(int, [dyn])); | |
| never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [], [dyn])); | |
| never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [dyn])); | |
| never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [])); | |
| never(fnTypeFuzzy(dart.void, [int], {extra: int}), fnTypeFuzzy(int, [dyn])); | |
| never(fnTypeFuzzy(dart.void, [int]), fnTypeFuzzy(int, [int])); | |
| never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [], [int])); | |
| never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [int])); | |
| never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [])); | |
| never(fnTypeFuzzy(dart.void, [int], {extra: int}), fnTypeFuzzy(int, [int])); | |
| }); | |
| test('higher-order typedef', () => { | |
| let Func$ = dart.generic((S, T) => | |
| dart.typedef('Func', () => | |
| fnTypeFuzzy(T, [S]))); | |
| let Func2$ = dart.generic((R, S, T) => | |
| dart.typedef('Func2', () => | |
| fnTypeFuzzy(T, [Func$(R, S)]))); | |
| maybe(fnTypeFuzzy(int, [fnTypeFuzzy(int, [num])]), | |
| fnTypeFuzzy(num, [fnTypeFuzzy(int, [int])])); | |
| maybe(fnTypeFuzzy(int, [Func$(num, int)]), | |
| fnTypeFuzzy(num, [Func$(int, int)])); | |
| maybe(Func2$(num, int, int), Func2$(int, int, num)); | |
| }); | |
| test('mixed types', () => { | |
| let AA$ = dart.generic((T) => { | |
| class AA extends core.Object {} | |
| (AA.new = function() {}).prototype = AA.prototype; | |
| return AA; | |
| }); | |
| always(int, dyn); | |
| maybe(dyn, int); | |
| never(fnTypeFuzzy(int, [int]), int); | |
| never(int, fnTypeFuzzy(int, [int])); | |
| always(AA$(int), AA$(dyn)); | |
| maybe(AA$(dyn), AA$(int)); | |
| never(AA$(core.Object), AA$(int)); | |
| always(AA$(fnTypeFuzzy(int, [int])), AA$(dyn)); | |
| maybe(AA$(dyn), AA$(fnTypeFuzzy(int, [int]))); | |
| never(AA$(core.Object), AA$(fnTypeFuzzy(int, [int]))); | |
| always(AA$(fnTypeFuzzy(int, [int])), AA$(fnTypeFuzzy(dyn, [dyn]))); | |
| maybe(AA$(fnTypeFuzzy(dyn, [dyn])), AA$(fnTypeFuzzy(int, [int]))); | |
| maybe(AA$(fnTypeFuzzy(core.Object, [core.Object])), | |
| AA$(fnTypeFuzzy(int, [int]))); | |
| }); | |
| }); | |
| suite('canonicalization', function() { | |
| 'use strict'; | |
| let fnTypeFuzzy = dart.fnTypeFuzzy; | |
| let fnType = dart.fnType; | |
| let typedef = dart.typedef; | |
| let generic = dart.generic; | |
| let Object = core.Object; | |
| let String = core.String; | |
| let int = core.int; | |
| let dynamic = dart.dynamic; | |
| let bottom = dart.bottom; | |
| let Map = core.Map; | |
| let Map$ = core.Map$; | |
| class A {} | |
| let AA$ = generic((T, U) => { | |
| class AA extends core.Object {} | |
| (AA.new = function() {}).prototype = AA.prototype; | |
| return AA; | |
| }); | |
| let AA = AA$(); | |
| let Func2 = typedef('Func2', () => fnTypeFuzzy(dynamic, [dynamic, dynamic])); | |
| let FuncG$ = generic((T, U) => typedef('FuncG', () => fnTypeFuzzy(T, [T, U]))) | |
| let FuncG = FuncG$(); | |
| test('base types', () => { | |
| assert.equal(Object, Object); | |
| assert.equal(String, String); | |
| assert.equal(dynamic, dynamic); | |
| }); | |
| test('class types', () => { | |
| assert.equal(A, A); | |
| }); | |
| test('generic class types', () => { | |
| assert.equal(AA, AA); | |
| assert.equal(AA, AA$(dynamic, dynamic)); | |
| assert.equal(AA$(dynamic, dynamic), AA$(dynamic, dynamic)); | |
| assert.equal(AA$(AA, Object), AA$(AA, Object)); | |
| assert.equal(Map, Map); | |
| assert.equal(Map$(dynamic, dynamic), Map); | |
| assert.equal(Map$(int, Map$(int, int)), Map$(int, Map$(int, int))); | |
| }); | |
| test('typedefs', () => { | |
| assert.equal(Func2, Func2); | |
| assert.equal(FuncG, FuncG$(dynamic, dynamic)); | |
| assert.equal(FuncG$(dynamic, dynamic), FuncG$(dynamic, dynamic)); | |
| assert.equal(FuncG$(String, Func2), FuncG$(String, Func2)); | |
| }); | |
| test('function types', () => { | |
| assert.equal(fnTypeFuzzy(dynamic, [dynamic, dynamic]), | |
| fnTypeFuzzy(dynamic, [dynamic, dynamic])) | |
| assert.notEqual(fnType(dynamic, [dynamic, dynamic]), | |
| fnTypeFuzzy(dynamic, [dynamic, dynamic])) | |
| assert.equal(fnTypeFuzzy(dynamic, [dynamic, dynamic]), | |
| fnTypeFuzzy(dynamic, [bottom, bottom])) | |
| assert.equal(fnTypeFuzzy(dynamic, [], [dynamic, dynamic]), | |
| fnTypeFuzzy(dynamic, [], [dynamic, dynamic])) | |
| assert.notEqual(fnType(dynamic, [], [dynamic, dynamic]), | |
| fnTypeFuzzy(dynamic, [], [dynamic, dynamic])) | |
| assert.equal(fnTypeFuzzy(dynamic, [], [dynamic, dynamic]), | |
| fnTypeFuzzy(dynamic, [], [bottom, bottom])) | |
| assert.equal(fnTypeFuzzy(dynamic, [], {extra: dynamic}), | |
| fnTypeFuzzy(dynamic, [], {extra: dynamic})) | |
| assert.notEqual(fnType(dynamic, [], {extra: dynamic}), | |
| fnTypeFuzzy(dynamic, [], {extra: dynamic})) | |
| assert.equal(fnTypeFuzzy(dynamic, [], {extra: dynamic}), | |
| fnTypeFuzzy(dynamic, [], {extra: bottom})) | |
| assert.equal(fnTypeFuzzy(int, [int, int]), | |
| fnTypeFuzzy(int, [int, int])) | |
| assert.equal(fnTypeFuzzy(int, [], [int, int]), | |
| fnTypeFuzzy(int, [], [int, int])) | |
| assert.equal(fnTypeFuzzy(int, [int, int], {extra: int}), | |
| fnTypeFuzzy(int, [int, int], {extra: int})) | |
| assert.equal(fnTypeFuzzy(int, [int, int, int, int, int]), | |
| fnTypeFuzzy(int, [int, int, int, int, int])) | |
| assert.notEqual(fnTypeFuzzy(int, [int, int, int, int, int]), | |
| fnTypeFuzzy(int, [int, int, int], [int, int])) | |
| assert.notEqual(fnTypeFuzzy(String, [int, int, int, int, int]), | |
| fnTypeFuzzy(int, [int, int, int, int, int])) | |
| assert.notEqual(fnTypeFuzzy(String, []), | |
| fnTypeFuzzy(int, [])) | |
| }); | |
| }); | |
| suite('primitives', function() { | |
| 'use strict'; | |
| test('fixed length list', () => { | |
| let list = core.List.new(10); | |
| list[0] = 42; | |
| assert.throws(() => list.add(42)); | |
| }); | |
| test('toString on ES Symbol', () => { | |
| let sym = Symbol('_foobar'); | |
| assert.equal(dart.toString(sym), 'Symbol(_foobar)'); | |
| }); | |
| }); | |
| }); |