mirror of
https://github.com/flutter/flutter
synced 2024-08-24 18:36:03 +00:00
Support flutter run --wasm
and flutter drive --wasm
. (#146231)
This adds support for adding the `--wasm` flag to `flutter run` and `flutter drive` * Emits errors if you attempt to use the skwasm renderer without the `--wasm` flag * Emits errors if you try to use `--wasm` when not using a web device * Uses the skwasm renderer by default if you pass `--wasm` and no `--web-renderer`
This commit is contained in:
parent
e2c812155c
commit
9973673752
|
@ -32,6 +32,7 @@ Future<void> webLongRunningTestsRunner(String flutterRoot) async {
|
|||
target: path.join('test_driver', 'failure.dart'),
|
||||
buildMode: buildMode,
|
||||
renderer: 'canvaskit',
|
||||
wasm: false,
|
||||
// This test intentionally fails and prints stack traces in the browser
|
||||
// logs. To avoid confusion, silence browser output.
|
||||
silenceBrowserOutput: true,
|
||||
|
@ -42,6 +43,17 @@ Future<void> webLongRunningTestsRunner(String flutterRoot) async {
|
|||
driver: path.join('test_driver', 'integration_test.dart'),
|
||||
buildMode: buildMode,
|
||||
renderer: 'canvaskit',
|
||||
wasm: false,
|
||||
expectWriteResponseFile: true,
|
||||
expectResponseFileContent: 'null',
|
||||
),
|
||||
() => _runFlutterDriverWebTest(
|
||||
testAppDirectory: path.join('packages', 'integration_test', 'example'),
|
||||
target: path.join('integration_test', 'example_test.dart'),
|
||||
driver: path.join('test_driver', 'integration_test.dart'),
|
||||
buildMode: buildMode,
|
||||
renderer: 'skwasm',
|
||||
wasm: true,
|
||||
expectWriteResponseFile: true,
|
||||
expectResponseFileContent: 'null',
|
||||
),
|
||||
|
@ -51,6 +63,7 @@ Future<void> webLongRunningTestsRunner(String flutterRoot) async {
|
|||
driver: path.join('test_driver', 'extended_integration_test.dart'),
|
||||
buildMode: buildMode,
|
||||
renderer: 'canvaskit',
|
||||
wasm: false,
|
||||
expectWriteResponseFile: true,
|
||||
expectResponseFileContent: '''
|
||||
{
|
||||
|
@ -97,6 +110,7 @@ Future<void> webLongRunningTestsRunner(String flutterRoot) async {
|
|||
() => _runWebE2eTest('capabilities_integration_canvaskit', buildMode: 'debug', renderer: 'auto'),
|
||||
() => _runWebE2eTest('capabilities_integration_canvaskit', buildMode: 'profile', renderer: 'canvaskit'),
|
||||
() => _runWebE2eTest('capabilities_integration_html', buildMode: 'release', renderer: 'html'),
|
||||
() => _runWebE2eTest('capabilities_integration_skwasm', buildMode: 'release', renderer: 'skwasm', wasm: true),
|
||||
|
||||
// This test doesn't do anything interesting w.r.t. rendering, so we don't run the full build mode x renderer matrix.
|
||||
// CacheWidth and CacheHeight are only currently supported in CanvasKit mode, so we don't run the test in HTML mode.
|
||||
|
@ -110,6 +124,7 @@ Future<void> webLongRunningTestsRunner(String flutterRoot) async {
|
|||
target: 'test_driver/smoke_web_engine.dart',
|
||||
buildMode: 'profile',
|
||||
renderer: 'auto',
|
||||
wasm: false,
|
||||
),
|
||||
() => _runGalleryE2eWebTest('debug'),
|
||||
() => _runGalleryE2eWebTest('debug', canvasKit: true),
|
||||
|
@ -192,12 +207,14 @@ Future<void> _runWebE2eTest(
|
|||
String name, {
|
||||
required String buildMode,
|
||||
required String renderer,
|
||||
bool wasm = false,
|
||||
}) async {
|
||||
await _runFlutterDriverWebTest(
|
||||
target: path.join('test_driver', '$name.dart'),
|
||||
buildMode: buildMode,
|
||||
renderer: renderer,
|
||||
testAppDirectory: path.join(flutterRoot, 'dev', 'integration_tests', 'web_e2e_tests'),
|
||||
wasm: wasm,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -206,6 +223,7 @@ Future<void> _runFlutterDriverWebTest({
|
|||
required String buildMode,
|
||||
required String renderer,
|
||||
required String testAppDirectory,
|
||||
required bool wasm,
|
||||
String? driver,
|
||||
bool expectFailure = false,
|
||||
bool silenceBrowserOutput = false,
|
||||
|
@ -235,6 +253,7 @@ Future<void> _runFlutterDriverWebTest({
|
|||
'web-server',
|
||||
'--$buildMode',
|
||||
'--web-renderer=$renderer',
|
||||
if (wasm) '--wasm',
|
||||
],
|
||||
expectNonZeroExit: expectFailure,
|
||||
workingDirectory: testAppDirectory,
|
||||
|
|
12
dev/integration_tests/non_nullable/web/flutter_bootstrap.js
Normal file
12
dev/integration_tests/non_nullable/web/flutter_bootstrap.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
// 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.
|
||||
|
||||
{{flutter_js}}
|
||||
{{flutter_build_config}}
|
||||
_flutter.loader.load({
|
||||
config: {
|
||||
// Use the local CanvasKit bundle instead of the CDN to reduce test flakiness.
|
||||
canvasKitBaseUrl: "/canvaskit/",
|
||||
},
|
||||
});
|
|
@ -22,16 +22,6 @@ found in the LICENSE file. -->
|
|||
<link rel="manifest" href="manifest.json">
|
||||
</head>
|
||||
<body>
|
||||
<!-- This script installs service_worker.js to provide PWA functionality to
|
||||
application. For more information, see:
|
||||
https://developers.google.com/web/fundamentals/primers/service-workers -->
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function () {
|
||||
navigator.serviceWorker.register('flutter_service_worker.js');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script src="main.dart.js" type="application/javascript"></script>
|
||||
<script src="flutter_bootstrap.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// 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.
|
||||
|
||||
{{flutter_js}}
|
||||
{{flutter_build_config}}
|
||||
_flutter.loader.load({
|
||||
config: {
|
||||
// Use the local CanvasKit bundle instead of the CDN to reduce test flakiness.
|
||||
canvasKitBaseUrl: "/canvaskit/",
|
||||
},
|
||||
});
|
|
@ -7,6 +7,6 @@ found in the LICENSE file. -->
|
|||
<title>Hello, World</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="main.dart.js"></script>
|
||||
<script src="flutter_bootstrap.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -12,5 +12,7 @@ void main() {
|
|||
testWidgets('isCanvasKit returns true in CanvasKit mode', (WidgetTester tester) async {
|
||||
await tester.pumpAndSettle();
|
||||
expect(isCanvasKit, true);
|
||||
expect(isSkwasm, false);
|
||||
expect(isSkiaWeb, true);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@ import 'package:integration_test/integration_test.dart';
|
|||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
testWidgets('isCanvasKit returns false in HTML mode', (WidgetTester tester) async {
|
||||
testWidgets('capabilities are set properly in HTML mode', (WidgetTester tester) async {
|
||||
await tester.pumpAndSettle();
|
||||
expect(isCanvasKit, false);
|
||||
expect(isSkwasm, false);
|
||||
expect(isSkiaWeb, false);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// 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:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
testWidgets('capabilities are set properly in Skwasm mode', (WidgetTester tester) async {
|
||||
await tester.pumpAndSettle();
|
||||
expect(isCanvasKit, false);
|
||||
expect(isSkwasm, true);
|
||||
expect(isSkiaWeb, true);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// 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:integration_test/integration_test_driver.dart' as test;
|
||||
|
||||
Future<void> main() async => test.integrationDriver();
|
12
examples/hello_world/web/flutter_bootstrap.js
Normal file
12
examples/hello_world/web/flutter_bootstrap.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
// 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.
|
||||
|
||||
{{flutter_js}}
|
||||
{{flutter_build_config}}
|
||||
_flutter.loader.load({
|
||||
config: {
|
||||
// Use the local CanvasKit bundle instead of the CDN to reduce test flakiness.
|
||||
canvasKitBaseUrl: "/canvaskit/",
|
||||
},
|
||||
});
|
|
@ -7,6 +7,6 @@ found in the LICENSE file. -->
|
|||
<title>Hello, World</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="main.dart.js"></script>
|
||||
<script src="flutter_bootstrap.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -64,7 +64,7 @@ class BuildWebCommand extends BuildSubCommand {
|
|||
help:
|
||||
'Sets the optimization level used for Dart compilation to JavaScript/Wasm.',
|
||||
defaultsTo: '${WebCompilerConfig.kDefaultOptimizationLevel}',
|
||||
allowed: const <String>['1', '2', '3', '4'],
|
||||
allowed: const <String>['0', '1', '2', '3', '4'],
|
||||
);
|
||||
|
||||
//
|
||||
|
|
|
@ -30,6 +30,7 @@ import '../runner/flutter_command_runner.dart';
|
|||
import '../tracing.dart';
|
||||
import '../vmservice.dart';
|
||||
import '../web/compile.dart';
|
||||
import '../web/web_constants.dart';
|
||||
import '../web/web_runner.dart';
|
||||
import 'daemon.dart';
|
||||
|
||||
|
@ -179,7 +180,12 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
|||
hide: !verboseHelp,
|
||||
help: 'Uninstall previous versions of the app on the device '
|
||||
'before reinstalling. Currently only supported on iOS.',
|
||||
);
|
||||
)
|
||||
..addFlag(
|
||||
FlutterOptions.kWebWasmFlag,
|
||||
help: 'Compile to WebAssembly rather than JavaScript.\n$kWasmMoreInfo',
|
||||
negatable: false,
|
||||
);
|
||||
usesWebOptions(verboseHelp: verboseHelp);
|
||||
usesTargetOption();
|
||||
usesPortOptions(verboseHelp: verboseHelp);
|
||||
|
@ -227,6 +233,13 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
|||
|
||||
String? get traceAllowlist => stringArg('trace-allowlist');
|
||||
|
||||
bool get useWasm => boolArg(FlutterOptions.kWebWasmFlag);
|
||||
|
||||
WebRendererMode get webRenderer => WebRendererMode.fromCliOption(
|
||||
stringArg(FlutterOptions.kWebRendererFlag),
|
||||
useWasm: useWasm
|
||||
);
|
||||
|
||||
/// Create a debugging options instance for the current `run` or `drive` invocation.
|
||||
@visibleForTesting
|
||||
@protected
|
||||
|
@ -242,10 +255,6 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
|||
final Map<String, String> webHeaders = featureFlags.isWebEnabled
|
||||
? extractWebHeaders()
|
||||
: const <String, String>{};
|
||||
final String? webRendererString = stringArg('web-renderer');
|
||||
final WebRendererMode webRenderer = (webRendererString != null)
|
||||
? WebRendererMode.values.byName(webRendererString)
|
||||
: WebRendererMode.auto;
|
||||
|
||||
if (buildInfo.mode.isRelease) {
|
||||
return DebuggingOptions.disabled(
|
||||
|
@ -264,6 +273,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
|||
webBrowserFlags: webBrowserFlags,
|
||||
webHeaders: webHeaders,
|
||||
webRenderer: webRenderer,
|
||||
webUseWasm: useWasm,
|
||||
enableImpeller: enableImpeller,
|
||||
enableVulkanValidation: enableVulkanValidation,
|
||||
uninstallFirst: uninstallFirst,
|
||||
|
@ -314,6 +324,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
|||
webLaunchUrl: featureFlags.isWebEnabled ? stringArg('web-launch-url') : null,
|
||||
webHeaders: webHeaders,
|
||||
webRenderer: webRenderer,
|
||||
webUseWasm: useWasm,
|
||||
vmserviceOutFile: stringArg('vmservice-out-file'),
|
||||
fastStart: argParser.options.containsKey('fast-start')
|
||||
&& boolArg('fast-start')
|
||||
|
@ -630,12 +641,21 @@ class RunCommand extends RunCommandBase {
|
|||
if (devices!.any((Device device) => device is AndroidDevice)) {
|
||||
_deviceDeprecationBehavior = DeprecationBehavior.exit;
|
||||
}
|
||||
|
||||
// Only support "web mode" with a single web device due to resident runner
|
||||
// refactoring required otherwise.
|
||||
webMode = featureFlags.isWebEnabled &&
|
||||
devices!.length == 1 &&
|
||||
await devices!.single.targetPlatform == TargetPlatform.web_javascript;
|
||||
|
||||
if (useWasm && !webMode) {
|
||||
throwToolExit('--wasm is only supported on the web platform');
|
||||
}
|
||||
|
||||
if (webRenderer == WebRendererMode.skwasm && !useWasm) {
|
||||
throwToolExit('Skwasm renderer requires --wasm');
|
||||
}
|
||||
|
||||
final String? flavor = stringArg('flavor');
|
||||
final bool flavorsSupportedOnEveryDevice = devices!
|
||||
.every((Device device) => device.supportsFlavors);
|
||||
|
|
|
@ -330,6 +330,11 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
|||
return super.verifyThenRunCommand(commandPath);
|
||||
}
|
||||
|
||||
WebRendererMode get webRenderer => WebRendererMode.fromCliOption(
|
||||
stringArg(FlutterOptions.kWebRendererFlag),
|
||||
useWasm: useWasm
|
||||
);
|
||||
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
if (!globals.fs.isFileSync('pubspec.yaml')) {
|
||||
|
@ -388,10 +393,6 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
|||
);
|
||||
}
|
||||
|
||||
final String? webRendererString = stringArg('web-renderer');
|
||||
final WebRendererMode webRenderer = (webRendererString != null)
|
||||
? WebRendererMode.values.byName(webRendererString)
|
||||
: WebRendererMode.auto;
|
||||
final DebuggingOptions debuggingOptions = DebuggingOptions.enabled(
|
||||
buildInfo,
|
||||
startPaused: startPaused,
|
||||
|
@ -405,6 +406,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
|||
enableImpeller: ImpellerStatus.fromBool(argResults!['enable-impeller'] as bool?),
|
||||
debugLogsDirectoryPath: debugLogsDirectoryPath,
|
||||
webRenderer: webRenderer,
|
||||
webUseWasm: useWasm,
|
||||
);
|
||||
|
||||
String? testAssetDirectory;
|
||||
|
@ -511,6 +513,10 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
|||
throwToolExit('--wasm is only supported on the web platform');
|
||||
}
|
||||
|
||||
if (webRenderer == WebRendererMode.skwasm && !useWasm) {
|
||||
throwToolExit('Skwasm renderer requires --wasm');
|
||||
}
|
||||
|
||||
Device? integrationTestDevice;
|
||||
if (_isIntegrationTest) {
|
||||
integrationTestDevice = await findTargetDevice();
|
||||
|
@ -589,7 +595,6 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
|||
testAssetDirectory: testAssetDirectory,
|
||||
flutterProject: flutterProject,
|
||||
web: isWeb,
|
||||
useWasm: useWasm,
|
||||
randomSeed: stringArg('test-randomize-ordering-seed'),
|
||||
reporter: stringArg('reporter'),
|
||||
fileReporter: stringArg('file-reporter'),
|
||||
|
|
|
@ -994,6 +994,7 @@ class DebuggingOptions {
|
|||
this.webHeaders = const <String, String>{},
|
||||
this.webLaunchUrl,
|
||||
this.webRenderer = WebRendererMode.auto,
|
||||
this.webUseWasm = false,
|
||||
this.vmserviceOutFile,
|
||||
this.fastStart = false,
|
||||
this.nullAssertions = false,
|
||||
|
@ -1024,6 +1025,7 @@ class DebuggingOptions {
|
|||
this.webLaunchUrl,
|
||||
this.webHeaders = const <String, String>{},
|
||||
this.webRenderer = WebRendererMode.auto,
|
||||
this.webUseWasm = false,
|
||||
this.cacheSkSL = false,
|
||||
this.traceAllowlist,
|
||||
this.enableImpeller = ImpellerStatus.platformDefault,
|
||||
|
@ -1104,6 +1106,7 @@ class DebuggingOptions {
|
|||
required this.webHeaders,
|
||||
required this.webLaunchUrl,
|
||||
required this.webRenderer,
|
||||
required this.webUseWasm,
|
||||
required this.vmserviceOutFile,
|
||||
required this.fastStart,
|
||||
required this.nullAssertions,
|
||||
|
@ -1191,6 +1194,9 @@ class DebuggingOptions {
|
|||
/// Which web renderer to use for the debugging session
|
||||
final WebRendererMode webRenderer;
|
||||
|
||||
/// Whether to compile to webassembly
|
||||
final bool webUseWasm;
|
||||
|
||||
/// A file where the VM Service URL should be written after the application is started.
|
||||
final String? vmserviceOutFile;
|
||||
final bool fastStart;
|
||||
|
@ -1300,6 +1306,7 @@ class DebuggingOptions {
|
|||
'webLaunchUrl': webLaunchUrl,
|
||||
'webHeaders': webHeaders,
|
||||
'webRenderer': webRenderer.name,
|
||||
'webUseWasm': webUseWasm,
|
||||
'vmserviceOutFile': vmserviceOutFile,
|
||||
'fastStart': fastStart,
|
||||
'nullAssertions': nullAssertions,
|
||||
|
@ -1356,6 +1363,7 @@ class DebuggingOptions {
|
|||
webHeaders: (json['webHeaders']! as Map<dynamic, dynamic>).cast<String, String>(),
|
||||
webLaunchUrl: json['webLaunchUrl'] as String?,
|
||||
webRenderer: WebRendererMode.values.byName(json['webRenderer']! as String),
|
||||
webUseWasm: json['webUseWasm']! as bool,
|
||||
vmserviceOutFile: json['vmserviceOutFile'] as String?,
|
||||
fastStart: json['fastStart']! as bool,
|
||||
nullAssertions: json['nullAssertions']! as bool,
|
||||
|
|
|
@ -79,6 +79,7 @@ class WebDriverService extends DriverService {
|
|||
port: debuggingOptions.port,
|
||||
hostname: debuggingOptions.hostname,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
webUseWasm: debuggingOptions.webUseWasm
|
||||
)
|
||||
: DebuggingOptions.enabled(
|
||||
buildInfo,
|
||||
|
@ -86,6 +87,7 @@ class WebDriverService extends DriverService {
|
|||
hostname: debuggingOptions.hostname,
|
||||
disablePortPublication: debuggingOptions.disablePortPublication,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
webUseWasm: debuggingOptions.webUseWasm,
|
||||
),
|
||||
stayResident: true,
|
||||
flutterProject: FlutterProject.current(),
|
||||
|
|
|
@ -180,6 +180,7 @@ class WebAssetServer implements AssetReader {
|
|||
Map<String, String> extraHeaders,
|
||||
NullSafetyMode nullSafetyMode, {
|
||||
required WebRendererMode webRenderer,
|
||||
required bool isWasm,
|
||||
bool testMode = false,
|
||||
DwdsLauncher dwdsLauncher = Dwds.start,
|
||||
// TODO(markzipan): Make sure this default value aligns with that in the debugger options.
|
||||
|
@ -237,8 +238,8 @@ class WebAssetServer implements AssetReader {
|
|||
return server;
|
||||
}
|
||||
|
||||
// In release builds deploy a simpler proxy server.
|
||||
if (buildInfo.mode != BuildMode.debug) {
|
||||
// In release builds (or wasm builds) deploy a simpler proxy server.
|
||||
if (buildInfo.mode != BuildMode.debug || isWasm) {
|
||||
final ReleaseAssetServer releaseAssetServer = ReleaseAssetServer(
|
||||
entrypoint,
|
||||
fileSystem: globals.fs,
|
||||
|
@ -246,6 +247,7 @@ class WebAssetServer implements AssetReader {
|
|||
flutterRoot: Cache.flutterRoot,
|
||||
webBuildDirectory: getWebBuildDirectory(),
|
||||
basePath: server.basePath,
|
||||
needsCoopCoep: webRenderer == WebRendererMode.skwasm,
|
||||
);
|
||||
runZonedGuarded(() {
|
||||
shelf.serveRequests(httpServer!, releaseAssetServer.handle);
|
||||
|
@ -737,6 +739,7 @@ class WebDevFS implements DevFS {
|
|||
required this.nullSafetyMode,
|
||||
required this.ddcModuleSystem,
|
||||
required this.webRenderer,
|
||||
required this.isWasm,
|
||||
required this.rootDirectory,
|
||||
this.testMode = false,
|
||||
}) : _port = port;
|
||||
|
@ -763,6 +766,7 @@ class WebDevFS implements DevFS {
|
|||
final String? tlsCertPath;
|
||||
final String? tlsCertKeyPath;
|
||||
final WebRendererMode webRenderer;
|
||||
final bool isWasm;
|
||||
|
||||
late WebAssetServer webAssetServer;
|
||||
|
||||
|
@ -863,6 +867,7 @@ class WebDevFS implements DevFS {
|
|||
extraHeaders,
|
||||
nullSafetyMode,
|
||||
webRenderer: webRenderer,
|
||||
isWasm: isWasm,
|
||||
testMode: testMode,
|
||||
ddcModuleSystem: ddcModuleSystem,
|
||||
);
|
||||
|
@ -1108,11 +1113,13 @@ class ReleaseAssetServer {
|
|||
required String? webBuildDirectory,
|
||||
required String? flutterRoot,
|
||||
required Platform platform,
|
||||
required bool needsCoopCoep,
|
||||
this.basePath = '',
|
||||
}) : _fileSystem = fileSystem,
|
||||
_platform = platform,
|
||||
_flutterRoot = flutterRoot,
|
||||
_webBuildDirectory = webBuildDirectory,
|
||||
_needsCoopCoep = needsCoopCoep,
|
||||
_fileSystemUtils =
|
||||
FileSystemUtils(fileSystem: fileSystem, platform: platform);
|
||||
|
||||
|
@ -1122,6 +1129,7 @@ class ReleaseAssetServer {
|
|||
final FileSystem _fileSystem;
|
||||
final FileSystemUtils _fileSystemUtils;
|
||||
final Platform _platform;
|
||||
final bool _needsCoopCoep;
|
||||
|
||||
/// The base path to serve from.
|
||||
///
|
||||
|
@ -1174,14 +1182,23 @@ class ReleaseAssetServer {
|
|||
'application/octet-stream';
|
||||
return shelf.Response.ok(bytes, headers: <String, String>{
|
||||
'Content-Type': mimeType,
|
||||
if (_needsCoopCoep && file.basename == 'index.html') ...<String, String>{
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final File file = _fileSystem
|
||||
.file(_fileSystem.path.join(_webBuildDirectory!, 'index.html'));
|
||||
return shelf.Response.ok(file.readAsBytesSync(), headers: <String, String>{
|
||||
'Content-Type': 'text/html',
|
||||
});
|
||||
return shelf.Response.ok(file.readAsBytesSync(),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'text/html',
|
||||
if (_needsCoopCoep) ...<String, String>{
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -134,9 +134,9 @@ class ResidentWebRunner extends ResidentRunner {
|
|||
// and platform initialization.
|
||||
Directory? _generatedEntrypointDirectory;
|
||||
|
||||
// Only the debug builds of the web support the service protocol.
|
||||
// Only non-wasm debug builds of the web support the service protocol.
|
||||
@override
|
||||
bool get supportsServiceProtocol => isRunningDebug && deviceIsDebuggable;
|
||||
bool get supportsServiceProtocol => !debuggingOptions.webUseWasm && isRunningDebug && deviceIsDebuggable;
|
||||
|
||||
@override
|
||||
bool get debuggingEnabled => isRunningDebug && deviceIsDebuggable;
|
||||
|
@ -311,13 +311,14 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
|
|||
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
|
||||
ddcModuleSystem: debuggingOptions.buildInfo.ddcModuleFormat == DdcModuleFormat.ddc,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
isWasm: debuggingOptions.webUseWasm,
|
||||
rootDirectory: fileSystem.directory(projectRootPath),
|
||||
);
|
||||
Uri url = await device!.devFS!.create();
|
||||
if (debuggingOptions.tlsCertKeyPath != null && debuggingOptions.tlsCertPath != null) {
|
||||
url = url.replace(scheme: 'https');
|
||||
}
|
||||
if (debuggingOptions.buildInfo.isDebug) {
|
||||
if (debuggingOptions.buildInfo.isDebug && !debuggingOptions.webUseWasm) {
|
||||
await runSourceGenerators();
|
||||
final UpdateFSReport report = await _updateDevFS(fullRestart: true);
|
||||
if (!report.success) {
|
||||
|
@ -342,12 +343,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
|
|||
target,
|
||||
debuggingOptions.buildInfo,
|
||||
ServiceWorkerStrategy.none,
|
||||
compilerConfigs: <WebCompilerConfig>[
|
||||
JsCompilerConfig.run(
|
||||
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
|
||||
renderer: debuggingOptions.webRenderer,
|
||||
)
|
||||
]
|
||||
compilerConfigs: <WebCompilerConfig>[_compilerConfig],
|
||||
);
|
||||
}
|
||||
await device!.device!.startApp(
|
||||
|
@ -386,6 +382,17 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
|
|||
}
|
||||
}
|
||||
|
||||
WebCompilerConfig get _compilerConfig => (debuggingOptions.webUseWasm)
|
||||
? WasmCompilerConfig(
|
||||
optimizationLevel: 0,
|
||||
stripWasm: false,
|
||||
renderer: debuggingOptions.webRenderer
|
||||
)
|
||||
: JsCompilerConfig.run(
|
||||
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
|
||||
renderer: debuggingOptions.webRenderer,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<OperationResult> restart({
|
||||
bool fullRestart = false,
|
||||
|
@ -399,7 +406,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
|
|||
progressId: 'hot.restart',
|
||||
);
|
||||
|
||||
if (debuggingOptions.buildInfo.isDebug) {
|
||||
if (debuggingOptions.buildInfo.isDebug && !debuggingOptions.webUseWasm) {
|
||||
await runSourceGenerators();
|
||||
// Full restart is always false for web, since the extra recompile is wasteful.
|
||||
final UpdateFSReport report = await _updateDevFS();
|
||||
|
@ -426,12 +433,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
|
|||
target,
|
||||
debuggingOptions.buildInfo,
|
||||
ServiceWorkerStrategy.none,
|
||||
compilerConfigs: <WebCompilerConfig>[
|
||||
JsCompilerConfig.run(
|
||||
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
|
||||
renderer: debuggingOptions.webRenderer,
|
||||
)
|
||||
],
|
||||
compilerConfigs: <WebCompilerConfig>[_compilerConfig],
|
||||
);
|
||||
} on ToolExit {
|
||||
return OperationResult(1, 'Failed to recompile application.');
|
||||
|
|
|
@ -1181,10 +1181,10 @@ abstract class ResidentRunner extends ResidentHandlers {
|
|||
bool get debuggingEnabled => debuggingOptions.debuggingEnabled;
|
||||
|
||||
@override
|
||||
bool get isRunningDebug => debuggingOptions.buildInfo.isDebug;
|
||||
bool get isRunningDebug => !debuggingOptions.webUseWasm && debuggingOptions.buildInfo.isDebug;
|
||||
|
||||
@override
|
||||
bool get isRunningProfile => debuggingOptions.buildInfo.isProfile;
|
||||
bool get isRunningProfile => !debuggingOptions.webUseWasm && debuggingOptions.buildInfo.isProfile;
|
||||
|
||||
@override
|
||||
bool get isRunningRelease => debuggingOptions.buildInfo.isRelease;
|
||||
|
|
|
@ -52,7 +52,6 @@ abstract class FlutterTestRunner {
|
|||
String? icudtlPath,
|
||||
Directory? coverageDirectory,
|
||||
bool web = false,
|
||||
bool useWasm = false,
|
||||
String? randomSeed,
|
||||
String? reporter,
|
||||
String? fileReporter,
|
||||
|
@ -118,7 +117,6 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
|||
String? icudtlPath,
|
||||
Directory? coverageDirectory,
|
||||
bool web = false,
|
||||
bool useWasm = false,
|
||||
String? randomSeed,
|
||||
String? reporter,
|
||||
String? fileReporter,
|
||||
|
@ -188,7 +186,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
|||
testFiles: testFiles.map((Uri uri) => uri.toFilePath()).toList(),
|
||||
buildInfo: debuggingOptions.buildInfo,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
useWasm: useWasm,
|
||||
useWasm: debuggingOptions.webUseWasm,
|
||||
);
|
||||
testArgs
|
||||
..add('--platform=chrome')
|
||||
|
@ -221,7 +219,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
|||
),
|
||||
testTimeRecorder: testTimeRecorder,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
useWasm: useWasm,
|
||||
useWasm: debuggingOptions.webUseWasm,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -184,6 +184,17 @@ enum WebRendererMode implements CliEnum {
|
|||
/// Always use skwasm.
|
||||
skwasm;
|
||||
|
||||
factory WebRendererMode.fromCliOption(String? webRendererString, {required bool useWasm}) {
|
||||
final WebRendererMode mode = webRendererString != null
|
||||
? WebRendererMode.values.byName(webRendererString)
|
||||
: WebRendererMode.auto;
|
||||
if (mode == WebRendererMode.auto && useWasm) {
|
||||
// Wasm defaults to skwasm
|
||||
return WebRendererMode.skwasm;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
@override
|
||||
String get cliName => snakeCase(name, '-');
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ sealed class WebCompilerConfig {
|
|||
|
||||
/// The compiler optimization level.
|
||||
///
|
||||
/// Valid values are O1 (lowest, profile default) to O4 (highest, release default).
|
||||
/// Valid values are O0 (lowest, debug default) to O4 (highest, release default).
|
||||
final int optimizationLevel;
|
||||
|
||||
/// Returns which target this compiler outputs (js or wasm)
|
||||
|
|
|
@ -29,6 +29,7 @@ import 'package:flutter_tools/src/resident_runner.dart';
|
|||
import 'package:flutter_tools/src/run_hot.dart';
|
||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||
import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:flutter_tools/src/web/compile.dart';
|
||||
import 'package:test/fake.dart';
|
||||
import 'package:unified_analytics/unified_analytics.dart' as analytics;
|
||||
import 'package:vm_service/vm_service.dart';
|
||||
|
@ -986,6 +987,36 @@ void main() {
|
|||
DeviceManager: () => testDeviceManager,
|
||||
});
|
||||
|
||||
testUsingContext('throws a ToolExit when using --wasm on a non-web platform', () async {
|
||||
final RunCommand command = RunCommand();
|
||||
await expectLater(
|
||||
() => createTestCommandRunner(command).run(<String>[
|
||||
'run',
|
||||
'--no-pub',
|
||||
'--wasm',
|
||||
]), throwsToolExit(message: '--wasm is only supported on the web platform'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Logger: () => logger,
|
||||
DeviceManager: () => testDeviceManager,
|
||||
});
|
||||
|
||||
testUsingContext('throws a ToolExit when using the skwasm renderer without --wasm', () async {
|
||||
final RunCommand command = RunCommand();
|
||||
await expectLater(
|
||||
() => createTestCommandRunner(command).run(<String>[
|
||||
'run',
|
||||
'--no-pub',
|
||||
'--web-renderer=skwasm',
|
||||
]), throwsToolExit(message: 'Skwasm renderer requires --wasm'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Logger: () => logger,
|
||||
DeviceManager: () => testDeviceManager,
|
||||
});
|
||||
|
||||
testUsingContext('accepts headers with commas in them', () async {
|
||||
final RunCommand command = RunCommand();
|
||||
await expectLater(
|
||||
|
@ -1170,6 +1201,24 @@ void main() {
|
|||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('wasm mode selects skwasm renderer by default', () async {
|
||||
final RunCommand command = RunCommand();
|
||||
await expectLater(() => createTestCommandRunner(command).run(<String>[
|
||||
'run',
|
||||
'-d chrome',
|
||||
'--wasm',
|
||||
]), throwsToolExit());
|
||||
|
||||
final DebuggingOptions options = await command.createDebuggingOptions(false);
|
||||
|
||||
expect(options.webUseWasm, true);
|
||||
expect(options.webRenderer, WebRendererMode.skwasm);
|
||||
}, overrides: <Type, Generator>{
|
||||
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('fails when "--web-launch-url" is not supported', () async {
|
||||
final RunCommand command = RunCommand();
|
||||
await expectLater(
|
||||
|
|
|
@ -1348,6 +1348,24 @@ dev_dependencies:
|
|||
FileSystem: () => fs,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('Web renderer defaults to Skwasm when using wasm', () async {
|
||||
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
|
||||
|
||||
final TestCommand testCommand = TestCommand(testRunner: testRunner);
|
||||
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
|
||||
|
||||
await commandRunner.run(const <String>[
|
||||
'test',
|
||||
'--no-pub',
|
||||
'--platform=chrome',
|
||||
'--wasm',
|
||||
]);
|
||||
expect(testRunner.lastDebuggingOptionsValue.webRenderer, WebRendererMode.skwasm);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -137,6 +137,7 @@ void main() {
|
|||
flutterRoot: null, // ignore: avoid_redundant_argument_values
|
||||
platform: FakePlatform(),
|
||||
webBuildDirectory: null, // ignore: avoid_redundant_argument_values
|
||||
needsCoopCoep: false,
|
||||
);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
|
@ -927,6 +928,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.unsound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.html,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
|
||||
|
@ -1063,6 +1065,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.html,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
|
||||
|
@ -1199,6 +1202,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
|
||||
|
@ -1272,6 +1276,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
|
||||
|
@ -1321,6 +1326,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
|
||||
|
@ -1372,6 +1378,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.auto,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
|
||||
|
@ -1425,6 +1432,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.unsound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
|
||||
|
@ -1463,6 +1471,7 @@ void main() {
|
|||
const <String, String>{},
|
||||
NullSafetyMode.unsound,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
testMode: true);
|
||||
|
||||
expect(webAssetServer.defaultResponseHeaders['x-frame-options'], null);
|
||||
|
@ -1496,6 +1505,7 @@ void main() {
|
|||
},
|
||||
NullSafetyMode.unsound,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
testMode: true);
|
||||
|
||||
expect(webAssetServer.defaultResponseHeaders[extraHeaderKey],
|
||||
|
@ -1596,6 +1606,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.unsound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
|
||||
|
|
|
@ -76,6 +76,7 @@ void main() {
|
|||
flutterRoot: null,
|
||||
platform: FakePlatform(),
|
||||
webBuildDirectory: null,
|
||||
needsCoopCoep: false,
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
Logger: () => logger,
|
||||
|
@ -715,6 +716,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.unsound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.html,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.requireJS.createSync(recursive: true);
|
||||
|
@ -827,6 +829,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.html,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.requireJS.createSync(recursive: true);
|
||||
|
@ -945,6 +948,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.requireJS.createSync(recursive: true);
|
||||
|
@ -1009,6 +1013,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.requireJS.createSync(recursive: true);
|
||||
|
@ -1057,6 +1062,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.requireJS.createSync(recursive: true);
|
||||
|
@ -1106,6 +1112,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.sound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.auto,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.requireJS.createSync(recursive: true);
|
||||
|
@ -1156,6 +1163,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.unsound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.requireJS.createSync(recursive: true);
|
||||
|
@ -1194,6 +1202,7 @@ void main() {
|
|||
const <String, String>{},
|
||||
NullSafetyMode.unsound,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
testMode: true
|
||||
);
|
||||
|
||||
|
@ -1228,6 +1237,7 @@ void main() {
|
|||
},
|
||||
NullSafetyMode.unsound,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
testMode: true
|
||||
);
|
||||
|
||||
|
@ -1310,6 +1320,7 @@ void main() {
|
|||
nullSafetyMode: NullSafetyMode.unsound,
|
||||
ddcModuleSystem: usesDdcModuleSystem,
|
||||
webRenderer: WebRendererMode.canvaskit,
|
||||
isWasm: false,
|
||||
rootDirectory: globals.fs.currentDirectory,
|
||||
);
|
||||
webDevFS.requireJS.createSync(recursive: true);
|
||||
|
|
|
@ -49,6 +49,7 @@ void main() {
|
|||
platform: platform,
|
||||
flutterRoot: '/flutter',
|
||||
webBuildDirectory: 'build/web',
|
||||
needsCoopCoep: false,
|
||||
);
|
||||
fileSystem.file('build/web/assets/foo.png')
|
||||
..createSync(recursive: true)
|
||||
|
@ -68,6 +69,7 @@ void main() {
|
|||
platform: platform,
|
||||
flutterRoot: '/flutter',
|
||||
webBuildDirectory: 'build/web',
|
||||
needsCoopCoep: false,
|
||||
);
|
||||
fileSystem.file('build/web/assets/foo.js')
|
||||
..createSync(recursive: true)
|
||||
|
@ -87,6 +89,7 @@ void main() {
|
|||
platform: platform,
|
||||
flutterRoot: '/flutter',
|
||||
webBuildDirectory: 'build/web',
|
||||
needsCoopCoep: false,
|
||||
);
|
||||
fileSystem.file('build/web/assets/foo.html')
|
||||
..createSync(recursive: true)
|
||||
|
@ -106,6 +109,7 @@ void main() {
|
|||
platform: platform,
|
||||
flutterRoot: '/flutter',
|
||||
webBuildDirectory: 'build/web',
|
||||
needsCoopCoep: false,
|
||||
);
|
||||
fileSystem.file('flutter/bar.dart')
|
||||
..createSync(recursive: true)
|
||||
|
@ -122,6 +126,7 @@ void main() {
|
|||
platform: platform,
|
||||
flutterRoot: '/flutter',
|
||||
webBuildDirectory: 'build/web',
|
||||
needsCoopCoep: false,
|
||||
);
|
||||
fileSystem.file('bar.dart')
|
||||
..createSync(recursive: true)
|
||||
|
@ -131,4 +136,44 @@ void main() {
|
|||
|
||||
expect(response.statusCode, HttpStatus.ok);
|
||||
});
|
||||
|
||||
testWithoutContext('release asset server serves html content with COOP/COEP headers when specified', () async {
|
||||
final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base,
|
||||
fileSystem: fileSystem,
|
||||
platform: platform,
|
||||
flutterRoot: '/flutter',
|
||||
webBuildDirectory: 'build/web',
|
||||
needsCoopCoep: true,
|
||||
);
|
||||
fileSystem.file('build/web/index.html')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('<html></html>');
|
||||
final Response response = await assetServer
|
||||
.handle(Request('GET', Uri.parse('http://localhost:8080/index.html')));
|
||||
|
||||
expect(response.statusCode, HttpStatus.ok);
|
||||
final Map<String, String> headers = response.headers;
|
||||
expect(headers['Cross-Origin-Opener-Policy'], 'same-origin');
|
||||
expect(headers['Cross-Origin-Embedder-Policy'], 'require-corp');
|
||||
});
|
||||
|
||||
testWithoutContext('release asset server serves html content without COOP/COEP headers when specified', () async {
|
||||
final ReleaseAssetServer assetServer = ReleaseAssetServer(Uri.base,
|
||||
fileSystem: fileSystem,
|
||||
platform: platform,
|
||||
flutterRoot: '/flutter',
|
||||
webBuildDirectory: 'build/web',
|
||||
needsCoopCoep: false,
|
||||
);
|
||||
fileSystem.file('build/web/index.html')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('<html></html>');
|
||||
final Response response = await assetServer
|
||||
.handle(Request('GET', Uri.parse('http://localhost:8080/index.html')));
|
||||
|
||||
expect(response.statusCode, HttpStatus.ok);
|
||||
final Map<String, String> headers = response.headers;
|
||||
expect(headers.containsKey('Cross-Origin-Opener-Policy'), false);
|
||||
expect(headers.containsKey('Cross-Origin-Embedder-Policy'), false);
|
||||
});
|
||||
}
|
||||
|
|
12
packages/integration_test/example/web/flutter_bootstrap.js
Normal file
12
packages/integration_test/example/web/flutter_bootstrap.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
// 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.
|
||||
|
||||
{{flutter_js}}
|
||||
{{flutter_build_config}}
|
||||
_flutter.loader.load({
|
||||
config: {
|
||||
// Use the local CanvasKit bundle instead of the CDN to reduce test flakiness.
|
||||
canvasKitBaseUrl: "/canvaskit/",
|
||||
},
|
||||
});
|
|
@ -21,16 +21,6 @@ found in the LICENSE file. -->
|
|||
<link rel="manifest" href="/manifest.json">
|
||||
</head>
|
||||
<body>
|
||||
<!-- This script installs service_worker.js to provide PWA functionality to
|
||||
application. For more information, see:
|
||||
https://developers.google.com/web/fundamentals/primers/service-workers -->
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function () {
|
||||
navigator.serviceWorker.register('/flutter_service_worker.js');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script src="main.dart.js" type="application/javascript"></script>
|
||||
<script src="flutter_bootstrap.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue