blob: 6b4695c5c21e03655eab3867ae95293cee021476 [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:typed_data';
import 'package:compiler/src/elements/names.dart';
import 'package:compiler/src/util/memory_compiler.dart';
import 'package:expect/async_helper.dart';
import 'package:compiler/src/common/elements.dart';
import 'package:compiler/src/elements/entities.dart'
show LibraryEntity, ClassEntity;
import 'package:compiler/src/kernel/dart2js_target.dart';
import 'package:compiler/src/phase/load_kernel.dart' as load_kernel;
import 'package:expect/expect.dart';
import 'package:front_end/src/api_prototype/front_end.dart';
import 'package:front_end/src/api_prototype/memory_file_system.dart';
import 'package:front_end/src/api_prototype/standard_file_system.dart';
import 'package:front_end/src/api_unstable/dart2js.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/target/targets.dart' show TargetFlags;
/// Test that the compiler can load kernel in modular fragments.
main() {
asyncTest(() async {
var aDill = await compileUnit(['a0.dart'], {'a0.dart': sourceA});
var bDill = await compileUnit(
['b1.dart'],
{'b1.dart': sourceB, 'a.dill': aDill},
deps: ['a.dill'],
);
var cDill = await compileUnit(
['c2.dart'],
{'c2.dart': sourceC, 'a.dill': aDill, 'b.dill': bDill},
deps: ['a.dill', 'b.dill'],
);
var unusedDill = await compileUnit(
['unused0.dart'],
{'unused0.dart': unusedSource},
);
DiagnosticCollector diagnostics = DiagnosticCollector();
OutputCollector output = OutputCollector();
Uri entryPoint = Uri.parse('org-dartlang-test:///c2.dart');
var compiler = compilerFor(
entryPoint: entryPoint,
options: [
'--input-dill=memory:c.dill',
'--dill-dependencies=memory:a.dill,memory:b.dill,memory:unused.dill',
],
memorySourceFiles: {
'a.dill': aDill,
'b.dill': bDill,
'c.dill': cDill,
'unused.dill': unusedDill,
},
diagnosticHandler: diagnostics,
outputProvider: output,
);
load_kernel.Output result =
(await load_kernel.run(
load_kernel.Input(
compiler.options,
compiler.provider,
compiler.reporter,
compiler.initializedCompilerState,
false,
),
))!;
// Make sure we trim the unused library.
Expect.isFalse(result.libraries!.any((l) => l.path == '/unused0.dart'));
compiler.frontendStrategy.registerLoadedLibraries(
result.component,
result.libraries!,
);
Expect.equals(0, diagnostics.errors.length);
Expect.equals(0, diagnostics.warnings.length);
ElementEnvironment environment =
compiler.frontendStrategy.elementEnvironment;
LibraryEntity? library = environment.lookupLibrary(toTestUri('b1.dart'));
Expect.isNotNull(library);
ClassEntity? clss = environment.lookupClass(library!, 'B1');
Expect.isNotNull(clss);
var member = environment.lookupClassMember(clss!, PublicName('foo'));
Expect.isNotNull(member);
});
}
/// Generate a component for a modular compilation unit.
Future<Uint8List> compileUnit(
List<String> inputs,
Map<String, dynamic> sources, {
List<String> deps = const [],
}) async {
var fs = MemoryFileSystem(_defaultDir);
sources.forEach((name, data) {
var entity = fs.entityForUri(toTestUri(name));
if (data is String) {
entity.writeAsStringSync(data);
} else {
entity.writeAsBytesSync(data);
}
});
List<Uri> additionalDills = [
computePlatformBinariesLocation().resolve("dart2js_platform.dill"),
]..addAll(deps.map(toTestUri));
fs
.entityForUri(toTestUri('.dart_tool/package_config.json'))
.writeAsStringSync('{"configVersion": 2, "packages": []}');
var options =
CompilerOptions()
..target = Dart2jsTarget("dart2js", TargetFlags())
..fileSystem = TestFileSystem(fs)
..additionalDills = additionalDills
..packagesFileUri = toTestUri('.dart_tool/package_config.json')
..explicitExperimentalFlags = {ExperimentalFlag.nonNullable: true};
var inputUris = inputs.map(toTestUri).toList();
var inputUriSet = inputUris.toSet();
var component = (await kernelForModule(inputUris, options)).component;
for (var lib in component!.libraries) {
if (!inputUriSet.contains(lib.importUri)) {
lib.bindCanonicalNames(component.root);
}
}
return serializeComponent(
component,
filter: (Library lib) => inputUriSet.contains(lib.importUri),
);
}
Uri _defaultDir = Uri.parse('org-dartlang-test:///');
Uri toTestUri(String relativePath) => _defaultDir.resolve(relativePath);
class TestFileSystem implements FileSystem {
final MemoryFileSystem memory;
final FileSystem physical = StandardFileSystem.instance;
TestFileSystem(this.memory);
@override
FileSystemEntity entityForUri(Uri uri) {
if (uri.isScheme('file')) return physical.entityForUri(uri);
return memory.entityForUri(uri);
}
}
const sourceA = '''
class A0 {
StringBuffer buffer = StringBuffer();
}
''';
const sourceB = '''
import 'a0.dart';
class B1 extends A0 {
A0? get foo => null;
}
A0 createA0() => A0();
''';
const sourceC = '''
import 'b1.dart';
class C2 extends B1 {
final foo = createA0();
}
main() => print(C2().foo.buffer.toString());
''';
const unusedSource = '''
void unused() => throw 'Unused';
''';