forked from firka/flutter
Allow skipping webOnlyInitializePlatform in Flutter for Web (#40301)
This commit is contained in:
@@ -101,7 +101,11 @@ final List<core.BuilderApplication> builders = <core.BuilderApplication>[
|
||||
<BuilderFactory>[
|
||||
(BuilderOptions options) {
|
||||
final bool hasPlugins = options.config['hasPlugins'] == true;
|
||||
return FlutterWebShellBuilder(hasPlugins: hasPlugins);
|
||||
final bool initializePlatform = options.config['initializePlatform'] == true;
|
||||
return FlutterWebShellBuilder(
|
||||
hasPlugins: hasPlugins,
|
||||
initializePlatform: initializePlatform,
|
||||
);
|
||||
}
|
||||
],
|
||||
core.toRoot(),
|
||||
@@ -360,10 +364,13 @@ void setStackTraceMapper(StackTraceMapper mapper) {
|
||||
|
||||
/// A shell builder which generates the web specific entrypoint.
|
||||
class FlutterWebShellBuilder implements Builder {
|
||||
const FlutterWebShellBuilder({this.hasPlugins = false});
|
||||
const FlutterWebShellBuilder({this.hasPlugins = false, this.initializePlatform = true});
|
||||
|
||||
final bool hasPlugins;
|
||||
|
||||
/// Whether to call webOnlyInitializePlatform.
|
||||
final bool initializePlatform;
|
||||
|
||||
@override
|
||||
Future<void> build(BuildStep buildStep) async {
|
||||
final AssetId dartEntrypointId = buildStep.inputId;
|
||||
@@ -383,7 +390,9 @@ import "${path.url.basename(buildStep.inputId.path)}" as entrypoint;
|
||||
|
||||
Future<void> main() async {
|
||||
registerPlugins(webPluginRegistry);
|
||||
await ui.webOnlyInitializePlatform();
|
||||
if ($initializePlatform) {
|
||||
await ui.webOnlyInitializePlatform();
|
||||
}
|
||||
entrypoint.main();
|
||||
}
|
||||
''');
|
||||
@@ -394,7 +403,9 @@ import 'dart:ui' as ui;
|
||||
import "${path.url.basename(buildStep.inputId.path)}" as entrypoint;
|
||||
|
||||
Future<void> main() async {
|
||||
await ui.webOnlyInitializePlatform();
|
||||
if ($initializePlatform) {
|
||||
await ui.webOnlyInitializePlatform();
|
||||
}
|
||||
entrypoint.main();
|
||||
}
|
||||
''');
|
||||
|
||||
@@ -168,6 +168,7 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
target: target,
|
||||
flutterProject: flutterProject,
|
||||
buildInfo: debuggingOptions.buildInfo,
|
||||
initializePlatform: debuggingOptions.initializePlatform,
|
||||
hostname: debuggingOptions.hostname,
|
||||
port: debuggingOptions.port,
|
||||
skipDwds: device is WebServerDevice,
|
||||
|
||||
@@ -16,6 +16,9 @@ import 'package:path/path.dart' as path;
|
||||
import '../base/file_system.dart';
|
||||
import '../build_info.dart';
|
||||
import '../convert.dart';
|
||||
import '../platform_plugins.dart';
|
||||
import '../plugins.dart';
|
||||
import '../project.dart';
|
||||
import '../web/compile.dart';
|
||||
import 'web_fs.dart';
|
||||
|
||||
@@ -28,18 +31,23 @@ class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
|
||||
Directory projectDirectory,
|
||||
String testOutputDir,
|
||||
BuildMode mode,
|
||||
String projectName
|
||||
String projectName,
|
||||
bool initializePlatform,
|
||||
}) async {
|
||||
// Create the .dart_tool directory if it doesn't exist.
|
||||
projectDirectory
|
||||
.childDirectory('.dart_tool')
|
||||
.createSync();
|
||||
final FlutterProject flutterProject = FlutterProject.fromDirectory(projectDirectory);
|
||||
final bool hasWebPlugins = findPlugins(flutterProject)
|
||||
.any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
|
||||
final BuildDaemonClient client = await buildDaemonCreator.startBuildDaemon(
|
||||
projectDirectory.path,
|
||||
release: mode == BuildMode.release,
|
||||
profile: mode == BuildMode.profile,
|
||||
hasPlugins: false,
|
||||
hasPlugins: hasWebPlugins,
|
||||
includeTests: true,
|
||||
initializePlatform: initializePlatform,
|
||||
);
|
||||
client.startBuild();
|
||||
bool success = true;
|
||||
|
||||
@@ -75,6 +75,7 @@ typedef WebFsFactory = Future<WebFs> Function({
|
||||
@required FlutterProject flutterProject,
|
||||
@required BuildInfo buildInfo,
|
||||
@required bool skipDwds,
|
||||
@required bool initializePlatform,
|
||||
@required String hostname,
|
||||
@required String port,
|
||||
});
|
||||
@@ -142,6 +143,7 @@ class WebFs {
|
||||
@required FlutterProject flutterProject,
|
||||
@required BuildInfo buildInfo,
|
||||
@required bool skipDwds,
|
||||
@required bool initializePlatform,
|
||||
@required String hostname,
|
||||
@required String port,
|
||||
}) async {
|
||||
@@ -149,11 +151,16 @@ class WebFs {
|
||||
if (!flutterProject.dartTool.existsSync()) {
|
||||
flutterProject.dartTool.createSync(recursive: true);
|
||||
}
|
||||
|
||||
final bool hasWebPlugins = findPlugins(flutterProject).any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
|
||||
final bool hasWebPlugins = findPlugins(flutterProject)
|
||||
.any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
|
||||
// Start the build daemon and run an initial build.
|
||||
final BuildDaemonClient client = await buildDaemonCreator
|
||||
.startBuildDaemon(fs.currentDirectory.path, release: buildInfo.isRelease, profile: buildInfo.isProfile, hasPlugins: hasWebPlugins);
|
||||
.startBuildDaemon(fs.currentDirectory.path,
|
||||
release: buildInfo.isRelease,
|
||||
profile: buildInfo.isProfile,
|
||||
hasPlugins: hasWebPlugins,
|
||||
initializePlatform: initializePlatform,
|
||||
);
|
||||
client.startBuild();
|
||||
// Only provide relevant build results
|
||||
final Stream<BuildResult> filteredBuildResults = client.buildResults
|
||||
@@ -340,11 +347,14 @@ class BuildDaemonCreator {
|
||||
static const String _ignoredLine3 = 'have your dependencies specified fully in your pubspec.yaml';
|
||||
|
||||
/// Start a build daemon and register the web targets.
|
||||
///
|
||||
/// [initializePlatform] controls whether we should invoke [webOnlyInitializePlatform].
|
||||
Future<BuildDaemonClient> startBuildDaemon(String workingDirectory, {
|
||||
bool release = false,
|
||||
bool profile = false,
|
||||
bool hasPlugins = false,
|
||||
bool includeTests = false,
|
||||
bool initializePlatform = true,
|
||||
}) async {
|
||||
try {
|
||||
final BuildDaemonClient client = await _connectClient(
|
||||
@@ -352,6 +362,7 @@ class BuildDaemonCreator {
|
||||
release: release,
|
||||
profile: profile,
|
||||
hasPlugins: hasPlugins,
|
||||
initializePlatform: initializePlatform,
|
||||
);
|
||||
_registerBuildTargets(client, includeTests);
|
||||
return client;
|
||||
@@ -384,7 +395,7 @@ class BuildDaemonCreator {
|
||||
|
||||
Future<BuildDaemonClient> _connectClient(
|
||||
String workingDirectory,
|
||||
{ bool release, bool profile, bool hasPlugins }
|
||||
{ bool release, bool profile, bool hasPlugins, bool initializePlatform }
|
||||
) {
|
||||
final String flutterToolsPackages = fs.path.join(Cache.flutterRoot, 'packages', 'flutter_tools', '.packages');
|
||||
final String buildScript = fs.path.join(Cache.flutterRoot, 'packages', 'flutter_tools', 'lib', 'src', 'build_runner', 'build_script.dart');
|
||||
@@ -406,6 +417,7 @@ class BuildDaemonCreator {
|
||||
'--define', 'flutter_tools:entrypoint=profile=$profile',
|
||||
'--define', 'flutter_tools:shell=flutterWebSdk=$flutterWebSdk',
|
||||
'--define', 'flutter_tools:shell=hasPlugins=$hasPlugins',
|
||||
'--define', 'flutter_tools:shell=initializePlatform=$initializePlatform'
|
||||
],
|
||||
logHandler: (ServerLog serverLog) {
|
||||
switch (serverLog.level) {
|
||||
|
||||
@@ -18,6 +18,12 @@ class BuildWebCommand extends BuildSubCommand {
|
||||
usesTargetOption();
|
||||
usesPubOption();
|
||||
addBuildModeFlags();
|
||||
argParser.addFlag('web-initialize-platform',
|
||||
defaultsTo: true,
|
||||
negatable: true,
|
||||
hide: true,
|
||||
help: 'Whether to automatically invoke webOnlyInitializePlatform.',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -44,7 +50,7 @@ class BuildWebCommand extends BuildSubCommand {
|
||||
final FlutterProject flutterProject = FlutterProject.current();
|
||||
final String target = argResults['target'];
|
||||
final BuildInfo buildInfo = getBuildInfo();
|
||||
await buildWeb(flutterProject, target, buildInfo);
|
||||
await buildWeb(flutterProject, target, buildInfo, argResults['web-initialize-platform']);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,12 @@ class RunCommand extends RunCommandBase {
|
||||
hide: !verboseHelp,
|
||||
help: 'No longer require an authentication code to connect to the VM '
|
||||
'service (not recommended).')
|
||||
..addFlag('web-initialize-platform',
|
||||
negatable: true,
|
||||
defaultsTo: true,
|
||||
hide: true,
|
||||
help: 'Whether to automatically invoke webOnlyInitializePlatform.'
|
||||
)
|
||||
..addOption(FlutterOptions.kExtraFrontEndOptions, hide: true)
|
||||
..addOption(FlutterOptions.kExtraGenSnapshotOptions, hide: true)
|
||||
..addMultiOption(FlutterOptions.kEnableExperiment,
|
||||
@@ -274,7 +280,10 @@ class RunCommand extends RunCommandBase {
|
||||
DebuggingOptions _createDebuggingOptions() {
|
||||
final BuildInfo buildInfo = getBuildInfo();
|
||||
if (buildInfo.isRelease) {
|
||||
return DebuggingOptions.disabled(buildInfo);
|
||||
return DebuggingOptions.disabled(
|
||||
buildInfo,
|
||||
initializePlatform: argResults['web-initialize-platform'],
|
||||
);
|
||||
} else {
|
||||
return DebuggingOptions.enabled(
|
||||
buildInfo,
|
||||
@@ -289,6 +298,7 @@ class RunCommand extends RunCommandBase {
|
||||
dumpSkpOnShaderCompilation: argResults['dump-skp-on-shader-compilation'],
|
||||
observatoryPort: observatoryPort,
|
||||
verboseSystemLogs: argResults['verbose-system-logs'],
|
||||
initializePlatform: argResults['web-initialize-platform'],
|
||||
hostname: featureFlags.isWebEnabled ? argResults['web-hostname'] : '',
|
||||
port: featureFlags.isWebEnabled ? argResults['web-port'] : '',
|
||||
);
|
||||
|
||||
@@ -484,11 +484,12 @@ class DebuggingOptions {
|
||||
this.useTestFonts = false,
|
||||
this.verboseSystemLogs = false,
|
||||
this.observatoryPort,
|
||||
this.initializePlatform = true,
|
||||
this.hostname,
|
||||
this.port,
|
||||
}) : debuggingEnabled = true;
|
||||
|
||||
DebuggingOptions.disabled(this.buildInfo)
|
||||
DebuggingOptions.disabled(this.buildInfo, { this.initializePlatform = true })
|
||||
: debuggingEnabled = false,
|
||||
useTestFonts = false,
|
||||
startPaused = false,
|
||||
@@ -517,6 +518,8 @@ class DebuggingOptions {
|
||||
final bool dumpSkpOnShaderCompilation;
|
||||
final bool useTestFonts;
|
||||
final bool verboseSystemLogs;
|
||||
/// Whether to invoke webOnlyInitializePlatform in Flutter for web.
|
||||
final bool initializePlatform;
|
||||
final int observatoryPort;
|
||||
final String port;
|
||||
final String hostname;
|
||||
|
||||
@@ -70,6 +70,7 @@ Future<int> runTests(
|
||||
projectDirectory: flutterProject.directory,
|
||||
testOutputDir: tempBuildDir,
|
||||
projectName: flutterProject.manifest.appName,
|
||||
initializePlatform: true,
|
||||
);
|
||||
if (!result) {
|
||||
throwToolExit('Failed to compile tests');
|
||||
|
||||
@@ -18,7 +18,7 @@ import '../reporting/reporting.dart';
|
||||
/// The [WebCompilationProxy] instance.
|
||||
WebCompilationProxy get webCompilationProxy => context.get<WebCompilationProxy>();
|
||||
|
||||
Future<void> buildWeb(FlutterProject flutterProject, String target, BuildInfo buildInfo) async {
|
||||
Future<void> buildWeb(FlutterProject flutterProject, String target, BuildInfo buildInfo, bool initializePlatform) async {
|
||||
if (!flutterProject.web.existsSync()) {
|
||||
throwToolExit('Missing index.html.');
|
||||
}
|
||||
@@ -32,6 +32,7 @@ Future<void> buildWeb(FlutterProject flutterProject, String target, BuildInfo bu
|
||||
projectDirectory: FlutterProject.current().directory,
|
||||
mode: buildInfo.mode,
|
||||
projectName: flutterProject.manifest.appName,
|
||||
initializePlatform: initializePlatform,
|
||||
);
|
||||
if (result) {
|
||||
// Places assets adjacent to the web stuff.
|
||||
@@ -84,6 +85,7 @@ class WebCompilationProxy {
|
||||
@required String projectName,
|
||||
String testOutputDir,
|
||||
BuildMode mode,
|
||||
bool initializePlatform,
|
||||
}) async {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2019 The Chromium 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:build/build.dart';
|
||||
import 'package:flutter_tools/src/build_runner/build_script.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
|
||||
void main() {
|
||||
MockBuildStep mockBuildStep;
|
||||
AssetId inputId;
|
||||
|
||||
setUp(() {
|
||||
mockBuildStep = MockBuildStep();
|
||||
inputId = AssetId('hello_world', 'lib/main.dart');
|
||||
when(mockBuildStep.inputId).thenReturn(inputId);
|
||||
when(mockBuildStep.readAsString(any)).thenAnswer((Invocation invocation) async {
|
||||
return 'void main() { }';
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('FlutterWebShellBuilder correctly configures platform', () async {
|
||||
const FlutterWebShellBuilder builder = FlutterWebShellBuilder(
|
||||
hasPlugins: false,
|
||||
initializePlatform: true,
|
||||
);
|
||||
|
||||
await builder.build(mockBuildStep);
|
||||
|
||||
verify(mockBuildStep.writeAsString(any, argThat(contains('if (true) '
|
||||
'{\n await ui.webOnlyInitializePlatform')))).called(1);
|
||||
});
|
||||
|
||||
test('FlutterWebShellBuilder correctly configures does not platform', () async {
|
||||
const FlutterWebShellBuilder builder = FlutterWebShellBuilder(
|
||||
hasPlugins: false,
|
||||
initializePlatform: false,
|
||||
);
|
||||
|
||||
await builder.build(mockBuildStep);
|
||||
|
||||
verify(mockBuildStep.writeAsString(any, argThat(contains('if (false) '
|
||||
'{\n await ui.webOnlyInitializePlatform')))).called(1);
|
||||
});
|
||||
|
||||
test('FlutterWebShellBuilder correctly configures plugins', () async {
|
||||
const FlutterWebShellBuilder builder = FlutterWebShellBuilder(
|
||||
hasPlugins: true,
|
||||
initializePlatform: true,
|
||||
);
|
||||
|
||||
await builder.build(mockBuildStep);
|
||||
|
||||
verify(mockBuildStep.writeAsString(any,
|
||||
argThat(contains('registerPlugins(webPluginRegistry)')))).called(1);
|
||||
});
|
||||
|
||||
test('FlutterWebShellBuilder correctly does not configure plugins', () async {
|
||||
const FlutterWebShellBuilder builder = FlutterWebShellBuilder(
|
||||
hasPlugins: false,
|
||||
initializePlatform: true,
|
||||
);
|
||||
|
||||
await builder.build(mockBuildStep);
|
||||
|
||||
verify(mockBuildStep.writeAsString(any,
|
||||
argThat(isNot(contains('registerPlugins(webPluginRegistry)'))))).called(1);
|
||||
});
|
||||
}
|
||||
|
||||
class MockBuildStep extends Mock implements BuildStep {}
|
||||
@@ -43,7 +43,8 @@ void main() {
|
||||
when(mockWebCompilationProxy.initialize(
|
||||
projectName: anyNamed('projectName'),
|
||||
projectDirectory: anyNamed('projectDirectory'),
|
||||
mode: anyNamed('mode')
|
||||
mode: anyNamed('mode'),
|
||||
initializePlatform: anyNamed('initializePlatform')
|
||||
)).thenAnswer((Invocation invocation) {
|
||||
final String path = fs.path.join('.dart_tool', 'build', 'flutter_web', 'foo', 'lib', 'main_web_entrypoint.dart.js');
|
||||
fs.file(path).createSync(recursive: true);
|
||||
@@ -65,6 +66,7 @@ void main() {
|
||||
FlutterProject.current(),
|
||||
fs.path.join('lib', 'main.dart'),
|
||||
BuildInfo.debug,
|
||||
false,
|
||||
), throwsA(isInstanceOf<ToolExit>()));
|
||||
}));
|
||||
|
||||
@@ -86,6 +88,7 @@ void main() {
|
||||
FlutterProject.current(),
|
||||
fs.path.join('lib', 'main.dart'),
|
||||
BuildInfo.debug,
|
||||
false,
|
||||
);
|
||||
}));
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ void main() {
|
||||
@required FlutterProject flutterProject,
|
||||
@required BuildInfo buildInfo,
|
||||
@required bool skipDwds,
|
||||
@required bool initializePlatform,
|
||||
@required String hostname,
|
||||
@required String port,
|
||||
}) async {
|
||||
@@ -102,7 +103,6 @@ void main() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MockWebDevice extends Mock implements Device {}
|
||||
class MockBuildDaemonCreator extends Mock implements BuildDaemonCreator {}
|
||||
class MockFlutterWebFs extends Mock implements WebFs {}
|
||||
|
||||
@@ -52,6 +52,7 @@ void main() {
|
||||
@required FlutterProject flutterProject,
|
||||
@required BuildInfo buildInfo,
|
||||
@required bool skipDwds,
|
||||
@required bool initializePlatform,
|
||||
@required String hostname,
|
||||
@required String port,
|
||||
}) async {
|
||||
|
||||
@@ -26,20 +26,23 @@ void main() {
|
||||
MockHttpMultiServer mockHttpMultiServer;
|
||||
MockBuildDaemonClient mockBuildDaemonClient;
|
||||
MockOperatingSystemUtils mockOperatingSystemUtils;
|
||||
bool lastInitializePlatform;
|
||||
dynamic lastAddress;
|
||||
int lastPort;
|
||||
|
||||
setUp(() {
|
||||
lastAddress = null;
|
||||
lastPort = null;
|
||||
lastInitializePlatform = null;
|
||||
mockBuildDaemonCreator = MockBuildDaemonCreator();
|
||||
mockChromeLauncher = MockChromeLauncher();
|
||||
mockHttpMultiServer = MockHttpMultiServer();
|
||||
mockBuildDaemonClient = MockBuildDaemonClient();
|
||||
mockOperatingSystemUtils = MockOperatingSystemUtils();
|
||||
mockDwds = MockDwds();
|
||||
when(mockBuildDaemonCreator.startBuildDaemon(any, release: anyNamed('release')))
|
||||
.thenAnswer((Invocation _) async {
|
||||
when(mockBuildDaemonCreator.startBuildDaemon(any, release: anyNamed('release'), initializePlatform: anyNamed('initializePlatform')))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
lastInitializePlatform = invocation.namedArguments[#initializePlatform];
|
||||
return mockBuildDaemonClient;
|
||||
});
|
||||
when(mockOperatingSystemUtils.findFreePort()).thenAnswer((Invocation _) async {
|
||||
@@ -89,6 +92,7 @@ void main() {
|
||||
target: fs.path.join('lib', 'main.dart'),
|
||||
buildInfo: BuildInfo.debug,
|
||||
flutterProject: flutterProject,
|
||||
initializePlatform: true,
|
||||
hostname: null,
|
||||
port: null,
|
||||
);
|
||||
@@ -98,6 +102,27 @@ void main() {
|
||||
|
||||
// .dart_tool directory is created.
|
||||
expect(flutterProject.dartTool.existsSync(), true);
|
||||
expect(lastInitializePlatform, true);
|
||||
}));
|
||||
|
||||
test('Can create webFs from mocked interfaces with initializePlatform', () => testbed.run(() async {
|
||||
final FlutterProject flutterProject = FlutterProject.current();
|
||||
await WebFs.start(
|
||||
skipDwds: false,
|
||||
target: fs.path.join('lib', 'main.dart'),
|
||||
buildInfo: BuildInfo.debug,
|
||||
flutterProject: flutterProject,
|
||||
initializePlatform: false,
|
||||
hostname: null,
|
||||
port: null,
|
||||
);
|
||||
|
||||
// The build daemon is told to build once.
|
||||
verify(mockBuildDaemonClient.startBuild()).called(1);
|
||||
|
||||
// .dart_tool directory is created.
|
||||
expect(flutterProject.dartTool.existsSync(), true);
|
||||
expect(lastInitializePlatform, false);
|
||||
}));
|
||||
|
||||
test('Uses provided port number and hostname.', () => testbed.run(() async {
|
||||
@@ -107,6 +132,7 @@ void main() {
|
||||
target: fs.path.join('lib', 'main.dart'),
|
||||
buildInfo: BuildInfo.debug,
|
||||
flutterProject: flutterProject,
|
||||
initializePlatform: false,
|
||||
hostname: 'foo',
|
||||
port: '1234',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user