diff --git a/packages/flutter_tools/lib/src/build_system/build_targets.dart b/packages/flutter_tools/lib/src/build_system/build_targets.dart index 0c5a31b807f..a0471d10195 100644 --- a/packages/flutter_tools/lib/src/build_system/build_targets.dart +++ b/packages/flutter_tools/lib/src/build_system/build_targets.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:unified_analytics/unified_analytics.dart'; + import '../base/file_system.dart'; import '../web/compiler_config.dart'; import './build_system.dart'; @@ -14,7 +16,11 @@ abstract class BuildTargets { Target get releaseCopyFlutterBundle; Target get generateLocalizationsTarget; Target get dartPluginRegistrantTarget; - Target webServiceWorker(FileSystem fileSystem, List compileConfigs); + Target webServiceWorker( + FileSystem fileSystem, + List compileConfigs, + Analytics analytics, + ); } /// BuildTargets that return NoOpTarget for every action. @@ -34,8 +40,11 @@ class NoOpBuildTargets extends BuildTargets { Target get dartPluginRegistrantTarget => const _NoOpTarget(); @override - Target webServiceWorker(FileSystem fileSystem, List compileConfigs) => - const _NoOpTarget(); + Target webServiceWorker( + FileSystem fileSystem, + List compileConfigs, + Analytics analytics, + ) => const _NoOpTarget(); } /// A [Target] that does nothing. diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart index aad6e5b65f4..57fda33e446 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/web.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart @@ -6,6 +6,7 @@ import 'dart:math'; import 'package:crypto/crypto.dart'; import 'package:package_config/package_config.dart'; +import 'package:unified_analytics/unified_analytics.dart'; import '../../artifacts.dart'; import '../../base/file_system.dart'; @@ -273,11 +274,13 @@ class Dart2JSTarget extends Dart2WebTarget { /// Compiles a web entry point with dart2wasm. class Dart2WasmTarget extends Dart2WebTarget { - Dart2WasmTarget(this.compilerConfig); + Dart2WasmTarget(this.compilerConfig, this._analytics); @override final WasmCompilerConfig compilerConfig; + final Analytics _analytics; + /// List the preconfigured build options for a given build mode. List buildModeOptions(BuildMode mode, List dartDefines) => switch (mode) { BuildMode.debug => [ @@ -403,22 +406,28 @@ class Dart2WasmTarget extends Dart2WebTarget { final int exitCode = runResult.exitCode; final String stdout = runResult.stdout; final String stderr = runResult.stderr; + final String result; + String? findingsSummary; + if (exitCode != 0 && exitCode != 254) { environment.logger.printWarning('Unexpected wasm dry run failure ($exitCode):'); if (stderr.isNotEmpty) { environment.logger.printWarning(stdout); environment.logger.printWarning(stderr); } + result = 'crash'; } else if (exitCode == 0) { environment.logger.printWarning( 'Wasm dry run succeeded. Consider building and testing your application with the ' '`--wasm` flag. See docs for more info: ' 'https://docs.flutter.dev/platform-integration/web/wasm', ); + result = 'success'; } else if (stderr.isNotEmpty) { environment.logger.printWarning('Wasm dry run failed:'); environment.logger.printWarning(stdout); environment.logger.printWarning(stderr); + result = 'failure'; } else if (stdout.isNotEmpty) { environment.logger.printWarning('Wasm dry run findings:'); environment.logger.printWarning(stdout); @@ -426,20 +435,30 @@ class Dart2WasmTarget extends Dart2WebTarget { 'Consider addressing these issues to enable wasm builds. See docs for more info: ' 'https://docs.flutter.dev/platform-integration/web/wasm\n', ); + result = 'findings'; + findingsSummary = RegExp( + r'\(([0-9]+)\)', + ).allMatches(stdout).map((RegExpMatch f) => f.group(1)).join(','); + } else { + result = 'unknown'; } environment.logger.printWarning('Use --no-wasm-dry-run to disable these warnings.'); + + _analytics.send( + Event.flutterWasmDryRun(result: result, exitCode: exitCode, findingsSummary: findingsSummary), + ); } } /// Unpacks the dart2js or dart2wasm compilation and resources to a given /// output directory. class WebReleaseBundle extends Target { - WebReleaseBundle(List configs) + WebReleaseBundle(List configs, Analytics analytics) : this._( compileTargets: configs .map( (WebCompilerConfig config) => switch (config) { - WasmCompilerConfig() => Dart2WasmTarget(config), + WasmCompilerConfig() => Dart2WasmTarget(config, analytics), JsCompilerConfig() => Dart2JSTarget(config), }, ) @@ -743,17 +762,18 @@ class WebBuiltInAssets extends Target { /// Generate a service worker for a web target. class WebServiceWorker extends Target { - const WebServiceWorker(this.fileSystem, this.compileConfigs); + const WebServiceWorker(this.fileSystem, this.compileConfigs, this.analytics); final FileSystem fileSystem; final List compileConfigs; + final Analytics analytics; @override String get name => 'web_service_worker'; @override List get dependencies => [ - WebReleaseBundle(compileConfigs), + WebReleaseBundle(compileConfigs, analytics), WebBuiltInAssets(fileSystem), ]; diff --git a/packages/flutter_tools/lib/src/isolated/build_targets.dart b/packages/flutter_tools/lib/src/isolated/build_targets.dart index e721495a289..fb46f915cc8 100644 --- a/packages/flutter_tools/lib/src/isolated/build_targets.dart +++ b/packages/flutter_tools/lib/src/isolated/build_targets.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:unified_analytics/unified_analytics.dart'; + import '../base/file_system.dart'; import '../build_system/build_system.dart'; import '../build_system/build_targets.dart'; @@ -27,6 +29,9 @@ class BuildTargetsImpl extends BuildTargets { Target get dartPluginRegistrantTarget => const DartPluginRegistrantTarget(); @override - Target webServiceWorker(FileSystem fileSystem, List compileConfigs) => - WebServiceWorker(fileSystem, compileConfigs); + Target webServiceWorker( + FileSystem fileSystem, + List compileConfigs, + Analytics analytics, + ) => WebServiceWorker(fileSystem, compileConfigs, analytics); } diff --git a/packages/flutter_tools/lib/src/web/compile.dart b/packages/flutter_tools/lib/src/web/compile.dart index 316ec9bbd2e..327393e3d76 100644 --- a/packages/flutter_tools/lib/src/web/compile.dart +++ b/packages/flutter_tools/lib/src/web/compile.dart @@ -88,7 +88,7 @@ class WebBuilder { final Stopwatch sw = Stopwatch()..start(); try { final BuildResult result = await _buildSystem.build( - globals.buildTargets.webServiceWorker(_fileSystem, compilerConfigs), + globals.buildTargets.webServiceWorker(_fileSystem, compilerConfigs, _analytics), Environment( projectDir: flutterProject.directory, outputDir: outputDirectory, diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml index 2bb5ff447f0..97b371ccfa6 100644 --- a/packages/flutter_tools/pubspec.yaml +++ b/packages/flutter_tools/pubspec.yaml @@ -53,7 +53,7 @@ dependencies: http_multi_server: 3.2.2 convert: 3.1.2 async: 2.13.0 - unified_analytics: 8.0.2 + unified_analytics: 8.0.5 pubspec_parse: 1.5.0 graphs: 2.3.2 @@ -126,4 +126,4 @@ dev_dependencies: dartdoc: # Exclude this package from the hosted API docs. nodoc: true -# PUBSPEC CHECKSUM: 36e76b +# PUBSPEC CHECKSUM: kr614i diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart index 23b555608c8..ade15105bba 100644 --- a/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart +++ b/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart @@ -17,6 +17,7 @@ import 'package:flutter_tools/src/isolated/mustache_template.dart'; import 'package:flutter_tools/src/web/compile.dart'; import 'package:flutter_tools/src/web/file_generators/flutter_service_worker_js.dart'; import 'package:flutter_tools/src/web_template.dart'; +import 'package:unified_analytics/unified_analytics.dart'; import '../../../src/common.dart'; import '../../../src/fake_process_manager.dart'; @@ -133,7 +134,9 @@ name: foo final Directory webResources = environment.projectDir.childDirectory('web'); webResources.childFile('index.html').createSync(recursive: true); environment.buildDir.childFile('main.dart.js').createSync(); - await WebReleaseBundle([const JsCompilerConfig()]).build(environment); + await WebReleaseBundle([ + const JsCompilerConfig(), + ], const NoOpAnalytics()).build(environment); expect(environment.outputDir.childFile('version.json'), exists); }), @@ -148,7 +151,9 @@ name: foo final Directory webResources = environment.projectDir.childDirectory('web'); webResources.childFile('index.html').createSync(recursive: true); environment.buildDir.childFile('main.dart.js').createSync(); - await WebReleaseBundle([const JsCompilerConfig()]).build(environment); + await WebReleaseBundle([ + const JsCompilerConfig(), + ], const NoOpAnalytics()).build(environment); final String versionFile = environment.outputDir.childFile('version.json').readAsStringSync(); expect(versionFile, contains('"version":"2.0.0"')); @@ -265,7 +270,7 @@ name: foo await WebReleaseBundle([ const JsCompilerConfig(dumpInfo: true), - ]).build(environment); + ], const NoOpAnalytics()).build(environment); expect(environment.outputDir.childFile('foo.txt').readAsStringSync(), 'A'); expect(environment.outputDir.childFile('main.dart.js').existsSync(), true); @@ -284,7 +289,9 @@ name: foo // Update to arbitrary resource file triggers rebuild. webResources.childFile('foo.txt').writeAsStringSync('B'); - await WebReleaseBundle([const JsCompilerConfig()]).build(environment); + await WebReleaseBundle([ + const JsCompilerConfig(), + ], const NoOpAnalytics()).build(environment); expect(environment.outputDir.childFile('foo.txt').readAsStringSync(), 'B'); }), @@ -304,7 +311,9 @@ name: foo environment.buildDir.childFile('main.dart.mjs') ..createSync() ..writeAsStringSync('old mjs'); - await WebReleaseBundle([const WasmCompilerConfig()]).build(environment); + await WebReleaseBundle([ + const WasmCompilerConfig(), + ], const NoOpAnalytics()).build(environment); expect(environment.outputDir.childFile('main.dart.wasm').readAsStringSync(), 'old wasm'); expect(environment.outputDir.childFile('main.dart.mjs').readAsStringSync(), 'old mjs'); @@ -315,7 +324,9 @@ name: foo ..createSync() ..writeAsStringSync('new mjs'); - await WebReleaseBundle([const WasmCompilerConfig()]).build(environment); + await WebReleaseBundle([ + const WasmCompilerConfig(), + ], const NoOpAnalytics()).build(environment); expect(environment.outputDir.childFile('main.dart.wasm').readAsStringSync(), 'new wasm'); expect(environment.outputDir.childFile('main.dart.mjs').readAsStringSync(), 'new mjs'); @@ -1198,6 +1209,7 @@ name: foo sourceMaps: sourceMaps, minify: minify, ), + const NoOpAnalytics(), ).build(environment); expect(outputJsFile.existsSync(), isTrue); @@ -1267,7 +1279,7 @@ name: foo ]; final Iterable buildKeys = testConfigs.map((WasmCompilerConfig config) { - final Dart2WasmTarget target = Dart2WasmTarget(config); + final Dart2WasmTarget target = Dart2WasmTarget(config, const NoOpAnalytics()); return target.buildKey; }); @@ -1404,7 +1416,7 @@ name: foo ..writeAsStringSync('A'); await WebServiceWorker(globals.fs, [ const JsCompilerConfig(), - ]).build(environment); + ], const NoOpAnalytics()).build(environment); expect(environment.outputDir.childFile('flutter_service_worker.js'), exists); // Contains file hash. @@ -1435,7 +1447,7 @@ name: foo ..writeAsStringSync('A'); await WebServiceWorker(globals.fs, [ const JsCompilerConfig(), - ]).build(environment); + ], const NoOpAnalytics()).build(environment); expect(environment.outputDir.childFile('flutter_service_worker.js'), exists); // Contains the same file hash for both `/` and the root index.html file. @@ -1464,7 +1476,7 @@ name: foo environment.outputDir.childFile('main.dart.js.map').createSync(recursive: true); await WebServiceWorker(globals.fs, [ const JsCompilerConfig(), - ]).build(environment); + ], const NoOpAnalytics()).build(environment); // No caching of source maps. expect(