blob: c853b01314a894a802a3f428bdb5ecde329cfed4 [file] [log] [blame]
// Copyright (c) 2019, 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 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
import 'package:front_end/src/api_prototype/standard_file_system.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/verifier.dart';
import 'package:vm/target/vm.dart';
import 'package:vm/kernel_front_end.dart';
main() async {
Uri sdkSummary =
sdkRootFile(Platform.executable).resolve('vm_platform_strong.dill');
if (!await File.fromUri(sdkSummary).exists()) {
// If we run from the <build-dir>/dart-sdk/bin folder, we need to navigate two
// levels up.
sdkSummary = sdkRootFile(Platform.executable)
.resolve('../../vm_platform_strong.dill');
}
// Tests are run in the root directory of the sdk checkout.
final Uri packagesFile = sdkRootFile('.packages');
final Uri librariesFile = sdkRootFile('sdk/lib/libraries.json');
final vmTarget = VmTarget(TargetFlags());
await withTempDirectory((Uri uri) async {
final mixinFilename = uri.resolve('mixin.dart');
final mixinDillFilename = uri.resolve('mixin.dart.dill');
File.fromUri(mixinFilename).writeAsStringSync(mixinFile);
await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
mixinDillFilename, <Uri>[mixinFilename], <Uri>[]);
final mainFilename = uri.resolve('main.dart');
final mainDillFilename = uri.resolve('main.dart.dill');
File.fromUri(mainFilename).writeAsStringSync(mainFile);
await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
mainDillFilename, <Uri>[mainFilename], <Uri>[mixinDillFilename]);
final bytes = concat(
await File.fromUri(sdkSummary).readAsBytes(),
concat(await File.fromUri(mixinDillFilename).readAsBytes(),
await File.fromUri(mainDillFilename).readAsBytes()));
final component = loadComponentFromBytes(bytes);
// Verify before running global transformations.
verifyComponent(component, isOutline: false, afterConst: true);
const useGlobalTypeFlowAnalysis = true;
const enableAsserts = false;
const useProtobufTreeShakerV2 = false;
await runGlobalTransformations(
vmTarget,
component,
useGlobalTypeFlowAnalysis,
enableAsserts,
useProtobufTreeShakerV2,
ErrorDetector());
// Verify after running global transformations.
verifyComponent(component, isOutline: false, afterConst: true);
// Verify that we can reserialize the component to ensure that all
// references are contained within the component.
writeComponentToBytes(
loadComponentFromBytes(writeComponentToBytes(component)));
});
}
Future compileToKernel(
Target target,
Uri librariesFile,
Uri sdkSummary,
Uri packagesFile,
Uri outputFile,
List<Uri> sources,
List<Uri> additionalDills) async {
final state = await fe.initializeCompiler(
null,
sdkSummary,
librariesFile,
packagesFile,
additionalDills,
target,
StandardFileSystem.instance, const <String>[], const <String, String>{});
void onDiagnostic(fe.DiagnosticMessage message) {
message.plainTextFormatted.forEach(print);
}
final Component? component =
await fe.compileComponent(state, sources, onDiagnostic);
final Uint8List kernel = fe.serializeComponent(component!,
filter: (library) => sources.contains(library.importUri));
await File(outputFile.toFilePath()).writeAsBytes(kernel);
}
Future withTempDirectory(Future func(Uri dirUri)) async {
final dir = await Directory.systemTemp.createTemp('modular-compile-test');
try {
await func(dir.uri);
} finally {
await dir.delete(recursive: true);
}
}
Uint8List concat(List<int> a, List<int> b) {
final bytes = Uint8List(a.length + b.length);
bytes.setRange(0, a.length, a);
bytes.setRange(a.length, bytes.length, b);
return bytes;
}
Uri sdkRootFile(name) => Directory.current.uri.resolveUri(Uri.file(name));
const String mainFile = r'''
// @dart=2.9
// This library is opt-out to provoke the creation of member signatures in
// R that point to members of A2.
import 'mixin.dart';
class R extends A2 {
void bar() {
mixinProperty = '';
mixinProperty.foo();
mixinMethod('').foo();
super.mixinProperty= '';
super.mixinProperty.foo();
super.mixinMethod('').foo();
}
}
main() {
A1();
final a2 = A2();
// The mixin deduplication will remove the anonymous mixin application class
// from `A2 & Mixin` and instead use the one from `A1 & Mixin`.
a2.mixinProperty= '';
a2.mixinProperty.foo();
a2.mixinMethod('').foo();
R().bar();
B1();
B1.named();
B2();
final b2 = B2.named();
// The mixin deduplication will remove the anonymous mixin application class
// from `B2 & Mixin` and instead use the one from `B1 & Mixin`.
b2.mixinProperty= '';
b2.mixinProperty.foo();
b2.mixinMethod('').foo();
}
''';
const String mixinFile = r'''
class Foo {
foo() {}
}
class Mixin {
void set mixinProperty(v) {}
Foo get mixinProperty => new Foo();
Foo mixinMethod(v) => new Foo();
}
class A1 extends Object with Mixin { }
class A2 extends Object with Mixin { }
class B {
B();
B.named();
}
class B1 extends B with Mixin {
B1() : super();
B1.named() : super.named();
}
class B2 extends B with Mixin {
B2() : super();
B2.named() : super.named();
}
''';