Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Unified Diff: test/js_interop_test.ts

Issue 2225953002: Strip more unused features. (Closed) Base URL: git@github.com:dart-lang/js_facade_gen.git@master
Patch Set: Fix types Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/function_test.ts ('k') | test/literal_test.ts » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/js_interop_test.ts
diff --git a/test/js_interop_test.ts b/test/js_interop_test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..488fb76faab1c34aed98dc05083b3192d83ab29a
--- /dev/null
+++ b/test/js_interop_test.ts
@@ -0,0 +1,862 @@
+/// <reference path="../typings/mocha/mocha.d.ts"/>
+import {expectTranslate} from './test_support';
+
+// TODO(jacobr): merge these tests back in with the other tests. These tests are
+// only separate because we expected at one point to integrate with TS2Dart
+// instead of refactoring TS2Dart to only output facades.
+describe('variables', () => {
+ it('should print variable declaration', () => {
+ expectTranslate('var a:number;').to.equal(`@JS()
+external num get a;
+@JS()
+external set a(num v);`);
+ expectTranslate('var a;').to.equal(`@JS()
+external get a;
+@JS()
+external set a(v);`);
+ expectTranslate('var a:any;').to.equal(`@JS()
+external dynamic get a;
+@JS()
+external set a(dynamic v);`);
+ });
+ it('should transpile variable declaration lists', () => {
+ expectTranslate('var a: A;').to.equal(`@JS()
+external A get a;
+@JS()
+external set a(A v);`);
+
+ expectTranslate('var a, b;').to.equal(`@JS()
+external get a;
+@JS()
+external set a(v);
+@JS()
+external get b;
+@JS()
+external set b(v);`);
+ });
+ it('support vardecls containing more than one type (implicit or explicit)', () => {
+ expectTranslate('var a: A, b: B;').to.equal(`@JS()
+external A get a;
+@JS()
+external set a(A v);
+@JS()
+external B get b;
+@JS()
+external set b(B v);`);
+ expectTranslate('var a: number, b: string;').to.equal(`@JS()
+external num get a;
+@JS()
+external set a(num v);
+@JS()
+external String get b;
+@JS()
+external set b(String v);`);
+ });
+
+ it('supports const', () => {
+ expectTranslate('const a:number = 1;').to.equal(`@JS()
+external num get a;`);
+
+ expectTranslate('const a:number = 1, b:number = 2;').to.equal(`@JS()
+external num get a;
+@JS()
+external num get b;`);
+
+ expectTranslate('const a:string').to.equal(`@JS()
+external String get a;`);
+
+ expectTranslate('const a:number, b:number;').to.equal(`@JS()
+external num get a;
+@JS()
+external num get b;`);
+ });
+});
+
+describe('classes', () => {
+ it('should translate classes', () => {
+ expectTranslate('class X {}').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+}`);
+ });
+ it('should support extends', () => {
+ expectTranslate('class X extends Y {}').to.equal(`@JS()
+class X extends Y {
+ // @Ignore
+ X.fakeConstructor$() : super.fakeConstructor$();
+}`);
+ });
+ it('should support implements', () => {
+ expectTranslate('class X implements Y, Z {}').to.equal(`@JS()
+class X implements Y, Z {
+ // @Ignore
+ X.fakeConstructor$();
+}`);
+ });
+ it('should support implements', () => {
+ expectTranslate('class X extends Y implements Z {}').to.equal(`@JS()
+class X extends Y implements Z {
+ // @Ignore
+ X.fakeConstructor$() : super.fakeConstructor$();
+}`);
+ });
+ it('should support abstract', () => {
+ expectTranslate('abstract class X {}').to.equal(`@JS()
+abstract class X {
+ // @Ignore
+ X.fakeConstructor$();
+}`);
+ });
+ describe('members', () => {
+ it('supports empty declarations', () => {
+ expectTranslate('class X { ; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+}`);
+ });
+ it('supports fields', () => {
+ expectTranslate('class X { x: number; y: string; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external num get x;
+ external set x(num v);
+ external String get y;
+ external set y(String v);
+}`);
+ expectTranslate('class X { x; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external get x;
+ external set x(v);
+}`);
+ });
+ it('ignore field initializers', () => {
+ expectTranslate('class X { x: number = 42; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external num get x;
+ external set x(num v);
+}`);
+ });
+ it('supports visibility modifiers', () => {
+ expectTranslate('class X { private _x; x; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external get JS$_x;
+ external set JS$_x(v);
+ external get x;
+ external set x(v);
+}`);
+ expectTranslate('class X { private x; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external get x;
+ external set x(v);
+}`);
+ expectTranslate('class X { constructor (private x) {} }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external get x;
+ external set x(v);
+ external factory X(x);
+}`);
+ expectTranslate('class X { _x; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external get JS$_x;
+ external set JS$_x(v);
+}`);
+ });
+ it('does not support protected', () => {
+ expectTranslate('class X { protected x; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external get x;
+ external set x(v);
+}`);
+ });
+ it('supports static fields', () => {
+ expectTranslate('class X { static x: number = 42; }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external static num get x;
+ external static set x(num v);
+}`);
+ });
+ it('supports methods', () => {
+ expectTranslate('class X { x() { return 42; } }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external x();
+}`);
+ });
+ it('supports abstract methods', () => {
+ expectTranslate('abstract class X { abstract x(); }').to.equal(`@JS()
+abstract class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external x();
+}`);
+ });
+ it('supports method return types', () => {
+ expectTranslate('class X { x(): number { return 42; } }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external num x();
+}`);
+ });
+ it('supports method params', () => {
+ expectTranslate('class X { x(a, b); }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external x(a, b);
+}`);
+ });
+ it('supports method return types', () => {
+ expectTranslate('class X { x( a : number, b : string ) : num }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external num x(num a, String b);
+}`);
+ });
+ it('supports get methods', () => {
+ expectTranslate('class X { get y(): number {} }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external num get y;
+}`);
+ expectTranslate('class X { static get Y(): number {} }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external static num get Y;
+}`);
+ });
+ it('supports set methods', () => {
+ expectTranslate('class X { set y(n: number) {} }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external set y(num n);
+}`);
+ expectTranslate('class X { static get Y(): number {} }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external static num get Y;
+}`);
+ });
+ it('supports generic methods', () => {
+ expectTranslate('class X<T> { static Z<T>(): X<T> {} }').to.equal(`@JS()
+class X<T> {
+ // @Ignore
+ X.fakeConstructor$();
+ external static X<dynamic/*=T*/ > Z/*<T>*/();
+}`);
+ expectTranslate('class X<T> { Z(): X<T> {} }').to.equal(`@JS()
+class X<T> {
+ // @Ignore
+ X.fakeConstructor$();
+ external X<T> Z();
+}`);
+ });
+ it('merge overrides', () => {
+ expectTranslate(`
+class X {
+ createElement(tagName: "img"): HTMLImageElement;
+ createElement(tagName: "video"): HTMLVideoElement;
+ createElement(tagName: string): HTMLElement;
+}`).to.equal(`import "dart:html";
+
+@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ /*external ImageElement createElement("img" tagName);*/
+ /*external VideoElement createElement("video" tagName);*/
+ /*external HtmlElement createElement(String tagName);*/
+ external dynamic /*ImageElement|VideoElement|HtmlElement*/ createElement(
+ String tagName);
+}`);
+ expectTranslate(`
+class X {
+ F(a:string):num;
+ F(a:string, b: string|num):string;
+ F(a2:string, b: string, c: num):string;
+}`).to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ /*external num F(String a);*/
+ /*external String F(String a, String|num b);*/
+ /*external String F(String a2, String b, num c);*/
+ external dynamic /*num|String*/ F(String a_a2,
+ [dynamic /*String|num*/ b, num c]);
+}`);
+
+ expectTranslate(`
+class X {
+ Y(a:string):num {};
+ Y(a:string, b: num):string {};
+ Y(a2:string, b: string, c: num):string {};
+}`).to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ /*external num Y(String a);*/
+ /*external String Y(String a, num b);*/
+ /*external String Y(String a2, String b, num c);*/
+ external dynamic /*num|String*/ Y(String a_a2,
+ [dynamic /*num|String*/ b, num c]);
+}`);
+ expectTranslate(`
+class X {
+ firstElement(elements: HTMLImageElement[]): HTMLImageElement;
+ firstElement(elements: HTMLVideoElement[]): HTMLVideoElement;
+ firstElement(elements: HTMLElement[]): HTMLElement;
+}`).to.equal(`import "dart:html";
+
+@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ /*external ImageElement firstElement(List<ImageElement> elements);*/
+ /*external VideoElement firstElement(List<VideoElement> elements);*/
+ /*external HtmlElement firstElement(List<HtmlElement> elements);*/
+ external dynamic /*ImageElement|VideoElement|HtmlElement*/ firstElement(
+ List<
+ HtmlElement> /*List<ImageElement>|List<VideoElement>|List<HtmlElement>*/ elements);
+}`);
+
+ // TODO(jacobr): we should consider special casing so EventLister and
+ // EventListenerObject are treated as the same in Dart even though they
+ // are different.
+ expectTranslate(`
+interface SampleAudioNode {
+ addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void;
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
+}`).to.equal(`import "dart:html";
+import "package:func/func.dart";
+
+@anonymous
+@JS()
+abstract class SampleAudioNode {
+ /*external void addEventListener("ended" type, dynamic listener(Event ev), [bool useCapture]);*/
+ /*external void addEventListener(String type, EventListener|EventListenerObject listener, [bool useCapture]);*/
+ external void addEventListener(String type,
+ dynamic /*Func1<Event, dynamic>|EventListener|EventListenerObject*/ listener,
+ [bool useCapture]);
+}`);
+
+ expectTranslate(`
+interface ListenObject {
+ someDummyMethod(evt: string): void;
+}
+
+interface ExampleListener {
+ (evt: string): void;
+}
+
+interface DummySample {
+ addEventListener(type: "ended", listener: ListenObject): void;
+ addEventListener(type: string, listener: ExampleListener): void;
+}`).to.equal(`@anonymous
+@JS()
+abstract class ListenObject {
+ external void someDummyMethod(String evt);
+}
+
+typedef void ExampleListener(String evt);
+
+@anonymous
+@JS()
+abstract class DummySample {
+ /*external void addEventListener("ended" type, ListenObject listener);*/
+ /*external void addEventListener(String type, ExampleListener listener);*/
+ external void addEventListener(
+ String type, dynamic /*ListenObject|ExampleListener*/ listener);
+}`);
+
+ expectTranslate(`
+interface ListenAny {
+ (evt: any): void;
+}
+
+interface ExampleListener {
+ (evt: string): void;
+}
+
+interface DummySample {
+ addEventListener(type: "ended", listener: ListenAny): void;
+ addEventListener(type: string, listener: ExampleListener): void;
+}`).to.equal(`typedef void ListenAny(dynamic evt);
+typedef void ExampleListener(String evt);
+
+@anonymous
+@JS()
+abstract class DummySample {
+ /*external void addEventListener("ended" type, ListenAny listener);*/
+ /*external void addEventListener(String type, ExampleListener listener);*/
+ external void addEventListener(
+ String type, Function /*ListenAny|ExampleListener*/ listener);
+}`);
+
+ });
+ it('dot dot dot', () => {
+ expectTranslate(`
+function buildName(firstName: string, ...restOfName: string[]): string;
+`).to.equal(`@JS()
+external String buildName(String firstName,
+ [String restOfName1,
+ String restOfName2,
+ String restOfName3,
+ String restOfName4,
+ String restOfName5]);`);
+ expectTranslate(`
+function log(...args);`)
+ .to.equal(`@JS()
+external log([args1, args2, args3, args4, args5]);`);
+ });
+ it('interface constructors', () => {
+ expectTranslate(`
+interface C {
+ oncached: (ev: Event) => any;
+}
+declare var C: {new(): C; CHECKING: number; }`)
+ .to.equal(`import "package:func/func.dart";
+import "dart:html";
+
+@JS()
+abstract class C {
+ external Func1<Event, dynamic> get oncached;
+ external set oncached(Func1<Event, dynamic> v);
+ external factory C();
+ external static num get CHECKING;
+ external static set CHECKING(num v);
+}`);
+ });
+ it('property bag interfaces', () => {
+ expectTranslate(`
+interface X {
+ a: string;
+ b: num;
+ c: X;
+}
+interface Y extends X {
+ d: num;
+ /* example comment */
+ e: any;
+}`).to.equal(`@anonymous
+@JS()
+abstract class X {
+ external String get a;
+ external set a(String v);
+ external num get b;
+ external set b(num v);
+ external X get c;
+ external set c(X v);
+ external factory X({String a, num b, X c});
+}
+
+@anonymous
+@JS()
+abstract class Y implements X {
+ external num get d;
+ external set d(num v);
+
+ /// example comment
+ external dynamic get e;
+ external set e(dynamic v);
+ external factory Y({num d, dynamic e, String a, num b, X c});
+}`);
+ expectTranslate(`interface X<A> { a: A; b: num, c: X }
+ interface Y<A,B> extends X<A> { d: B; e: any; }`)
+ .to.equal(`@anonymous
+@JS()
+abstract class X<A> {
+ external A get a;
+ external set a(A v);
+ external num get b;
+ external set b(num v);
+ external X get c;
+ external set c(X v);
+ external factory X({A a, num b, X c});
+}
+
+@anonymous
+@JS()
+abstract class Y<A, B> implements X<A> {
+ external B get d;
+ external set d(B v);
+ external dynamic get e;
+ external set e(dynamic v);
+ external factory Y({B d, dynamic e, A a, num b, X c});
+}`);
+ });
+ it('callable', () => {
+ expectTranslate('interface X<T> { (a:T):T; Y():T; }').to.equal(`@anonymous
+@JS()
+abstract class X<T> implements Function {
+ external T call(T a);
+ external T Y();
+}`);
+ });
+
+ it('supports constructors', () => {
+ expectTranslate('class X { constructor() { } }').to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external factory X();
+}`);
+ });
+ it('supports parameter properties', () => {
+ expectTranslate(`
+class X {
+ c: number;
+ constructor(private _bar: B, public foo: string = "hello", private _goggles: boolean = true);
+}`).to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external B get JS$_bar;
+ external set JS$_bar(B v);
+ external String get foo;
+ external set foo(String v);
+ external bool get JS$_goggles;
+ external set JS$_goggles(bool v);
+ external num get c;
+ external set c(num v);
+ external factory X(B JS$_bar, [String foo, bool JS$_goggles]);
+}`);
+ expectTranslate(`
+class X {
+ constructor(public foo: string, b: number, private _marbles: boolean = true) {}
+}`).to.equal(`@JS()
+class X {
+ // @Ignore
+ X.fakeConstructor$();
+ external String get foo;
+ external set foo(String v);
+ external bool get JS$_marbles;
+ external set JS$_marbles(bool v);
+ external factory X(String foo, num b, [bool JS$_marbles]);
+}`);
+ });
+ });
+});
+
+describe('interfaces', () => {
+ it('translates interfaces to abstract classes', () => {
+ expectTranslate('interface X {}').to.equal(`@anonymous
+@JS()
+abstract class X {}`);
+ });
+ it('translates interface extends to class implements', () => {
+ expectTranslate('interface X extends Y, Z {}').to.equal(`@anonymous
+@JS()
+abstract class X implements Y, Z {}`);
+ });
+ it('supports abstract methods', () => {
+ expectTranslate('interface X { x(); }').to.equal(`@anonymous
+@JS()
+abstract class X {
+ external x();
+}`);
+ });
+
+ it('supports interface properties', () => {
+ expectTranslate('interface X { x: string; y; }').to.equal(`@anonymous
+@JS()
+abstract class X {
+ external String get x;
+ external set x(String v);
+ external get y;
+ external set y(v);
+ external factory X({String x, y});
+}`);
+ });
+});
+
+describe('single call signature interfaces', () => {
+ it('should support declaration', () => {
+ expectTranslate('interface F { (n: number): boolean; }').to.equal('typedef bool F(num n);');
+ });
+ it('should support generics', () => {
+ expectTranslate('interface F<A, B> { (a: A): B; }').to.equal('typedef B F<A, B>(A a);');
+ });
+});
+
+describe('enums', () => {
+ it('should support basic enum declaration', () => {
+ expectTranslate('enum Color { Red, Green, Blue }').to.equal(`@JS()
+class Color {
+ external static num get Red;
+ external static num get Green;
+ external static num get Blue;
+}`);
+ });
+ it('empty enum', () => {
+ expectTranslate('enum Color { }').to.equal(`@JS()
+class Color {}`);
+ });
+ it('enum with initializer', () => {
+ expectTranslate('enum Color { Red = 1, Green, Blue = 4 }').to.equal(`@JS()
+class Color {
+ external static num get Red;
+ external static num get Green;
+ external static num get Blue;
+}`);
+ });
+});
+
+describe('renames', () => {
+ it('should support class renames', () => {
+ expectTranslate(`
+declare module m1 {
+ interface A { x(); }
+}
+declare module m2 {
+ interface A { y(); }
+}
+`).to.equal(`// Module m1
+@anonymous
+@JS()
+abstract class A {
+ external x();
+}
+// End module m1
+
+// Module m2
+@anonymous
+@JS()
+abstract class m2_A {
+ external y();
+}
+// End module m2`);
+ expectTranslate(`
+declare module m1 {
+ class A { constructor(x); }
+}
+declare module m2 {
+ class A { constructor(y); }
+}`).to.equal(`// Module m1
+@JS("m1.A")
+class A {
+ // @Ignore
+ A.fakeConstructor$();
+ external factory A(x);
+}
+// End module m1
+
+// Module m2
+@JS("m2.A")
+class m2_A {
+ // @Ignore
+ m2_A.fakeConstructor$();
+ external factory m2_A(y);
+}
+// End module m2`);
+ expectTranslate(`
+declare module m1 {
+ class A { constructor(x:m2.A); }
+}
+declare module m2 {
+ class A { constructor(y:m1.A); }
+}
+`).to.equal(`// Module m1
+@JS("m1.A")
+class A {
+ // @Ignore
+ A.fakeConstructor$();
+ external factory A(m2_A x);
+}
+// End module m1
+
+// Module m2
+@JS("m2.A")
+class m2_A {
+ // @Ignore
+ m2_A.fakeConstructor$();
+ external factory m2_A(A y);
+}
+// End module m2`);
+
+ });
+ it('should support member renames', () => {
+ expectTranslate(`
+declare module m1 {
+ interface A { x(); }
+}
+declare module m2 {
+ export function A(x:m1.A);
+}`).to.equal(`// Module m1
+@anonymous
+@JS()
+abstract class A {
+ external x();
+}
+// End module m1
+
+// Module m2
+@JS("m2.A")
+external m2_A(A x);
+// End module m2`);
+ });
+
+ it('handle class renames in type declarations', () => {
+ expectTranslate(`
+declare module m1 {
+ interface A { x(); }
+}
+declare module m2 {
+ interface A { y(); }
+}
+export function register(x:m2.A);
+`).to.equal(`// Module m1
+@anonymous
+@JS()
+abstract class A {
+ external x();
+}
+// End module m1
+
+// Module m2
+@anonymous
+@JS()
+abstract class m2_A {
+ external y();
+}
+
+// End module m2
+@JS()
+external register(m2_A x);`);
+ expectTranslate(`
+declare module m1 {
+ module foo {
+ interface A { x(); }
+ }
+}
+declare module m2 {
+ module foo {
+ interface A { y(); }
+ }
+}
+declare module m3 {
+ module foo {
+ interface A { z(); }
+ }
+}
+export function register(y:m2.foo.A, z:m3.foo.A);
+`).to.equal(`// Module m1
+
+// Module foo
+@anonymous
+@JS()
+abstract class A {
+ external x();
+}
+// End module foo
+
+// End module m1
+
+// Module m2
+
+// Module foo
+@anonymous
+@JS()
+abstract class foo_A {
+ external y();
+}
+// End module foo
+
+// End module m2
+
+// Module m3
+
+// Module foo
+@anonymous
+@JS()
+abstract class m3_foo_A {
+ external z();
+}
+// End module foo
+
+// End module m3
+@JS()
+external register(foo_A y, m3_foo_A z);`);
+
+ expectTranslate(`
+declare module m1 {
+ interface A { x(); }
+}
+declare module m2 {
+ interface A { y(); }
+}
+export function register(x:m1.A);
+ `).to.equal(`// Module m1
+@anonymous
+@JS()
+abstract class A {
+ external x();
+}
+// End module m1
+
+// Module m2
+@anonymous
+@JS()
+abstract class m2_A {
+ external y();
+}
+
+// End module m2
+@JS()
+external register(A x);`);
+ });
+
+ describe('type alias', () => {
+ it('replace with simple type', () => {
+ expectTranslate(`
+type MyNumber = number;
+export function add(x: MyNumber, y: MyNumber): MyNumber;
+ `).to.equal(`@JS()
+external num add(num x, num y);`);
+ });
+ });
+
+ it('union types', () => {
+ // TODO(jacobr): ideally the draw method should specify that arg el has type
+ // HtmlElement instead of dynamic.
+ expectTranslate(`
+type listener1 = ()=>boolean;
+type listener2 = (e:string)=>boolean;
+function addEventListener(listener: listener1|listener2);`)
+ .to.equal(`import "package:func/func.dart";
+
+@JS()
+external addEventListener(
+ Function /*Func0<bool>|Func1<String, bool>*/ listener);`);
+
+ expectTranslate('function draw(el: HTMLCanvasElement|HTMLImageElement):void;')
+ .to.equal(`import "dart:html";
+
+@JS()
+external void draw(dynamic /*CanvasElement|ImageElement*/ el);`);
+ });
+});
« no previous file with comments | « test/function_test.ts ('k') | test/literal_test.ts » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698