[flutter_tools] wire up native-null-assertions for flutter web (#71618)
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 aff6c7c..ee56688d 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/web.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart
@@ -39,6 +39,9 @@ /// Whether the dart2js build should output source maps. const String kSourceMapsEnabled = 'SourceMaps'; +/// Whether the dart2js native null assertions are enabled. +const String kNativeNullAssertions = 'NativeNullAssertions'; + /// The caching strategy for the generated service worker. enum ServiceWorkerStrategy { /// Download the app shell eagerly and all other assets lazily. @@ -190,6 +193,7 @@ Future<void> build(Environment environment) async { final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]); final bool sourceMapsEnabled = environment.defines[kSourceMapsEnabled] == 'true'; + final bool nativeNullAssertions = environment.defines[kNativeNullAssertions] == 'true'; final List<String> sharedCommandOptions = <String>[ globals.artifacts.getArtifactPath(Artifact.engineDartBinary), @@ -197,6 +201,8 @@ globals.artifacts.getArtifactPath(Artifact.dart2jsSnapshot), '--libraries-spec=${globals.fs.path.join(globals.artifacts.getArtifactPath(Artifact.flutterWebSdk), 'libraries.json')}', ...?decodeDartDefines(environment.defines, kExtraFrontEndOptions), + if (nativeNullAssertions) + '--native-null-assertions', if (buildMode == BuildMode.profile) '-Ddart.vm.profile=true' else
diff --git a/packages/flutter_tools/lib/src/commands/build_web.dart b/packages/flutter_tools/lib/src/commands/build_web.dart index 62fad31..05c6ba5 100644 --- a/packages/flutter_tools/lib/src/commands/build_web.dart +++ b/packages/flutter_tools/lib/src/commands/build_web.dart
@@ -26,6 +26,7 @@ usesWebRendererOption(); addEnableExperimentation(hide: !verboseHelp); addNullSafetyModeOptions(hide: !verboseHelp); + addNativeNullAssertions(hide: false); argParser.addFlag('csp', defaultsTo: false, negatable: false, @@ -90,6 +91,7 @@ boolArg('csp'), stringArg('pwa-strategy'), boolArg('source-maps'), + boolArg('native-null-assertions'), ); return FlutterCommandResult.success(); }
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index d18cc18..374a554 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -30,6 +30,7 @@ usesDartDefineOption(); usesFlavorOption(); usesWebRendererOption(); + addNativeNullAssertions(hide: !verboseHelp); argParser ..addFlag('trace-startup', negatable: false, @@ -205,6 +206,7 @@ && boolArg('fast-start') && !runningWithPrebuiltApplication, nullAssertions: boolArg('null-assertions'), + nativeNullAssertions: boolArg('native-null-assertions'), ); } }
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 53932d7..019c129 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -863,6 +863,7 @@ this.vmserviceOutFile, this.fastStart = false, this.nullAssertions = false, + this.nativeNullAssertions = false, }) : debuggingEnabled = true; DebuggingOptions.disabled(this.buildInfo, { @@ -897,7 +898,8 @@ vmserviceOutFile = null, fastStart = false, webEnableExpressionEvaluation = false, - nullAssertions = false; + nullAssertions = false, + nativeNullAssertions = false; final bool debuggingEnabled; @@ -947,6 +949,12 @@ final bool nullAssertions; + /// Additional null runtime checks inserted for web applications. + /// + /// See also: + /// * https://github.com/dart-lang/sdk/blob/master/sdk/lib/html/doc/NATIVE_NULL_ASSERTIONS.md + final bool nativeNullAssertions; + bool get hasObservatoryPort => hostVmServicePort != null; }
diff --git a/packages/flutter_tools/lib/src/isolated/devfs_web.dart b/packages/flutter_tools/lib/src/isolated/devfs_web.dart index 2c24a79..7ca818b 100644 --- a/packages/flutter_tools/lib/src/isolated/devfs_web.dart +++ b/packages/flutter_tools/lib/src/isolated/devfs_web.dart
@@ -605,6 +605,7 @@ @required this.expressionCompiler, @required this.chromiumLauncher, @required this.nullAssertions, + @required this.nativeNullAssertions, @required this.nullSafetyMode, this.testMode = false, }) : _port = port; @@ -621,6 +622,7 @@ final ExpressionCompiler expressionCompiler; final ChromiumLauncher chromiumLauncher; final bool nullAssertions; + final bool nativeNullAssertions; final int _port; final NullSafetyMode nullSafetyMode; @@ -779,6 +781,7 @@ generateMainModule( entrypoint: entrypoint, nullAssertions: nullAssertions, + nativeNullAssertions: nativeNullAssertions, ), ); // TODO(jonahwilliams): refactor the asset code in this and the regular devfs to
diff --git a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart index e67be35..f0c98f7 100644 --- a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart
@@ -501,6 +501,7 @@ chromiumLauncher: _chromiumLauncher, nullAssertions: debuggingOptions.nullAssertions, nullSafetyMode: debuggingOptions.buildInfo.nullSafetyMode, + nativeNullAssertions: debuggingOptions.nativeNullAssertions, ); final Uri url = await device.devFS.create(); if (debuggingOptions.buildInfo.isDebug) { @@ -520,6 +521,7 @@ false, kNoneWorker, true, + debuggingOptions.nativeNullAssertions, ); } await device.device.startApp( @@ -587,6 +589,7 @@ false, kNoneWorker, true, + debuggingOptions.nativeNullAssertions, ); } on ToolExit { return OperationResult(1, 'Failed to recompile application.');
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index e2d2e35..f0ba9b8 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -674,6 +674,19 @@ ); } + void addNativeNullAssertions({ bool hide = false }) { + argParser.addFlag('native-null-assertions', + defaultsTo: true, + hide: hide, + help: 'Enables additional runtime null checks in web applications to ensure ' + 'the correct nullability of native (such as in dart:html) and external ' + '(such as with JS interop) types. This is enabled by default but only takes ' + 'effect in sound mode. To report an issue with a null assertion failure in ' + 'dart:html or the other dart web libraries, please file a bug at ' + 'https://github.com/dart-lang/sdk/issues/labels/web-libraries .' + ); + } + /// Adds build options common to all of the desktop build commands. void addCommonDesktopBuildOptions({ bool verboseHelp = false }) { addBuildModeFlags(verboseHelp: verboseHelp);
diff --git a/packages/flutter_tools/lib/src/test/flutter_web_platform.dart b/packages/flutter_tools/lib/src/test/flutter_web_platform.dart index 4eb4aa0..2b230f1 100644 --- a/packages/flutter_tools/lib/src/test/flutter_web_platform.dart +++ b/packages/flutter_tools/lib/src/test/flutter_web_platform.dart
@@ -224,6 +224,7 @@ final String generatedFile = _fileSystem.path.split(leadingPath).join('_') + '.dart.test.dart.js'; return shelf.Response.ok(generateMainModule( nullAssertions: nullAssertions, + nativeNullAssertions: true, bootstrapModule: _fileSystem.path.basename(leadingPath) + '.dart.bootstrap', entrypoint: '/' + generatedFile ), headers: <String, String>{
diff --git a/packages/flutter_tools/lib/src/web/bootstrap.dart b/packages/flutter_tools/lib/src/web/bootstrap.dart index 18c85a3..6071a27 100644 --- a/packages/flutter_tools/lib/src/web/bootstrap.dart +++ b/packages/flutter_tools/lib/src/web/bootstrap.dart
@@ -54,6 +54,7 @@ String generateMainModule({ @required String entrypoint, @required bool nullAssertions, + @required bool nativeNullAssertions, String bootstrapModule = 'main_module.bootstrap', }) { // TODO(jonahwilliams): fix typo in dwds and update. @@ -63,9 +64,8 @@ define("$bootstrapModule", ["$entrypoint", "dart_sdk"], function(app, dart_sdk) { dart_sdk.dart.setStartAsyncSynchronously(true); dart_sdk._debugger.registerDevtoolsFormatter(); - if ($nullAssertions) { - dart_sdk.dart.nonNullAsserts(true); - } + dart_sdk.dart.nonNullAsserts($nullAssertions); + dart_sdk.dart.nativeNonNullAsserts($nativeNullAssertions); // See the generateMainModule doc comment. var child = {};
diff --git a/packages/flutter_tools/lib/src/web/compile.dart b/packages/flutter_tools/lib/src/web/compile.dart index 7e08363..160f41d 100644 --- a/packages/flutter_tools/lib/src/web/compile.dart +++ b/packages/flutter_tools/lib/src/web/compile.dart
@@ -24,6 +24,7 @@ bool csp, String serviceWorkerStrategy, bool sourceMaps, + bool nativeNullAssertions, ) async { if (!flutterProject.web.existsSync()) { throwToolExit('Missing index.html.'); @@ -51,6 +52,7 @@ kCspMode: csp.toString(), kIconTreeShakerFlag: buildInfo.treeShakeIcons.toString(), kSourceMapsEnabled: sourceMaps.toString(), + kNativeNullAssertions: nativeNullAssertions.toString(), if (serviceWorkerStrategy != null) kServiceWorkerStrategy: serviceWorkerStrategy, if (buildInfo.extraFrontEndOptions?.isNotEmpty ?? false)