Unverified Commit 79a985f9 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Add compiler configuration to support dartdevc target (#43281)

parent 58c46a83
...@@ -40,6 +40,8 @@ enum Artifact { ...@@ -40,6 +40,8 @@ enum Artifact {
kernelWorkerSnapshot, kernelWorkerSnapshot,
/// The root of the web implementation of the dart SDK. /// The root of the web implementation of the dart SDK.
flutterWebSdk, flutterWebSdk,
/// The summary dill for the dartdevc target.
webPlatformKernelDill,
iosDeploy, iosDeploy,
ideviceinfo, ideviceinfo,
ideviceId, ideviceId,
...@@ -126,6 +128,8 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo ...@@ -126,6 +128,8 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo
return 'sky_engine'; return 'sky_engine';
case Artifact.flutterMacOSPodspec: case Artifact.flutterMacOSPodspec:
return 'FlutterMacOS.podspec'; return 'FlutterMacOS.podspec';
case Artifact.webPlatformKernelDill:
return 'flutter_ddc_sdk.dill';
} }
assert(false, 'Invalid artifact $artifact.'); assert(false, 'Invalid artifact $artifact.');
return null; return null;
...@@ -290,6 +294,8 @@ class CachedArtifacts extends Artifacts { ...@@ -290,6 +294,8 @@ class CachedArtifacts extends Artifacts {
return _getFlutterPatchedSdkPath(mode); return _getFlutterPatchedSdkPath(mode);
case Artifact.flutterWebSdk: case Artifact.flutterWebSdk:
return _getFlutterWebSdkPath(); return _getFlutterWebSdkPath();
case Artifact.webPlatformKernelDill:
return fs.path.join(_getFlutterWebSdkPath(), 'kernel', _artifactToFileName(artifact));
case Artifact.dart2jsSnapshot: case Artifact.dart2jsSnapshot:
return fs.path.join(dartSdkPath, 'bin', 'snapshots', _artifactToFileName(artifact)); return fs.path.join(dartSdkPath, 'bin', 'snapshots', _artifactToFileName(artifact));
case Artifact.dartdevcSnapshot: case Artifact.dartdevcSnapshot:
...@@ -422,6 +428,8 @@ class LocalEngineArtifacts extends Artifacts { ...@@ -422,6 +428,8 @@ class LocalEngineArtifacts extends Artifacts {
return fs.path.join(_hostEngineOutPath, 'gen', 'dart-pkg', artifactFileName); return fs.path.join(_hostEngineOutPath, 'gen', 'dart-pkg', artifactFileName);
case Artifact.flutterMacOSPodspec: case Artifact.flutterMacOSPodspec:
return fs.path.join(_hostEngineOutPath, _artifactToFileName(artifact)); return fs.path.join(_hostEngineOutPath, _artifactToFileName(artifact));
case Artifact.webPlatformKernelDill:
return fs.path.join(_getFlutterWebSdkPath(), 'kernel', _artifactToFileName(artifact));
} }
assert(false, 'Invalid artifact $artifact.'); assert(false, 'Invalid artifact $artifact.');
return null; return null;
......
...@@ -52,6 +52,8 @@ class TargetModel { ...@@ -52,6 +52,8 @@ class TargetModel {
return flutterRunner; return flutterRunner;
case 'vm': case 'vm':
return vm; return vm;
case 'dartdevc':
return dartdevc;
} }
assert(false); assert(false);
return null; return null;
...@@ -68,6 +70,9 @@ class TargetModel { ...@@ -68,6 +70,9 @@ class TargetModel {
/// The Dart vm. /// The Dart vm.
static const TargetModel vm = TargetModel._('vm'); static const TargetModel vm = TargetModel._('vm');
/// The development compiler for JavaScript.
static const TargetModel dartdevc = TargetModel._('dartdevc');
final String _value; final String _value;
@override @override
...@@ -383,9 +388,9 @@ abstract class _CompilationRequest { ...@@ -383,9 +388,9 @@ abstract class _CompilationRequest {
Completer<CompilerOutput> completer; Completer<CompilerOutput> completer;
Future<CompilerOutput> _run(ResidentCompiler compiler); Future<CompilerOutput> _run(DefaultResidentCompiler compiler);
Future<void> run(ResidentCompiler compiler) async { Future<void> run(DefaultResidentCompiler compiler) async {
completer.complete(await _run(compiler)); completer.complete(await _run(compiler));
} }
} }
...@@ -405,7 +410,7 @@ class _RecompileRequest extends _CompilationRequest { ...@@ -405,7 +410,7 @@ class _RecompileRequest extends _CompilationRequest {
String packagesFilePath; String packagesFilePath;
@override @override
Future<CompilerOutput> _run(ResidentCompiler compiler) async => Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
compiler._recompile(this); compiler._recompile(this);
} }
...@@ -428,7 +433,7 @@ class _CompileExpressionRequest extends _CompilationRequest { ...@@ -428,7 +433,7 @@ class _CompileExpressionRequest extends _CompilationRequest {
bool isStatic; bool isStatic;
@override @override
Future<CompilerOutput> _run(ResidentCompiler compiler) async => Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
compiler._compileExpression(this); compiler._compileExpression(this);
} }
...@@ -436,7 +441,7 @@ class _RejectRequest extends _CompilationRequest { ...@@ -436,7 +441,7 @@ class _RejectRequest extends _CompilationRequest {
_RejectRequest(Completer<CompilerOutput> completer) : super(completer); _RejectRequest(Completer<CompilerOutput> completer) : super(completer);
@override @override
Future<CompilerOutput> _run(ResidentCompiler compiler) async => Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
compiler._reject(); compiler._reject();
} }
...@@ -445,55 +450,22 @@ class _RejectRequest extends _CompilationRequest { ...@@ -445,55 +450,22 @@ class _RejectRequest extends _CompilationRequest {
/// ///
/// The wrapper is intended to stay resident in memory as user changes, reloads, /// The wrapper is intended to stay resident in memory as user changes, reloads,
/// restarts the Flutter app. /// restarts the Flutter app.
class ResidentCompiler { abstract class ResidentCompiler {
ResidentCompiler( factory ResidentCompiler(String sdkRoot, {
this._sdkRoot, {
@required BuildMode buildMode, @required BuildMode buildMode,
bool causalAsyncStacks = true, bool causalAsyncStacks,
bool trackWidgetCreation = false, bool trackWidgetCreation,
String packagesPath, String packagesPath,
List<String> fileSystemRoots, List<String> fileSystemRoots,
String fileSystemScheme, String fileSystemScheme,
CompilerMessageConsumer compilerMessageConsumer = printError, CompilerMessageConsumer compilerMessageConsumer,
String initializeFromDill, String initializeFromDill,
TargetModel targetModel = TargetModel.flutter, TargetModel targetModel,
bool unsafePackageSerialization, bool unsafePackageSerialization,
List<String> experimentalFlags, List<String> experimentalFlags,
}) : assert(_sdkRoot != null), String platformDill,
_buildMode = buildMode, }) = DefaultResidentCompiler;
_causalAsyncStacks = causalAsyncStacks,
_trackWidgetCreation = trackWidgetCreation,
_packagesPath = packagesPath,
_fileSystemRoots = fileSystemRoots,
_fileSystemScheme = fileSystemScheme,
_targetModel = targetModel,
_stdoutHandler = StdoutHandler(consumer: compilerMessageConsumer),
_controller = StreamController<_CompilationRequest>(),
_initializeFromDill = initializeFromDill,
_unsafePackageSerialization = unsafePackageSerialization,
_experimentalFlags = experimentalFlags {
// This is a URI, not a file path, so the forward slash is correct even on Windows.
if (!_sdkRoot.endsWith('/')) {
_sdkRoot = '$_sdkRoot/';
}
}
final BuildMode _buildMode;
final bool _causalAsyncStacks;
final bool _trackWidgetCreation;
final String _packagesPath;
final TargetModel _targetModel;
final List<String> _fileSystemRoots;
final String _fileSystemScheme;
String _sdkRoot;
Process _server;
final StdoutHandler _stdoutHandler;
final String _initializeFromDill;
final bool _unsafePackageSerialization;
final List<String> _experimentalFlags;
bool _compileRequestNeedsConfirmation = false;
final StreamController<_CompilationRequest> _controller;
/// If invoked for the first time, it compiles Dart script identified by /// If invoked for the first time, it compiles Dart script identified by
/// [mainPath], [invalidatedFiles] list is ignored. /// [mainPath], [invalidatedFiles] list is ignored.
...@@ -502,6 +474,89 @@ class ResidentCompiler { ...@@ -502,6 +474,89 @@ class ResidentCompiler {
/// point that is used for recompilation. /// point that is used for recompilation.
/// Binary file name is returned if compilation was successful, otherwise /// Binary file name is returned if compilation was successful, otherwise
/// null is returned. /// null is returned.
Future<CompilerOutput> recompile(
String mainPath,
List<Uri> invalidatedFiles, {
@required String outputPath,
String packagesFilePath,
});
Future<CompilerOutput> compileExpression(
String expression,
List<String> definitions,
List<String> typeDefinitions,
String libraryUri,
String klass,
bool isStatic,
);
/// Should be invoked when results of compilation are accepted by the client.
///
/// Either [accept] or [reject] should be called after every [recompile] call.
void accept();
/// Should be invoked when results of compilation are rejected by the client.
///
/// Either [accept] or [reject] should be called after every [recompile] call.
Future<CompilerOutput> reject();
/// Should be invoked when frontend server compiler should forget what was
/// accepted previously so that next call to [recompile] produces complete
/// kernel file.
void reset();
Future<dynamic> shutdown();
}
@visibleForTesting
class DefaultResidentCompiler implements ResidentCompiler {
DefaultResidentCompiler(
String sdkRoot, {
@required this.buildMode,
this.causalAsyncStacks = true,
this.trackWidgetCreation = false,
this.packagesPath,
this.fileSystemRoots,
this.fileSystemScheme,
CompilerMessageConsumer compilerMessageConsumer = printError,
this.initializeFromDill,
this.targetModel = TargetModel.flutter,
this.unsafePackageSerialization,
this.experimentalFlags,
this.platformDill,
}) : assert(sdkRoot != null),
_stdoutHandler = StdoutHandler(consumer: compilerMessageConsumer),
// This is a URI, not a file path, so the forward slash is correct even on Windows.
sdkRoot = sdkRoot.endsWith('/') ? sdkRoot : '$sdkRoot/';
final BuildMode buildMode;
final bool causalAsyncStacks;
final bool trackWidgetCreation;
final String packagesPath;
final TargetModel targetModel;
final List<String> fileSystemRoots;
final String fileSystemScheme;
final String initializeFromDill;
final bool unsafePackageSerialization;
final List<String> experimentalFlags;
/// The path to the root of the Dart SDK used to compile.
///
/// This is used to resolve the [platformDill].
final String sdkRoot;
/// The path to the platform dill file.
///
/// This does not need to be provided for the normal Flutter workflow.
final String platformDill;
Process _server;
final StdoutHandler _stdoutHandler;
bool _compileRequestNeedsConfirmation = false;
final StreamController<_CompilationRequest> _controller = StreamController<_CompilationRequest>();
@override
Future<CompilerOutput> recompile( Future<CompilerOutput> recompile(
String mainPath, String mainPath,
List<Uri> invalidatedFiles, { List<Uri> invalidatedFiles, {
...@@ -526,12 +581,12 @@ class ResidentCompiler { ...@@ -526,12 +581,12 @@ class ResidentCompiler {
// First time recompile is called we actually have to compile the app from // First time recompile is called we actually have to compile the app from
// scratch ignoring list of invalidated files. // scratch ignoring list of invalidated files.
PackageUriMapper packageUriMapper; PackageUriMapper packageUriMapper;
if (request.packagesFilePath != null || _packagesPath != null) { if (request.packagesFilePath != null || packagesPath != null) {
packageUriMapper = PackageUriMapper( packageUriMapper = PackageUriMapper(
request.mainPath, request.mainPath,
request.packagesFilePath ?? _packagesPath, request.packagesFilePath ?? packagesPath,
_fileSystemScheme, fileSystemScheme,
_fileSystemRoots, fileSystemRoots,
); );
} }
...@@ -541,7 +596,7 @@ class ResidentCompiler { ...@@ -541,7 +596,7 @@ class ResidentCompiler {
return _compile( return _compile(
_mapFilename(request.mainPath, packageUriMapper), _mapFilename(request.mainPath, packageUriMapper),
request.outputPath, request.outputPath,
_mapFilename(request.packagesFilePath ?? _packagesPath, /* packageUriMapper= */ null), _mapFilename(request.packagesFilePath ?? packagesPath, /* packageUriMapper= */ null),
); );
} }
...@@ -589,11 +644,11 @@ class ResidentCompiler { ...@@ -589,11 +644,11 @@ class ResidentCompiler {
artifacts.getArtifactPath(Artifact.engineDartBinary), artifacts.getArtifactPath(Artifact.engineDartBinary),
frontendServer, frontendServer,
'--sdk-root', '--sdk-root',
_sdkRoot, sdkRoot,
'--incremental', '--incremental',
'--strong', '--strong',
'--target=$_targetModel', '--target=$targetModel',
'-Ddart.developer.causal_async_stacks=$_causalAsyncStacks', '-Ddart.developer.causal_async_stacks=$causalAsyncStacks',
if (outputPath != null) ...<String>[ if (outputPath != null) ...<String>[
'--output-dill', '--output-dill',
outputPath, outputPath,
...@@ -601,28 +656,32 @@ class ResidentCompiler { ...@@ -601,28 +656,32 @@ class ResidentCompiler {
if (packagesFilePath != null) ...<String>[ if (packagesFilePath != null) ...<String>[
'--packages', '--packages',
packagesFilePath, packagesFilePath,
] else if (_packagesPath != null) ...<String>[ ] else if (packagesPath != null) ...<String>[
'--packages', '--packages',
_packagesPath, packagesPath,
], ],
..._buildModeOptions(_buildMode), ..._buildModeOptions(buildMode),
if (_trackWidgetCreation) '--track-widget-creation', if (trackWidgetCreation) '--track-widget-creation',
if (_fileSystemRoots != null) if (fileSystemRoots != null)
for (String root in _fileSystemRoots) ...<String>[ for (String root in fileSystemRoots) ...<String>[
'--filesystem-root', '--filesystem-root',
root, root,
], ],
if (_fileSystemScheme != null) ...<String>[ if (fileSystemScheme != null) ...<String>[
'--filesystem-scheme', '--filesystem-scheme',
_fileSystemScheme, fileSystemScheme,
], ],
if (_initializeFromDill != null) ...<String>[ if (initializeFromDill != null) ...<String>[
'--initialize-from-dill', '--initialize-from-dill',
_initializeFromDill, initializeFromDill,
], ],
if (_unsafePackageSerialization == true) '--unsafe-package-serialization', if (platformDill != null) ...<String>[
if ((_experimentalFlags != null) && _experimentalFlags.isNotEmpty) '--platform',
'--enable-experiment=${_experimentalFlags.join(',')}', platformDill,
],
if (unsafePackageSerialization == true) '--unsafe-package-serialization',
if ((experimentalFlags != null) && experimentalFlags.isNotEmpty)
'--enable-experiment=${experimentalFlags.join(',')}',
]; ];
printTrace(command.join(' ')); printTrace(command.join(' '));
_server = await processManager.start(command); _server = await processManager.start(command);
...@@ -657,6 +716,7 @@ class ResidentCompiler { ...@@ -657,6 +716,7 @@ class ResidentCompiler {
return _stdoutHandler.compilerOutput.future; return _stdoutHandler.compilerOutput.future;
} }
@override
Future<CompilerOutput> compileExpression( Future<CompilerOutput> compileExpression(
String expression, String expression,
List<String> definitions, List<String> definitions,
...@@ -700,9 +760,7 @@ class ResidentCompiler { ...@@ -700,9 +760,7 @@ class ResidentCompiler {
return _stdoutHandler.compilerOutput.future; return _stdoutHandler.compilerOutput.future;
} }
/// Should be invoked when results of compilation are accepted by the client. @override
///
/// Either [accept] or [reject] should be called after every [recompile] call.
void accept() { void accept() {
if (_compileRequestNeedsConfirmation) { if (_compileRequestNeedsConfirmation) {
_server.stdin.writeln('accept'); _server.stdin.writeln('accept');
...@@ -711,9 +769,7 @@ class ResidentCompiler { ...@@ -711,9 +769,7 @@ class ResidentCompiler {
_compileRequestNeedsConfirmation = false; _compileRequestNeedsConfirmation = false;
} }
/// Should be invoked when results of compilation are rejected by the client. @override
///
/// Either [accept] or [reject] should be called after every [recompile] call.
Future<CompilerOutput> reject() { Future<CompilerOutput> reject() {
if (!_controller.hasListener) { if (!_controller.hasListener) {
_controller.stream.listen(_handleCompilationRequest); _controller.stream.listen(_handleCompilationRequest);
...@@ -735,9 +791,7 @@ class ResidentCompiler { ...@@ -735,9 +791,7 @@ class ResidentCompiler {
return _stdoutHandler.compilerOutput.future; return _stdoutHandler.compilerOutput.future;
} }
/// Should be invoked when frontend server compiler should forget what was @override
/// accepted previously so that next call to [recompile] produces complete
/// kernel file.
void reset() { void reset() {
_server?.stdin?.writeln('reset'); _server?.stdin?.writeln('reset');
printTrace('<- reset'); printTrace('<- reset');
...@@ -765,21 +819,22 @@ class ResidentCompiler { ...@@ -765,21 +819,22 @@ class ResidentCompiler {
} }
} }
if (_fileSystemRoots != null) { if (fileSystemRoots != null) {
for (String root in _fileSystemRoots) { for (String root in fileSystemRoots) {
if (filename.startsWith(root)) { if (filename.startsWith(root)) {
return Uri( return Uri(
scheme: _fileSystemScheme, path: filename.substring(root.length)) scheme: fileSystemScheme, path: filename.substring(root.length))
.toString(); .toString();
} }
} }
} }
if (platform.isWindows && _fileSystemRoots != null && _fileSystemRoots.length > 1) { if (platform.isWindows && fileSystemRoots != null && fileSystemRoots.length > 1) {
return Uri.file(filename, windows: platform.isWindows).toString(); return Uri.file(filename, windows: platform.isWindows).toString();
} }
return null; return null;
} }
@override
Future<dynamic> shutdown() async { Future<dynamic> shutdown() async {
// Server was never successfully created. // Server was never successfully created.
if (_server == null) { if (_server == null) {
......
...@@ -39,6 +39,9 @@ class FeatureFlags { ...@@ -39,6 +39,9 @@ class FeatureFlags {
/// Whether the Android embedding V2 is enabled. /// Whether the Android embedding V2 is enabled.
bool get isAndroidEmbeddingV2Enabled => isEnabled(flutterAndroidEmbeddingV2Feature); bool get isAndroidEmbeddingV2Enabled => isEnabled(flutterAndroidEmbeddingV2Feature);
/// Whether the web incremental compiler is enabled.
bool get isWebIncrementalCompilerEnabled => isEnabled(flutterWebIncrementalCompiler);
/// Whether a particular feature is enabled for the current channel. /// Whether a particular feature is enabled for the current channel.
/// ///
/// Prefer using one of the specific getters above instead of this API. /// Prefer using one of the specific getters above instead of this API.
...@@ -72,6 +75,7 @@ const List<Feature> allFeatures = <Feature>[ ...@@ -72,6 +75,7 @@ const List<Feature> allFeatures = <Feature>[
flutterWindowsDesktopFeature, flutterWindowsDesktopFeature,
flutterBuildPluginAsAarFeature, flutterBuildPluginAsAarFeature,
flutterAndroidEmbeddingV2Feature, flutterAndroidEmbeddingV2Feature,
flutterWebIncrementalCompiler,
]; ];
/// The [Feature] for flutter web. /// The [Feature] for flutter web.
...@@ -143,6 +147,16 @@ const Feature flutterAndroidEmbeddingV2Feature = Feature( ...@@ -143,6 +147,16 @@ const Feature flutterAndroidEmbeddingV2Feature = Feature(
), ),
); );
/// The [Feature] for using the incremental compiler instead of build runner.
const Feature flutterWebIncrementalCompiler = Feature(
name: 'Enable the incremental compiler for web builds',
configSetting: 'enable-web-incremental-compiler',
master: FeatureChannelSetting(
available: true,
enabledByDefault: false,
),
);
/// A [Feature] is a process for conditionally enabling tool features. /// A [Feature] is a process for conditionally enabling tool features.
/// ///
/// All settings are optional, and if not provided will generally default to /// All settings are optional, and if not provided will generally default to
......
...@@ -22,6 +22,7 @@ import 'compile.dart'; ...@@ -22,6 +22,7 @@ import 'compile.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'devfs.dart'; import 'devfs.dart';
import 'device.dart'; import 'device.dart';
import 'features.dart';
import 'globals.dart'; import 'globals.dart';
import 'project.dart'; import 'project.dart';
import 'run_cold.dart'; import 'run_cold.dart';
...@@ -65,7 +66,19 @@ class FlutterDevice { ...@@ -65,7 +66,19 @@ class FlutterDevice {
ResidentCompiler generator, ResidentCompiler generator,
}) async { }) async {
ResidentCompiler generator; ResidentCompiler generator;
if (flutterProject.hasBuilders) { if (featureFlags.isWebIncrementalCompilerEnabled &&
await device.targetPlatform == TargetPlatform.web_javascript) {
generator = ResidentCompiler(
artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: buildMode),
buildMode: buildMode,
trackWidgetCreation: trackWidgetCreation,
fileSystemRoots: fileSystemRoots,
fileSystemScheme: fileSystemScheme,
targetModel: TargetModel.dartdevc,
experimentalFlags: experimentalFlags,
platformDill: artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildMode),
);
} else if (flutterProject.hasBuilders) {
generator = await CodeGeneratingResidentCompiler.create( generator = await CodeGeneratingResidentCompiler.create(
buildMode: buildMode, buildMode: buildMode,
flutterProject: flutterProject, flutterProject: flutterProject,
......
...@@ -37,6 +37,10 @@ void main() { ...@@ -37,6 +37,10 @@ void main() {
expect(TargetModel('flutter_runner'), TargetModel.flutterRunner); expect(TargetModel('flutter_runner'), TargetModel.flutterRunner);
expect(TargetModel.flutterRunner.toString(), 'flutter_runner'); expect(TargetModel.flutterRunner.toString(), 'flutter_runner');
expect(TargetModel('dartdevc'), TargetModel.dartdevc);
expect(TargetModel.dartdevc.toString(), 'dartdevc');
expect(() => TargetModel('foobar'), throwsA(isInstanceOf<AssertionError>())); expect(() => TargetModel('foobar'), throwsA(isInstanceOf<AssertionError>()));
}); });
} }
...@@ -5,14 +5,18 @@ ...@@ -5,14 +5,18 @@
import 'dart:async'; import 'dart:async';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/devfs.dart'; import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/globals.dart'; import 'package:flutter_tools/src/globals.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/resident_runner.dart'; import 'package:flutter_tools/src/resident_runner.dart';
import 'package:flutter_tools/src/run_cold.dart'; import 'package:flutter_tools/src/run_cold.dart';
...@@ -599,6 +603,29 @@ void main() { ...@@ -599,6 +603,29 @@ void main() {
expect(await fs.file('foo').readAsString(), testUri.toString()); expect(await fs.file('foo').readAsString(), testUri.toString());
})); }));
test('FlutterDevice uses dartdevc configuration when targeting web', () => testbed.run(() async {
final MockDevice mockDevice = MockDevice();
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
return TargetPlatform.web_javascript;
});
final DefaultResidentCompiler residentCompiler = (await FlutterDevice.create(
mockDevice,
buildMode: BuildMode.debug,
flutterProject: FlutterProject.current(),
target: null,
trackWidgetCreation: true,
)).generator;
expect(residentCompiler.targetModel, TargetModel.dartdevc);
expect(residentCompiler.sdkRoot,
artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: BuildMode.debug) + '/');
expect(residentCompiler.platformDill,
artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: BuildMode.debug));
}, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isWebIncrementalCompilerEnabled: true),
}));
} }
class MockFlutterDevice extends Mock implements FlutterDevice {} class MockFlutterDevice extends Mock implements FlutterDevice {}
...@@ -608,6 +635,7 @@ class MockDevFS extends Mock implements DevFS {} ...@@ -608,6 +635,7 @@ class MockDevFS extends Mock implements DevFS {}
class MockIsolate extends Mock implements Isolate {} class MockIsolate extends Mock implements Isolate {}
class MockDevice extends Mock implements Device {} class MockDevice extends Mock implements Device {}
class MockUsage extends Mock implements Usage {} class MockUsage extends Mock implements Usage {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockServiceEvent extends Mock implements ServiceEvent {} class MockServiceEvent extends Mock implements ServiceEvent {}
class TestFlutterDevice extends FlutterDevice { class TestFlutterDevice extends FlutterDevice {
TestFlutterDevice(Device device, this.views) TestFlutterDevice(Device device, this.views)
......
...@@ -700,6 +700,7 @@ class TestFeatureFlags implements FeatureFlags { ...@@ -700,6 +700,7 @@ class TestFeatureFlags implements FeatureFlags {
this.isWebEnabled = false, this.isWebEnabled = false,
this.isWindowsEnabled = false, this.isWindowsEnabled = false,
this.isAndroidEmbeddingV2Enabled = false, this.isAndroidEmbeddingV2Enabled = false,
this.isWebIncrementalCompilerEnabled = false,
}); });
@override @override
...@@ -717,6 +718,9 @@ class TestFeatureFlags implements FeatureFlags { ...@@ -717,6 +718,9 @@ class TestFeatureFlags implements FeatureFlags {
@override @override
final bool isAndroidEmbeddingV2Enabled; final bool isAndroidEmbeddingV2Enabled;
@override
final bool isWebIncrementalCompilerEnabled;
@override @override
bool isEnabled(Feature feature) { bool isEnabled(Feature feature) {
switch (feature) { switch (feature) {
...@@ -730,6 +734,8 @@ class TestFeatureFlags implements FeatureFlags { ...@@ -730,6 +734,8 @@ class TestFeatureFlags implements FeatureFlags {
return isWindowsEnabled; return isWindowsEnabled;
case flutterAndroidEmbeddingV2Feature: case flutterAndroidEmbeddingV2Feature:
return isAndroidEmbeddingV2Enabled; return isAndroidEmbeddingV2Enabled;
case flutterWebIncrementalCompiler:
return isWebIncrementalCompilerEnabled;
} }
return false; return false;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment