From 7ca4b7b86b9d46238061ba2a63ce15fe9d269c88 Mon Sep 17 00:00:00 2001 From: Tess Strickland Date: Mon, 22 Jan 2024 14:49:47 +0100 Subject: [PATCH] Mark defaultTargetPlatform as constant for non-debug non-web builds. (#141105) This PR adds the Dart VM `vm:platform-const-if` pragma introduced in https://github.com/dart-lang/sdk/commit/57a1168875 to the `defaultTargetPlatform` property, allowing it to be computed as if it was a constant field in non-debug AOT builds. In particular, this means that platform-specific code executed conditionally based on this property can be tree-shaken in release builds. Note that this PR changes `defaultTargetPlatform` to only allow overriding via `debugDefaultTargetPlatformOverride` in debug builds, and makes it so that compilation throws an error if code assigns to`debugDefaultTargetPlatformOverride` in other build modes. Related issue: #14233 ## Pre-launch Checklist - [X] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [X] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [X] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [X] I signed the [CLA]. - [X] I listed at least one issue that this PR fixes in the description above. - [X] I updated/added relevant documentation (doc comments with `///`). - [X] I added new tests to check the change I am making, or this PR is [test-exempt]. - [X] All existing and new tests are passing. --- .../lib/src/foundation/_platform_io.dart | 4 +++- .../flutter/lib/src/foundation/platform.dart | 22 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/flutter/lib/src/foundation/_platform_io.dart b/packages/flutter/lib/src/foundation/_platform_io.dart index d7750c08b20..7fd4f35ff7a 100644 --- a/packages/flutter/lib/src/foundation/_platform_io.dart +++ b/packages/flutter/lib/src/foundation/_platform_io.dart @@ -4,11 +4,13 @@ import 'dart:io'; import 'assertions.dart'; +import 'constants.dart'; import 'platform.dart' as platform; export 'platform.dart' show TargetPlatform; /// The dart:io implementation of [platform.defaultTargetPlatform]. +@pragma('vm:platform-const-if', !kDebugMode) platform.TargetPlatform get defaultTargetPlatform { platform.TargetPlatform? result; if (Platform.isAndroid) { @@ -30,7 +32,7 @@ platform.TargetPlatform get defaultTargetPlatform { } return true; }()); - if (platform.debugDefaultTargetPlatformOverride != null) { + if (kDebugMode && platform.debugDefaultTargetPlatformOverride != null) { result = platform.debugDefaultTargetPlatformOverride; } if (result == null) { diff --git a/packages/flutter/lib/src/foundation/platform.dart b/packages/flutter/lib/src/foundation/platform.dart index 60d90b22d77..b1905aea1a9 100644 --- a/packages/flutter/lib/src/foundation/platform.dart +++ b/packages/flutter/lib/src/foundation/platform.dart @@ -4,6 +4,8 @@ import '_platform_io.dart' if (dart.library.js_util) '_platform_web.dart' as platform; +import 'assertions.dart'; +import 'constants.dart'; /// The [TargetPlatform] that matches the platform on which the framework is /// currently executing. @@ -22,7 +24,7 @@ import '_platform_io.dart' /// originally written assuming Android-like behavior, and we added platform /// adaptations for iOS later). Tests can check iOS behavior by using the /// platform override APIs (such as [ThemeData.platform] in the material -/// library) or by setting [debugDefaultTargetPlatformOverride]. +/// library) or by setting [debugDefaultTargetPlatformOverride] in debug builds. /// /// Tests can also create specific platform tests by and adding a `variant:` /// argument to the test and using a [TargetPlatformVariant]. @@ -42,6 +44,7 @@ import '_platform_io.dart' // that would mean we'd be stuck with that platform forever emulating the other, // and we'd never be able to introduce dedicated behavior for that platform // (since doing so would be a big breaking change). +@pragma('vm:platform-const-if', !kDebugMode) TargetPlatform get defaultTargetPlatform => platform.defaultTargetPlatform; /// The platform that user interaction should adapt to target. @@ -76,7 +79,7 @@ enum TargetPlatform { windows, } -/// Override the [defaultTargetPlatform]. +/// Override the [defaultTargetPlatform] in debug builds. /// /// Setting this to null returns the [defaultTargetPlatform] to its original /// value (based on the actual current platform). @@ -94,5 +97,16 @@ enum TargetPlatform { /// certainly widgets to work assuming the presence of a system-wide back /// button, which will make those widgets unusable since iOS has no such button. /// -/// In general, therefore, this property should not be used in release builds. -TargetPlatform? debugDefaultTargetPlatformOverride; +/// Attempting to override this property in non-debug builds causes an error. +TargetPlatform? get debugDefaultTargetPlatformOverride => + _debugDefaultTargetPlatformOverride; + +set debugDefaultTargetPlatformOverride(TargetPlatform? value) { + if (!kDebugMode) { + throw FlutterError( + 'Cannot modify debugDefaultTargetPlatformOverride in non-debug builds.'); + } + _debugDefaultTargetPlatformOverride = value; +} + +TargetPlatform? _debugDefaultTargetPlatformOverride;