| // Copyright (c) 2018, 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. | |
| import 'package:compiler/src/commandline_options.dart'; | |
| import 'package:compiler/src/compiler.dart'; | |
| import 'package:compiler/src/elements/entities.dart'; | |
| import 'package:compiler/src/js_emitter/model.dart'; | |
| import 'package:compiler/src/js_model/js_world.dart' show JClosedWorld; | |
| import 'package:expect/async_helper.dart'; | |
| import 'package:expect/expect.dart'; | |
| import '../helpers/program_lookup.dart'; | |
| import 'package:compiler/src/util/memory_compiler.dart'; | |
| const String code = ''' | |
| // This needs one-arg instantiation. | |
| @pragma('dart2js:noInline') | |
| T f1a<T>(T t) => t; | |
| // This needs no instantiation because it is not closurized. | |
| @pragma('dart2js:noInline') | |
| T f1b<T>(T t1, T t2) => t1; | |
| class Class { | |
| // This needs two-arg instantiation. | |
| @pragma('dart2js:noInline') | |
| bool f2a<T, S>(T t, S s) => t == s; | |
| // This needs no instantiation because it is not closurized. | |
| @pragma('dart2js:noInline') | |
| bool f2b<T, S>(T t, S s1, S s2) => t == s1; | |
| } | |
| @pragma('dart2js:noInline') | |
| int method1(int i, int Function(int) f) => f(i); | |
| @pragma('dart2js:noInline') | |
| bool method2(int a, int b, bool Function(int, int) f) => f(a, b); | |
| @pragma('dart2js:noInline') | |
| int method3(int a, int b, int c, int Function(int, int, int) f) => f(a, b, c); | |
| main() { | |
| // This needs three-arg instantiation. | |
| T local1<T, S, U>(T t, S s, U u) => t; | |
| // This needs no instantiation because but a local function is always | |
| // closurized so we assume it does. | |
| T local2<T, S, U>(T t, S s, U u1, U u2) => t; | |
| print(method1(42, f1a)); | |
| print(f1b(42, 87)); | |
| Class c = Class(); | |
| print(method2(0, 1, c.f2a)); | |
| print(c.f2b(42, 87, 123)); | |
| print(method3(0, 1, 2, local1)); | |
| print(local2(42, 87, 123, 256)); | |
| } | |
| '''; | |
| main() { | |
| asyncTest(() async { | |
| CompilationResult result = await runCompiler( | |
| memorySourceFiles: {'main.dart': code}, | |
| options: [Flags.omitImplicitChecks], | |
| ); | |
| Expect.isTrue(result.isSuccess); | |
| Compiler compiler = result.compiler!; | |
| JClosedWorld closedWorld = compiler.backendClosedWorldForTesting!; | |
| ProgramLookup programLookup = ProgramLookup(compiler.backendStrategy); | |
| void checkStubs(ClassEntity element, List<String> expectedStubs) { | |
| Class? cls = programLookup.getClass(element); | |
| List<String> actualStubs = <String>[]; | |
| if (cls != null) { | |
| for (StubMethod stub in cls.callStubs) { | |
| actualStubs.add(stub.name!.key); | |
| } | |
| } | |
| Expect.setEquals( | |
| expectedStubs, | |
| actualStubs, | |
| "Unexpected stubs for $element:\n " | |
| "Expected: $expectedStubs\n Actual: $actualStubs", | |
| ); | |
| } | |
| checkStubs(closedWorld.commonElements.getInstantiationClass(1), [ | |
| r'call$1', | |
| r'$signature', | |
| ]); | |
| checkStubs(closedWorld.commonElements.getInstantiationClass(2), [ | |
| r'call$2', | |
| r'$signature', | |
| ]); | |
| checkStubs(closedWorld.commonElements.getInstantiationClass(3), [ | |
| r'call$3', | |
| r'call$4', | |
| r'$signature', | |
| ]); | |
| }); | |
| } |