| // 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)'); |
| }); |
| }); |
| }); |