| Index: tests/compiler/dart2js/interop_anonymous_unreachable_test.dart
|
| diff --git a/tests/compiler/dart2js/interop_anonymous_unreachable_test.dart b/tests/compiler/dart2js/interop_anonymous_unreachable_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3f382059772247abb9abeab45eef227cbe4ece3d
|
| --- /dev/null
|
| +++ b/tests/compiler/dart2js/interop_anonymous_unreachable_test.dart
|
| @@ -0,0 +1,177 @@
|
| +// 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.
|
| +
|
| +library tests.dart2js.interop_anonymous_unreachable_test;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:test/test.dart';
|
| +import 'compiler_helper.dart';
|
| +
|
| +
|
| +main() {
|
| + test("unreachable code doesn't crash the compiler", () async {
|
| + // 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(generated, isNot(contains("UniqueLongNameForTesting_A")));
|
| + });
|
| +
|
| + group('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);
|
| + }
|
| + """;
|
| +
|
| + test('no tree-shaking by default', () async {
|
| + String generated = await compile(program, returnAll: true);
|
| + expect(generated.contains("UniqueLongNameForTesting_A"), isTrue);
|
| + expect(generated.contains("UniqueLongNameForTesting_D"), isTrue);
|
| +
|
| + expect(generated.contains("UniqueLongNameForTesting_B"), isTrue);
|
| + expect(generated.contains("UniqueLongNameForTesting_C"), isTrue);
|
| + expect(generated.contains("UniqueLongNameForTesting_E"), isTrue);
|
| + });
|
| +
|
| + test('tree-shake when using flag', () async {
|
| + String generated = await compile(program,
|
| + trustJSInteropTypeAnnotations: true,
|
| + returnAll: true);
|
| + expect(generated.contains("UniqueLongNameForTesting_A"), isTrue);
|
| + expect(generated.contains("UniqueLongNameForTesting_D"), isTrue);
|
| +
|
| + expect(generated.contains("UniqueLongNameForTesting_B"), isFalse);
|
| + expect(generated.contains("UniqueLongNameForTesting_C"), isFalse);
|
| + expect(generated.contains("UniqueLongNameForTesting_E"), isFalse);
|
| + });
|
| + });
|
| +
|
| + group('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);
|
| + }
|
| + """;
|
| +
|
| + test('allocation effect of dynamic excludes native types', () async {
|
| + String generated = await compile(program, returnAll: true);
|
| + expect(generated.contains("UniqueLongNameForTesting_A"), isTrue);
|
| + // any js-interop type could be allocated by `get x`
|
| + expect(generated.contains("UniqueLongNameForTesting_B"), isTrue);
|
| + // but we exclude other native types like HTMLAudioElement
|
| + expect(generated.contains("HTMLAudioElement"), isFalse);
|
| + });
|
| +
|
| + test('allocation effect of dynamic excludes native types [flag]', () async {
|
| + // Trusting types doesn't make a difference.
|
| + String generated = await compile(program,
|
| + trustJSInteropTypeAnnotations: true,
|
| + returnAll: true);
|
| + expect(generated.contains("UniqueLongNameForTesting_A"), isTrue);
|
| + expect(generated.contains("UniqueLongNameForTesting_B"), isTrue);
|
| + expect(generated.contains("HTMLAudioElement"), isFalse);
|
| + });
|
| +
|
| + test('declared native types are included in allocation effect', () async {
|
| + 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 generated = await compile(program2, returnAll: true);
|
| + expect(generated.contains("UniqueLongNameForTesting_A"), isTrue);
|
| + expect(generated.contains("HTMLAudioElement"), isTrue);
|
| +
|
| + 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);
|
| + }
|
| + """;
|
| +
|
| + generated = await compile(program2, returnAll: true);
|
| + expect(generated.contains("UniqueLongNameForTesting_A"), isTrue);
|
| + // 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(generated.contains("HTMLAudioElement"), isFalse);
|
| + });
|
| + });
|
| +}
|
|
|