| // 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. |
| |
| // @dart = 2.7 |
| |
| library tests.web.interop_anonymous_unreachable_test; |
| |
| import 'package:async_helper/async_helper.dart'; |
| import 'package:expect/expect.dart'; |
| import '../helpers/compiler_helper.dart'; |
| |
| testUnreachableCrash() async { |
| print("-- unreachable code doesn't crash the compiler --"); |
| // This test is a regression for Issue #24974 |
| String generated = await compile(""" |
| import 'package:js/js.dart'; |
| |
| @JS() @anonymous |
| class UniqueLongNameForTesting_A { |
| external factory UniqueLongNameForTesting_A(); |
| } |
| main() {} |
| """, returnAll: true); |
| |
| // the code should not be included in the output either. |
| Expect.isFalse(generated.contains("UniqueLongNameForTesting_A")); |
| } |
| |
| testTreeShakingJsInteropTypes() async { |
| print('-- tree-shaking interop types --'); |
| String program = """ |
| import 'package:js/js.dart'; |
| |
| // reachable and allocated |
| @JS() @anonymous |
| class UniqueLongNameForTesting_A { |
| external bool get x; |
| external UniqueLongNameForTesting_D get d; |
| external UniqueLongNameForTesting_E get e; |
| external factory UniqueLongNameForTesting_A( |
| {UniqueLongNameForTesting_B arg0}); |
| } |
| |
| // visible through the parameter above, but not used. |
| @JS() @anonymous |
| class UniqueLongNameForTesting_B { |
| external factory UniqueLongNameForTesting_B(); |
| } |
| |
| // unreachable |
| @JS() @anonymous |
| class UniqueLongNameForTesting_C { |
| external factory UniqueLongNameForTesting_C(); |
| } |
| |
| // visible and reached through `d`. |
| @JS() @anonymous |
| class UniqueLongNameForTesting_D { |
| external factory UniqueLongNameForTesting_D(); |
| } |
| |
| // visible through `e`, but not reached. |
| @JS() @anonymous |
| class UniqueLongNameForTesting_E { |
| external factory UniqueLongNameForTesting_E(); |
| } |
| |
| main() { |
| print(new UniqueLongNameForTesting_A().x); |
| print(new UniqueLongNameForTesting_A().d); |
| } |
| """; |
| |
| print(' - no tree-shaking by default -'); |
| String generated1 = await compile(program, returnAll: true); |
| Expect.isTrue(generated1.contains("UniqueLongNameForTesting_A")); |
| Expect.isTrue(generated1.contains("UniqueLongNameForTesting_D")); |
| |
| Expect.isTrue(generated1.contains("UniqueLongNameForTesting_B")); |
| Expect.isTrue(generated1.contains("UniqueLongNameForTesting_C")); |
| Expect.isTrue(generated1.contains("UniqueLongNameForTesting_E")); |
| } |
| |
| testTreeShakingNativeTypes() async { |
| print('-- tree-shaking other native types --'); |
| |
| String program = """ |
| import 'dart:html'; |
| import 'package:js/js.dart'; |
| |
| @JS() @anonymous |
| class UniqueLongNameForTesting_A { |
| external dynamic get x; |
| } |
| |
| @JS() @anonymous |
| class UniqueLongNameForTesting_B { |
| external dynamic get y; |
| } |
| |
| main() { |
| print(new UniqueLongNameForTesting_A().x); |
| } |
| """; |
| |
| print(' - allocation effect of dynamic excludes native types -'); |
| String generated1 = await compile(program, returnAll: true); |
| Expect.isTrue(generated1.contains("UniqueLongNameForTesting_A")); |
| // any js-interop type could be allocated by `get x` |
| Expect.isTrue(generated1.contains("UniqueLongNameForTesting_B")); |
| // but we exclude other native types like HTMLAudioElement |
| Expect.isFalse(generated1.contains("HTMLAudioElement")); |
| |
| print(' - declared native types are included in allocation effect -'); |
| String program2 = """ |
| import 'dart:html'; |
| import 'package:js/js.dart'; |
| |
| @JS() @anonymous |
| class UniqueLongNameForTesting_A { |
| external AudioElement get x; |
| } |
| |
| main() { |
| print(new UniqueLongNameForTesting_A().x is AudioElement); |
| } |
| """; |
| |
| String generated3 = await compile(program2, returnAll: true); |
| Expect.isTrue(generated3.contains("UniqueLongNameForTesting_A")); |
| Expect.isTrue(generated3.contains("HTMLAudioElement")); |
| |
| program2 = """ |
| import 'dart:html'; |
| import 'package:js/js.dart'; |
| |
| @JS() @anonymous |
| class UniqueLongNameForTesting_A { |
| external dynamic get x; |
| } |
| |
| main() { |
| print(new UniqueLongNameForTesting_A().x is AudioElement); |
| } |
| """; |
| |
| generated3 = await compile(program2, returnAll: true); |
| Expect.isTrue(generated3.contains("UniqueLongNameForTesting_A")); |
| // This extra check is to make sure that we don't include HTMLAudioElement |
| // just because of the is-check. It is optimized away in this case because |
| // we believe it was never instantiated. |
| Expect.isFalse(generated3.contains("HTMLAudioElement")); |
| } |
| |
| main() { |
| runTests() async { |
| await testUnreachableCrash(); |
| await testTreeShakingJsInteropTypes(); |
| await testTreeShakingNativeTypes(); |
| } |
| |
| asyncTest(() async { |
| print('--test from kernel------------------------------------------------'); |
| await runTests(); |
| }); |
| } |