[flutter_tools] delete BuildRunnerWebCompilationProxy and WebCompilationProxy (#70914)
This commit is contained in:
parent
1816778529
commit
ffbca11f1b
@ -50,10 +50,8 @@ import 'src/globals.dart' as globals;
|
|||||||
import 'src/isolated/devtools_launcher.dart';
|
import 'src/isolated/devtools_launcher.dart';
|
||||||
import 'src/isolated/mustache_template.dart';
|
import 'src/isolated/mustache_template.dart';
|
||||||
import 'src/isolated/resident_web_runner.dart';
|
import 'src/isolated/resident_web_runner.dart';
|
||||||
import 'src/isolated/web_compilation_delegate.dart';
|
|
||||||
import 'src/resident_runner.dart';
|
import 'src/resident_runner.dart';
|
||||||
import 'src/runner/flutter_command.dart';
|
import 'src/runner/flutter_command.dart';
|
||||||
import 'src/web/compile.dart';
|
|
||||||
import 'src/web/web_runner.dart';
|
import 'src/web/web_runner.dart';
|
||||||
|
|
||||||
/// Main entry point for commands.
|
/// Main entry point for commands.
|
||||||
@ -145,7 +143,6 @@ Future<void> main(List<String> args) async {
|
|||||||
muteCommandLogging: muteCommandLogging,
|
muteCommandLogging: muteCommandLogging,
|
||||||
verboseHelp: verboseHelp,
|
verboseHelp: verboseHelp,
|
||||||
overrides: <Type, Generator>{
|
overrides: <Type, Generator>{
|
||||||
WebCompilationProxy: () => BuildRunnerWebCompilationProxy(),
|
|
||||||
// The web runner is not supported in google3 because it depends
|
// The web runner is not supported in google3 because it depends
|
||||||
// on dwds.
|
// on dwds.
|
||||||
WebRunnerFactory: () => DwdsWebRunnerFactory(),
|
WebRunnerFactory: () => DwdsWebRunnerFactory(),
|
||||||
|
@ -9,6 +9,7 @@ import 'package:pool/pool.dart';
|
|||||||
|
|
||||||
import 'asset.dart';
|
import 'asset.dart';
|
||||||
import 'base/common.dart';
|
import 'base/common.dart';
|
||||||
|
import 'base/config.dart';
|
||||||
import 'base/file_system.dart';
|
import 'base/file_system.dart';
|
||||||
import 'base/logger.dart';
|
import 'base/logger.dart';
|
||||||
import 'build_info.dart';
|
import 'build_info.dart';
|
||||||
@ -40,6 +41,8 @@ String getDefaultCachedKernelPath({
|
|||||||
@required bool trackWidgetCreation,
|
@required bool trackWidgetCreation,
|
||||||
@required List<String> dartDefines,
|
@required List<String> dartDefines,
|
||||||
@required List<String> extraFrontEndOptions,
|
@required List<String> extraFrontEndOptions,
|
||||||
|
FileSystem fileSystem,
|
||||||
|
Config config,
|
||||||
}) {
|
}) {
|
||||||
final StringBuffer buffer = StringBuffer();
|
final StringBuffer buffer = StringBuffer();
|
||||||
buffer.writeAll(dartDefines);
|
buffer.writeAll(dartDefines);
|
||||||
@ -51,7 +54,10 @@ String getDefaultCachedKernelPath({
|
|||||||
buildPrefix = '${hex.encode(digest.bytes)}.';
|
buildPrefix = '${hex.encode(digest.bytes)}.';
|
||||||
}
|
}
|
||||||
return getKernelPathForTransformerOptions(
|
return getKernelPathForTransformerOptions(
|
||||||
globals.fs.path.join(getBuildDirectory(), '${buildPrefix}cache.dill'),
|
(fileSystem ?? globals.fs).path.join(getBuildDirectory(
|
||||||
|
config ?? globals.config,
|
||||||
|
fileSystem ?? globals.fs
|
||||||
|
), '${buildPrefix}cache.dill'),
|
||||||
trackWidgetCreation: trackWidgetCreation,
|
trackWidgetCreation: trackWidgetCreation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,187 +0,0 @@
|
|||||||
// Copyright 2014 The Flutter Authors. 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:meta/meta.dart';
|
|
||||||
import 'package:package_config/package_config.dart';
|
|
||||||
|
|
||||||
import '../artifacts.dart';
|
|
||||||
import '../base/common.dart';
|
|
||||||
import '../base/file_system.dart';
|
|
||||||
import '../build_info.dart';
|
|
||||||
import '../bundle.dart';
|
|
||||||
import '../compile.dart';
|
|
||||||
import '../dart/language_version.dart';
|
|
||||||
import '../globals.dart' as globals;
|
|
||||||
import '../web/compile.dart';
|
|
||||||
import '../web/memory_fs.dart';
|
|
||||||
|
|
||||||
// TODO(jonahwilliams): this class was kept around to reduce the diff in the migration
|
|
||||||
// from build_runner to the frontend_server, but should be removed/refactored to be
|
|
||||||
// similar to the test_compiler pattern used for regular flutter tests
|
|
||||||
class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
|
|
||||||
BuildRunnerWebCompilationProxy();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<WebMemoryFS> initialize({
|
|
||||||
@required Directory projectDirectory,
|
|
||||||
@required String testOutputDir,
|
|
||||||
@required List<String> testFiles,
|
|
||||||
@required BuildInfo buildInfo,
|
|
||||||
}) async {
|
|
||||||
LanguageVersion languageVersion = LanguageVersion(2, 8);
|
|
||||||
Artifact platformDillArtifact;
|
|
||||||
// TODO(jonahwilliams): to support autodetect this would need to partition the source code into a
|
|
||||||
// a sound and unsound set and perform separate compilations.
|
|
||||||
final List<String> extraFrontEndOptions = List<String>.of(buildInfo.extraFrontEndOptions ?? <String>[]);
|
|
||||||
if (buildInfo.nullSafetyMode == NullSafetyMode.unsound || buildInfo.nullSafetyMode == NullSafetyMode.autodetect) {
|
|
||||||
platformDillArtifact = Artifact.webPlatformKernelDill;
|
|
||||||
if (!extraFrontEndOptions.contains('--no-sound-null-safety')) {
|
|
||||||
extraFrontEndOptions.add('--no-sound-null-safety');
|
|
||||||
}
|
|
||||||
} else if (buildInfo.nullSafetyMode == NullSafetyMode.sound) {
|
|
||||||
platformDillArtifact = Artifact.webPlatformSoundKernelDill;
|
|
||||||
languageVersion = nullSafeVersion;
|
|
||||||
if (!extraFrontEndOptions.contains('--sound-null-safety')) {
|
|
||||||
extraFrontEndOptions.add('--sound-null-safety');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Directory outputDirectory = globals.fs.directory(testOutputDir)
|
|
||||||
..createSync(recursive: true);
|
|
||||||
final List<File> generatedFiles = <File>[];
|
|
||||||
for (final String testFilePath in testFiles) {
|
|
||||||
final List<String> relativeTestSegments = globals.fs.path.split(
|
|
||||||
globals.fs.path.relative(testFilePath, from: projectDirectory.childDirectory('test').path));
|
|
||||||
final File generatedFile = globals.fs.file(
|
|
||||||
globals.fs.path.join(outputDirectory.path, '${relativeTestSegments.join('_')}.test.dart'));
|
|
||||||
generatedFile
|
|
||||||
..createSync(recursive: true)
|
|
||||||
..writeAsStringSync(_generateEntrypoint(relativeTestSegments.join('/'), testFilePath, languageVersion));
|
|
||||||
generatedFiles.add(generatedFile);
|
|
||||||
}
|
|
||||||
// Generate a fake main file that imports all tests to be executed. This will force
|
|
||||||
// each of them to be compiled.
|
|
||||||
final StringBuffer buffer = StringBuffer('// @dart=${languageVersion.major}.${languageVersion.minor}\n');
|
|
||||||
for (final File generatedFile in generatedFiles) {
|
|
||||||
buffer.writeln('import "${globals.fs.path.basename(generatedFile.path)}";');
|
|
||||||
}
|
|
||||||
buffer.writeln('void main() {}');
|
|
||||||
globals.fs.file(globals.fs.path.join(outputDirectory.path, 'main.dart'))
|
|
||||||
..createSync()
|
|
||||||
..writeAsStringSync(buffer.toString());
|
|
||||||
|
|
||||||
final ResidentCompiler residentCompiler = ResidentCompiler(
|
|
||||||
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: buildInfo.mode),
|
|
||||||
buildMode: buildInfo.mode,
|
|
||||||
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
|
||||||
fileSystemRoots: <String>[
|
|
||||||
projectDirectory.childDirectory('test').path,
|
|
||||||
testOutputDir,
|
|
||||||
],
|
|
||||||
// Override the filesystem scheme so that the frontend_server can find
|
|
||||||
// the generated entrypoint code.
|
|
||||||
fileSystemScheme: 'org-dartlang-app',
|
|
||||||
initializeFromDill: getDefaultCachedKernelPath(
|
|
||||||
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
|
||||||
dartDefines: buildInfo.dartDefines,
|
|
||||||
extraFrontEndOptions: extraFrontEndOptions,
|
|
||||||
),
|
|
||||||
targetModel: TargetModel.dartdevc,
|
|
||||||
extraFrontEndOptions: extraFrontEndOptions,
|
|
||||||
platformDill: globals.fs.file(globals.artifacts
|
|
||||||
.getArtifactPath(platformDillArtifact, mode: buildInfo.mode))
|
|
||||||
.absolute.uri.toString(),
|
|
||||||
dartDefines: buildInfo.dartDefines,
|
|
||||||
librariesSpec: globals.fs.file(globals.artifacts
|
|
||||||
.getArtifactPath(Artifact.flutterWebLibrariesJson)).uri.toString(),
|
|
||||||
packagesPath: buildInfo.packagesPath,
|
|
||||||
artifacts: globals.artifacts,
|
|
||||||
processManager: globals.processManager,
|
|
||||||
logger: globals.logger,
|
|
||||||
platform: globals.platform,
|
|
||||||
);
|
|
||||||
|
|
||||||
final CompilerOutput output = await residentCompiler.recompile(
|
|
||||||
Uri.parse('org-dartlang-app:///main.dart'),
|
|
||||||
<Uri>[],
|
|
||||||
outputPath: outputDirectory.childFile('out').path,
|
|
||||||
packageConfig: buildInfo.packageConfig,
|
|
||||||
);
|
|
||||||
if (output.errorCount > 0) {
|
|
||||||
throwToolExit('Failed to compile');
|
|
||||||
}
|
|
||||||
final File codeFile = outputDirectory.childFile('${output.outputFilename}.sources');
|
|
||||||
final File manifestFile = outputDirectory.childFile('${output.outputFilename}.json');
|
|
||||||
final File sourcemapFile = outputDirectory.childFile('${output.outputFilename}.map');
|
|
||||||
final File metadataFile = outputDirectory.childFile('${output.outputFilename}.metadata');
|
|
||||||
return WebMemoryFS()
|
|
||||||
..write(codeFile, manifestFile, sourcemapFile, metadataFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
String _generateEntrypoint(String relativeTestPath, String absolutePath, LanguageVersion languageVersion) {
|
|
||||||
return '''
|
|
||||||
// @dart = ${languageVersion.major}.${languageVersion.minor}
|
|
||||||
import 'org-dartlang-app:///$relativeTestPath' as test;
|
|
||||||
import 'dart:ui' as ui;
|
|
||||||
import 'dart:html';
|
|
||||||
import 'dart:js';
|
|
||||||
import 'package:stream_channel/stream_channel.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:test_api/src/backend/stack_trace_formatter.dart'; // ignore: implementation_imports
|
|
||||||
import 'package:test_api/src/remote_listener.dart'; // ignore: implementation_imports
|
|
||||||
import 'package:test_api/src/suite_channel_manager.dart'; // ignore: implementation_imports
|
|
||||||
|
|
||||||
// Extra initialization for flutter_web.
|
|
||||||
// The following parameters are hard-coded in Flutter's test embedder. Since
|
|
||||||
// we don't have an embedder yet this is the lowest-most layer we can put
|
|
||||||
// this stuff in.
|
|
||||||
Future<void> main() async {
|
|
||||||
ui.debugEmulateFlutterTesterEnvironment = true;
|
|
||||||
await ui.webOnlyInitializePlatform();
|
|
||||||
webGoldenComparator = DefaultWebGoldenComparator(Uri.parse('$absolutePath'));
|
|
||||||
(ui.window as dynamic).debugOverrideDevicePixelRatio(3.0);
|
|
||||||
(ui.window as dynamic).webOnlyDebugPhysicalSizeOverride = const ui.Size(2400, 1800);
|
|
||||||
internalBootstrapBrowserTest(() => test.main);
|
|
||||||
}
|
|
||||||
|
|
||||||
void internalBootstrapBrowserTest(Function getMain()) {
|
|
||||||
var channel = serializeSuite(getMain, hidePrints: false);
|
|
||||||
postMessageChannel().pipe(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamChannel serializeSuite(Function getMain(), {bool hidePrints = true}) => RemoteListener.start(getMain, hidePrints: hidePrints);
|
|
||||||
|
|
||||||
StreamChannel suiteChannel(String name) {
|
|
||||||
var manager = SuiteChannelManager.current;
|
|
||||||
if (manager == null) {
|
|
||||||
throw StateError('suiteChannel() may only be called within a test worker.');
|
|
||||||
}
|
|
||||||
return manager.connectOut(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamChannel postMessageChannel() {
|
|
||||||
var controller = StreamChannelController(sync: true);
|
|
||||||
window.onMessage.firstWhere((message) {
|
|
||||||
return message.origin == window.location.origin && message.data == "port";
|
|
||||||
}).then((message) {
|
|
||||||
var port = message.ports.first;
|
|
||||||
var portSubscription = port.onMessage.listen((message) {
|
|
||||||
controller.local.sink.add(message.data);
|
|
||||||
});
|
|
||||||
controller.local.stream.listen((data) {
|
|
||||||
port.postMessage({"data": data});
|
|
||||||
}, onDone: () {
|
|
||||||
port.postMessage({"event": "done"});
|
|
||||||
portSubscription.cancel();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
context['parent'].callMethod('postMessage', [
|
|
||||||
JsObject.jsify({"href": window.location.href, "ready": true}),
|
|
||||||
window.location.origin,
|
|
||||||
]);
|
|
||||||
return controller.foreign;
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,12 +12,12 @@ import '../build_info.dart';
|
|||||||
import '../globals.dart' as globals;
|
import '../globals.dart' as globals;
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../web/chrome.dart';
|
import '../web/chrome.dart';
|
||||||
import '../web/compile.dart';
|
|
||||||
import '../web/memory_fs.dart';
|
import '../web/memory_fs.dart';
|
||||||
import 'flutter_platform.dart' as loader;
|
import 'flutter_platform.dart' as loader;
|
||||||
import 'flutter_web_platform.dart';
|
import 'flutter_web_platform.dart';
|
||||||
import 'test_wrapper.dart';
|
import 'test_wrapper.dart';
|
||||||
import 'watcher.dart';
|
import 'watcher.dart';
|
||||||
|
import 'web_test_compiler.dart';
|
||||||
|
|
||||||
/// A class that abstracts launching the test process from the test runner.
|
/// A class that abstracts launching the test process from the test runner.
|
||||||
abstract class FlutterTestRunner {
|
abstract class FlutterTestRunner {
|
||||||
@ -123,7 +123,14 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
|||||||
.absolute
|
.absolute
|
||||||
.uri
|
.uri
|
||||||
.toFilePath();
|
.toFilePath();
|
||||||
final WebMemoryFS result = await webCompilationProxy.initialize(
|
final WebMemoryFS result = await WebTestCompiler(
|
||||||
|
logger: globals.logger,
|
||||||
|
fileSystem: globals.fs,
|
||||||
|
platform: globals.platform,
|
||||||
|
artifacts: globals.artifacts,
|
||||||
|
processManager: globals.processManager,
|
||||||
|
config: globals.config,
|
||||||
|
).initialize(
|
||||||
projectDirectory: flutterProject.directory,
|
projectDirectory: flutterProject.directory,
|
||||||
testOutputDir: tempBuildDir,
|
testOutputDir: tempBuildDir,
|
||||||
testFiles: testFiles,
|
testFiles: testFiles,
|
||||||
|
151
packages/flutter_tools/lib/src/test/web_test_compiler.dart
Normal file
151
packages/flutter_tools/lib/src/test/web_test_compiler.dart
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. 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:meta/meta.dart';
|
||||||
|
import 'package:package_config/package_config.dart';
|
||||||
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
|
import '../artifacts.dart';
|
||||||
|
import '../base/common.dart';
|
||||||
|
import '../base/config.dart';
|
||||||
|
import '../base/file_system.dart';
|
||||||
|
import '../base/logger.dart';
|
||||||
|
import '../base/platform.dart';
|
||||||
|
import '../build_info.dart';
|
||||||
|
import '../bundle.dart';
|
||||||
|
import '../compile.dart';
|
||||||
|
import '../dart/language_version.dart';
|
||||||
|
import '../web/bootstrap.dart';
|
||||||
|
import '../web/memory_fs.dart';
|
||||||
|
|
||||||
|
/// A web compiler for the test runner.
|
||||||
|
class WebTestCompiler {
|
||||||
|
WebTestCompiler({
|
||||||
|
@required FileSystem fileSystem,
|
||||||
|
@required Logger logger,
|
||||||
|
@required Artifacts artifacts,
|
||||||
|
@required Platform platform,
|
||||||
|
@required ProcessManager processManager,
|
||||||
|
@required Config config,
|
||||||
|
}) : _logger = logger,
|
||||||
|
_fileSystem = fileSystem,
|
||||||
|
_artifacts = artifacts,
|
||||||
|
_platform = platform,
|
||||||
|
_processManager = processManager,
|
||||||
|
_config = config;
|
||||||
|
|
||||||
|
final Logger _logger;
|
||||||
|
final FileSystem _fileSystem;
|
||||||
|
final Artifacts _artifacts;
|
||||||
|
final Platform _platform;
|
||||||
|
final ProcessManager _processManager;
|
||||||
|
final Config _config;
|
||||||
|
|
||||||
|
Future<WebMemoryFS> initialize({
|
||||||
|
@required Directory projectDirectory,
|
||||||
|
@required String testOutputDir,
|
||||||
|
@required List<String> testFiles,
|
||||||
|
@required BuildInfo buildInfo,
|
||||||
|
}) async {
|
||||||
|
LanguageVersion languageVersion = LanguageVersion(2, 8);
|
||||||
|
Artifact platformDillArtifact;
|
||||||
|
// TODO(jonahwilliams): to support autodetect this would need to partition the source code into a
|
||||||
|
// a sound and unsound set and perform separate compilations.
|
||||||
|
final List<String> extraFrontEndOptions = List<String>.of(buildInfo.extraFrontEndOptions ?? <String>[]);
|
||||||
|
if (buildInfo.nullSafetyMode == NullSafetyMode.unsound || buildInfo.nullSafetyMode == NullSafetyMode.autodetect) {
|
||||||
|
platformDillArtifact = Artifact.webPlatformKernelDill;
|
||||||
|
if (!extraFrontEndOptions.contains('--no-sound-null-safety')) {
|
||||||
|
extraFrontEndOptions.add('--no-sound-null-safety');
|
||||||
|
}
|
||||||
|
} else if (buildInfo.nullSafetyMode == NullSafetyMode.sound) {
|
||||||
|
platformDillArtifact = Artifact.webPlatformSoundKernelDill;
|
||||||
|
languageVersion = nullSafeVersion;
|
||||||
|
if (!extraFrontEndOptions.contains('--sound-null-safety')) {
|
||||||
|
extraFrontEndOptions.add('--sound-null-safety');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Directory outputDirectory = _fileSystem.directory(testOutputDir)
|
||||||
|
..createSync(recursive: true);
|
||||||
|
final List<File> generatedFiles = <File>[];
|
||||||
|
for (final String testFilePath in testFiles) {
|
||||||
|
final List<String> relativeTestSegments = _fileSystem.path.split(
|
||||||
|
_fileSystem.path.relative(testFilePath, from: projectDirectory.childDirectory('test').path));
|
||||||
|
final File generatedFile = _fileSystem.file(
|
||||||
|
_fileSystem.path.join(outputDirectory.path, '${relativeTestSegments.join('_')}.test.dart'));
|
||||||
|
generatedFile
|
||||||
|
..createSync(recursive: true)
|
||||||
|
..writeAsStringSync(generateTestEntrypoint(
|
||||||
|
relativeTestPath: relativeTestSegments.join('/'),
|
||||||
|
absolutePath: testFilePath,
|
||||||
|
languageVersion: languageVersion,
|
||||||
|
));
|
||||||
|
generatedFiles.add(generatedFile);
|
||||||
|
}
|
||||||
|
// Generate a fake main file that imports all tests to be executed. This will force
|
||||||
|
// each of them to be compiled.
|
||||||
|
final StringBuffer buffer = StringBuffer('// @dart=${languageVersion.major}.${languageVersion.minor}\n');
|
||||||
|
for (final File generatedFile in generatedFiles) {
|
||||||
|
buffer.writeln('import "${_fileSystem.path.basename(generatedFile.path)}";');
|
||||||
|
}
|
||||||
|
buffer.writeln('void main() {}');
|
||||||
|
_fileSystem.file(_fileSystem.path.join(outputDirectory.path, 'main.dart'))
|
||||||
|
..createSync()
|
||||||
|
..writeAsStringSync(buffer.toString());
|
||||||
|
|
||||||
|
final String cachedKernelPath = getDefaultCachedKernelPath(
|
||||||
|
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
||||||
|
dartDefines: buildInfo.dartDefines,
|
||||||
|
extraFrontEndOptions: extraFrontEndOptions,
|
||||||
|
fileSystem: _fileSystem,
|
||||||
|
config: _config,
|
||||||
|
);
|
||||||
|
final ResidentCompiler residentCompiler = ResidentCompiler(
|
||||||
|
_artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: buildInfo.mode),
|
||||||
|
buildMode: buildInfo.mode,
|
||||||
|
trackWidgetCreation: buildInfo.trackWidgetCreation,
|
||||||
|
fileSystemRoots: <String>[
|
||||||
|
projectDirectory.childDirectory('test').path,
|
||||||
|
testOutputDir,
|
||||||
|
],
|
||||||
|
// Override the filesystem scheme so that the frontend_server can find
|
||||||
|
// the generated entrypoint code.
|
||||||
|
fileSystemScheme: 'org-dartlang-app',
|
||||||
|
initializeFromDill: cachedKernelPath,
|
||||||
|
targetModel: TargetModel.dartdevc,
|
||||||
|
extraFrontEndOptions: extraFrontEndOptions,
|
||||||
|
platformDill: _fileSystem.file(_artifacts
|
||||||
|
.getArtifactPath(platformDillArtifact, mode: buildInfo.mode))
|
||||||
|
.absolute.uri.toString(),
|
||||||
|
dartDefines: buildInfo.dartDefines,
|
||||||
|
librariesSpec: _fileSystem.file(_artifacts
|
||||||
|
.getArtifactPath(Artifact.flutterWebLibrariesJson)).uri.toString(),
|
||||||
|
packagesPath: buildInfo.packagesPath,
|
||||||
|
artifacts: _artifacts,
|
||||||
|
processManager: _processManager,
|
||||||
|
logger: _logger,
|
||||||
|
platform: _platform,
|
||||||
|
);
|
||||||
|
|
||||||
|
final CompilerOutput output = await residentCompiler.recompile(
|
||||||
|
Uri.parse('org-dartlang-app:///main.dart'),
|
||||||
|
<Uri>[],
|
||||||
|
outputPath: outputDirectory.childFile('out').path,
|
||||||
|
packageConfig: buildInfo.packageConfig,
|
||||||
|
);
|
||||||
|
if (output.errorCount > 0) {
|
||||||
|
throwToolExit('Failed to compile');
|
||||||
|
}
|
||||||
|
// Cache the output kernel file to speed up subsequent compiles.
|
||||||
|
_fileSystem.file(cachedKernelPath).parent.createSync(recursive: true);
|
||||||
|
_fileSystem.file(output.outputFilename).copySync(cachedKernelPath);
|
||||||
|
|
||||||
|
final File codeFile = outputDirectory.childFile('${output.outputFilename}.sources');
|
||||||
|
final File manifestFile = outputDirectory.childFile('${output.outputFilename}.json');
|
||||||
|
final File sourcemapFile = outputDirectory.childFile('${output.outputFilename}.map');
|
||||||
|
final File metadataFile = outputDirectory.childFile('${output.outputFilename}.metadata');
|
||||||
|
return WebMemoryFS()
|
||||||
|
..write(codeFile, manifestFile, sourcemapFile, metadataFile);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
import 'package:package_config/package_config.dart';
|
||||||
|
|
||||||
/// The JavaScript bootstrap script to support in-browser hot restart.
|
/// The JavaScript bootstrap script to support in-browser hot restart.
|
||||||
///
|
///
|
||||||
@ -95,6 +96,75 @@ define("$bootstrapModule", ["$entrypoint", "dart_sdk"], function(app, dart_sdk)
|
|||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates the bootstrap logic required for a flutter test running in a browser.
|
||||||
|
///
|
||||||
|
/// This hard-codes the device pixel ratio to 3.0 and a 2400 x 1800 window size.
|
||||||
|
String generateTestEntrypoint({
|
||||||
|
@required String relativeTestPath,
|
||||||
|
@required String absolutePath,
|
||||||
|
@required LanguageVersion languageVersion,
|
||||||
|
}) {
|
||||||
|
return '''
|
||||||
|
// @dart = ${languageVersion.major}.${languageVersion.minor}
|
||||||
|
import 'org-dartlang-app:///$relativeTestPath' as test;
|
||||||
|
import 'dart:ui' as ui;
|
||||||
|
import 'dart:html';
|
||||||
|
import 'dart:js';
|
||||||
|
import 'package:stream_channel/stream_channel.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:test_api/src/backend/stack_trace_formatter.dart'; // ignore: implementation_imports
|
||||||
|
import 'package:test_api/src/remote_listener.dart'; // ignore: implementation_imports
|
||||||
|
import 'package:test_api/src/suite_channel_manager.dart'; // ignore: implementation_imports
|
||||||
|
|
||||||
|
Future<void> main() async {
|
||||||
|
ui.debugEmulateFlutterTesterEnvironment = true;
|
||||||
|
await ui.webOnlyInitializePlatform();
|
||||||
|
webGoldenComparator = DefaultWebGoldenComparator(Uri.parse('$absolutePath'));
|
||||||
|
(ui.window as dynamic).debugOverrideDevicePixelRatio(3.0);
|
||||||
|
(ui.window as dynamic).webOnlyDebugPhysicalSizeOverride = const ui.Size(2400, 1800);
|
||||||
|
internalBootstrapBrowserTest(() => test.main);
|
||||||
|
}
|
||||||
|
|
||||||
|
void internalBootstrapBrowserTest(Function getMain()) {
|
||||||
|
var channel = serializeSuite(getMain, hidePrints: false);
|
||||||
|
postMessageChannel().pipe(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamChannel serializeSuite(Function getMain(), {bool hidePrints = true}) => RemoteListener.start(getMain, hidePrints: hidePrints);
|
||||||
|
|
||||||
|
StreamChannel suiteChannel(String name) {
|
||||||
|
var manager = SuiteChannelManager.current;
|
||||||
|
if (manager == null) {
|
||||||
|
throw StateError('suiteChannel() may only be called within a test worker.');
|
||||||
|
}
|
||||||
|
return manager.connectOut(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamChannel postMessageChannel() {
|
||||||
|
var controller = StreamChannelController(sync: true);
|
||||||
|
window.onMessage.firstWhere((message) {
|
||||||
|
return message.origin == window.location.origin && message.data == "port";
|
||||||
|
}).then((message) {
|
||||||
|
var port = message.ports.first;
|
||||||
|
var portSubscription = port.onMessage.listen((message) {
|
||||||
|
controller.local.sink.add(message.data);
|
||||||
|
});
|
||||||
|
controller.local.stream.listen((data) {
|
||||||
|
port.postMessage({"data": data});
|
||||||
|
}, onDone: () {
|
||||||
|
port.postMessage({"event": "done"});
|
||||||
|
portSubscription.cancel();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
context['parent'].callMethod('postMessage', [
|
||||||
|
JsObject.jsify({"href": window.location.href, "ready": true}),
|
||||||
|
window.location.origin,
|
||||||
|
]);
|
||||||
|
return controller.foreign;
|
||||||
|
}
|
||||||
|
''';
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate the unit test bootstrap file.
|
/// Generate the unit test bootstrap file.
|
||||||
String generateTestBootstrapFileContents(String mainUri, String requireUrl, String mapperUrl) {
|
String generateTestBootstrapFileContents(String mainUri, String requireUrl, String mapperUrl) {
|
||||||
return '''
|
return '''
|
||||||
|
@ -2,11 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
|
|
||||||
import '../artifacts.dart';
|
import '../artifacts.dart';
|
||||||
import '../base/common.dart';
|
import '../base/common.dart';
|
||||||
import '../base/context.dart';
|
|
||||||
import '../base/file_system.dart';
|
import '../base/file_system.dart';
|
||||||
import '../base/logger.dart';
|
import '../base/logger.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
@ -19,10 +16,6 @@ import '../globals.dart' as globals;
|
|||||||
import '../platform_plugins.dart';
|
import '../platform_plugins.dart';
|
||||||
import '../plugins.dart';
|
import '../plugins.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../web/memory_fs.dart';
|
|
||||||
|
|
||||||
/// The [WebCompilationProxy] instance.
|
|
||||||
WebCompilationProxy get webCompilationProxy => context.get<WebCompilationProxy>();
|
|
||||||
|
|
||||||
Future<void> buildWeb(
|
Future<void> buildWeb(
|
||||||
FlutterProject flutterProject,
|
FlutterProject flutterProject,
|
||||||
@ -91,23 +84,6 @@ Future<void> buildWeb(
|
|||||||
globals.flutterUsage.sendTiming('build', 'dart2js', Duration(milliseconds: sw.elapsedMilliseconds));
|
globals.flutterUsage.sendTiming('build', 'dart2js', Duration(milliseconds: sw.elapsedMilliseconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An indirection on web compilation.
|
|
||||||
///
|
|
||||||
/// Avoids issues with syncing build_runner_core to other repos.
|
|
||||||
class WebCompilationProxy {
|
|
||||||
const WebCompilationProxy();
|
|
||||||
|
|
||||||
/// Initialize the web compiler from the `projectDirectory`.
|
|
||||||
Future<WebMemoryFS> initialize({
|
|
||||||
@required Directory projectDirectory,
|
|
||||||
@required String testOutputDir,
|
|
||||||
@required List<String> testFiles,
|
|
||||||
@required BuildInfo buildInfo,
|
|
||||||
}) async {
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Web rendering backend mode.
|
/// Web rendering backend mode.
|
||||||
enum WebRendererMode {
|
enum WebRendererMode {
|
||||||
/// Auto detects which rendering backend to use.
|
/// Auto detects which rendering backend to use.
|
||||||
|
@ -14,9 +14,9 @@ import 'package:flutter_tools/src/test/test_compiler.dart';
|
|||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
import 'package:package_config/package_config_types.dart';
|
import 'package:package_config/package_config_types.dart';
|
||||||
|
|
||||||
import '../src/common.dart';
|
import '../../src/common.dart';
|
||||||
import '../src/context.dart';
|
import '../../src/context.dart';
|
||||||
import '../src/testbed.dart';
|
import '../../src/testbed.dart';
|
||||||
|
|
||||||
final Platform linuxPlatform = FakePlatform(
|
final Platform linuxPlatform = FakePlatform(
|
||||||
operatingSystem: 'linux',
|
operatingSystem: 'linux',
|
Loading…
x
Reference in New Issue
Block a user