| // Copyright (c) 2022, 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. | 
 |  | 
 | // Test non-external factories and static methods of JS interop classes. | 
 |  | 
 | @JS() | 
 | library js_interop_non_external_test; | 
 |  | 
 | import 'package:expect/expect.dart'; | 
 | import 'package:expect/legacy/minitest.dart'; // ignore: deprecated_member_use_from_same_package | 
 | import 'package:js/js.dart'; | 
 |  | 
 | import 'js_interop_non_external_lib.dart'; | 
 |  | 
 | class _Class {} | 
 |  | 
 | @JS() | 
 | external dynamic eval(String code); | 
 |  | 
 | @JS() | 
 | class JSClass { | 
 |   external JSClass.cons(); | 
 |   factory JSClass() { | 
 |     field = 'unnamed'; | 
 |     return JSClass.cons(); | 
 |   } | 
 |  | 
 |   factory JSClass.named() { | 
 |     field = 'named'; | 
 |     return JSClass.cons(); | 
 |   } | 
 |  | 
 |   factory JSClass.redirecting() = JSClass; | 
 |  | 
 |   static String field = ''; | 
 |   static String get getSet { | 
 |     return field; | 
 |   } | 
 |  | 
 |   static set getSet(String val) { | 
 |     field = val; | 
 |   } | 
 |  | 
 |   static String method() => field; | 
 |  | 
 |   static T genericMethod<T extends num>(T t) { | 
 |     // Do a simple test using T. | 
 |     Expect.type<T>(t); | 
 |     Expect.notType<T>(''); | 
 |     return t; | 
 |   } | 
 | } | 
 |  | 
 | @JS('JSClass') | 
 | @staticInterop | 
 | class StaticInterop { | 
 |   external factory StaticInterop(); | 
 |   factory StaticInterop.named() { | 
 |     field = 'named'; | 
 |     return StaticInterop(); | 
 |   } | 
 |  | 
 |   static String field = ''; | 
 |  | 
 |   static String method() => field; | 
 | } | 
 |  | 
 | @JS() | 
 | @anonymous | 
 | class Anonymous { | 
 |   external factory Anonymous(); | 
 |  | 
 |   factory Anonymous.named() { | 
 |     field = 'named'; | 
 |     return Anonymous(); | 
 |   } | 
 |  | 
 |   static String field = ''; | 
 |  | 
 |   static String method() => field; | 
 | } | 
 |  | 
 | void testLocal() { | 
 |   // Test field is initialized and modified. | 
 |   expect(JSClass.field, ''); | 
 |   JSClass.field = 'modified'; | 
 |   expect(JSClass.field, 'modified'); | 
 |  | 
 |   // Test factories and side-effects to make sure body is executed. Test their | 
 |   // tear-offs too. | 
 |   JSClass(); | 
 |   expect(JSClass.field, 'unnamed'); | 
 |   JSClass.named(); | 
 |   expect(JSClass.field, 'named'); | 
 |   JSClass.redirecting(); | 
 |   expect(JSClass.field, 'unnamed'); | 
 |  | 
 |   (JSClass.cons)(); | 
 |   (JSClass.new)(); | 
 |   expect(JSClass.field, 'unnamed'); | 
 |   (JSClass.named)(); | 
 |   expect(JSClass.field, 'named'); | 
 |   (JSClass.redirecting)(); | 
 |   expect(JSClass.field, 'unnamed'); | 
 |  | 
 |   // Test getter and setter. | 
 |   expect(JSClass.getSet, JSClass.field); | 
 |   JSClass.getSet = 'set'; | 
 |   expect(JSClass.field, 'set'); | 
 |  | 
 |   // Test methods and their tear-offs. | 
 |   expect(JSClass.method(), JSClass.field); | 
 |   expect(JSClass.genericMethod(0), 0); | 
 |  | 
 |   expect((JSClass.method)(), JSClass.field); | 
 |   expect((JSClass.genericMethod)(0), 0); | 
 |  | 
 |   // Briefly check that other interop classes work too. | 
 |   expect(StaticInterop.field, ''); | 
 |   StaticInterop.field = 'modified'; | 
 |   expect(StaticInterop.field, 'modified'); | 
 |   StaticInterop.named(); | 
 |   expect(StaticInterop.field, 'named'); | 
 |   expect(StaticInterop.method(), StaticInterop.field); | 
 |  | 
 |   expect(Anonymous.field, ''); | 
 |   Anonymous.field = 'modified'; | 
 |   expect(Anonymous.field, 'modified'); | 
 |   Anonymous.named(); | 
 |   expect(Anonymous.field, 'named'); | 
 |   expect(Anonymous.method(), Anonymous.field); | 
 | } | 
 |  | 
 | // Run the same tests as `testLocal`, but with a class in a different library, | 
 | // and with class type args. | 
 | void testNonLocal() { | 
 |   expect(OtherJSClass.field, ''); | 
 |   OtherJSClass.field = 'modified'; | 
 |   expect(OtherJSClass.field, 'modified'); | 
 |  | 
 |   OtherJSClass<int>(0); | 
 |   Expect.throws<TypeError>(() => topLevelListAppend(_Class())); | 
 |   topLevelListAppend(42); | 
 |   expect(OtherJSClass.field, 'unnamed'); | 
 |   OtherJSClass.named(0); | 
 |   Expect.throws<TypeError>(() => topLevelListAppend(_Class())); | 
 |   topLevelListAppend(42); | 
 |   expect(OtherJSClass.field, 'named'); | 
 |   OtherJSClass<double>.redirecting(0.1); | 
 |   expect(OtherJSClass.field, 'unnamed'); | 
 |  | 
 |   (OtherJSClass.cons)(0); | 
 |   (OtherJSClass<int>.new)(0); | 
 |   expect(OtherJSClass.field, 'unnamed'); | 
 |   (OtherJSClass.named)(0); | 
 |   expect(OtherJSClass.field, 'named'); | 
 |   (OtherJSClass<double>.redirecting)(0.1); | 
 |   expect(OtherJSClass.field, 'unnamed'); | 
 |  | 
 |   expect(OtherJSClass.getSet, OtherJSClass.field); | 
 |   OtherJSClass.getSet = 'set'; | 
 |   expect(OtherJSClass.field, 'set'); | 
 |  | 
 |   expect(OtherJSClass.method(), OtherJSClass.field); | 
 |   expect(OtherJSClass.genericMethod(0), 0); | 
 |  | 
 |   expect((OtherJSClass.method)(), OtherJSClass.field); | 
 |   expect((OtherJSClass.genericMethod)(0), 0); | 
 | } | 
 |  | 
 | void main() { | 
 |   eval(''' | 
 |     function JSClass(arg) {} | 
 |   '''); | 
 |   testLocal(); | 
 |   testNonLocal(); | 
 | } |