Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3a65990
Add wasm opt-in setting
kenzieschmoll Aug 28, 2024
407eea6
fixes
kenzieschmoll Aug 28, 2024
9dba649
clean up
kenzieschmoll Aug 29, 2024
be44066
Add feature flag
kenzieschmoll Aug 29, 2024
40a7c39
Merge branch 'master' of github.com:flutter/devtools into wasm-opt-in
kenzieschmoll Aug 29, 2024
d784128
checkpoint
kenzieschmoll Aug 29, 2024
7325e0d
Merge branch 'master' of github.com:flutter/devtools into wasm-opt-in
kenzieschmoll Sep 6, 2024
f98f771
Update flutter_bootstrap.js
kenzieschmoll Sep 6, 2024
7eaa6d4
bootstrap
kenzieschmoll Sep 6, 2024
0f1fe62
bootstrap cleanup
kenzieschmoll Sep 9, 2024
ae0642b
Merge branch 'master' of github.com:flutter/devtools into wasm-opt-in
kenzieschmoll Sep 9, 2024
99800eb
fix dialog header
kenzieschmoll Sep 9, 2024
c30a1df
lints
kenzieschmoll Sep 9, 2024
9dbfba6
Merge branch 'master' of github.com:flutter/devtools into wasm-opt-in
kenzieschmoll Sep 9, 2024
91564ba
checkpoint
kenzieschmoll Sep 9, 2024
fe436fb
todo
kenzieschmoll Sep 9, 2024
d77e8ca
flags
kenzieschmoll Sep 9, 2024
1318b8e
remove prints
kenzieschmoll Sep 9, 2024
ed1f77d
analytics
kenzieschmoll Sep 10, 2024
5857f27
revert this
kenzieschmoll Sep 10, 2024
25eb19a
Merge branch 'master' of github.com:flutter/devtools into wasm-opt-in
kenzieschmoll Sep 10, 2024
e4f217e
Suppress notification in VS Code
kenzieschmoll Sep 10, 2024
aff0e10
Merge branch 'master' of github.com:flutter/devtools into wasm-opt-in
kenzieschmoll Sep 10, 2024
991218a
revert stuff
kenzieschmoll Sep 10, 2024
e738552
query param fix
kenzieschmoll Sep 10, 2024
16398de
fix rnotes
kenzieschmoll Sep 10, 2024
985a1d9
enable feature flag
kenzieschmoll Sep 10, 2024
ca2b7af
fix test
kenzieschmoll Sep 10, 2024
a63956a
Merge branch 'master' of github.com:flutter/devtools into wasm-opt-in
kenzieschmoll Sep 11, 2024
b247b5e
bootstrap changes
kenzieschmoll Sep 11, 2024
8c3c798
remove print
kenzieschmoll Sep 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ void setupErrorHandling(Future Function() appStartCallback) {
return appStartCallback();
},
(Object error, StackTrace stack) {
// TODO(https://github.com/flutter/devtools/issues/7856): can we detect
// severe errors here that are related to dart2wasm? Otherwise we may
// crash DevTools for the user without any way for them to force reload
// with JS.
reportError(error, stack: stack, errorType: 'zoneGuarded');
throw error;
},
Expand Down
7 changes: 5 additions & 2 deletions packages/devtools_app/lib/src/framework/framework_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:devtools_app_shared/ui.dart';
import 'package:devtools_app_shared/utils.dart';
import 'package:devtools_shared/devtools_shared.dart';
import 'package:devtools_shared/service.dart';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
import 'package:vm_service/vm_service.dart';

Expand Down Expand Up @@ -46,8 +47,10 @@ abstract class FrameworkCore {

await initializePlatform();

// Print the version number at startup.
_log.info('DevTools version $devToolsVersion.');
// Print DevTools info at startup.
_log.info(
'Version: $devToolsVersion, Renderer: ${kIsWasm ? 'skwasm' : 'canvaskit'}',
);

await _initDTDConnection();

Expand Down
26 changes: 25 additions & 1 deletion packages/devtools_app/lib/src/framework/settings_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import '../shared/analytics/analytics_controller.dart';
import '../shared/analytics/constants.dart' as gac;
import '../shared/common_widgets.dart';
import '../shared/config_specific/copy_to_clipboard/copy_to_clipboard.dart';
import '../shared/feature_flags.dart';
import '../shared/globals.dart';
import '../shared/log_storage.dart';
import '../shared/server/server.dart';
Expand All @@ -37,6 +38,7 @@ class SettingsDialog extends StatelessWidget {

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final analyticsController = Provider.of<AnalyticsController>(context);
return DevToolsDialog(
title: const DialogTitleText('Settings'),
Expand All @@ -50,6 +52,7 @@ class SettingsDialog extends StatelessWidget {
title: 'Use a dark theme',
notifier: preferences.darkModeEnabled,
onChanged: preferences.toggleDarkModeTheme,
gaScreen: gac.settingsDialog,
gaItem: gac.darkTheme,
),
),
Expand All @@ -61,6 +64,7 @@ class SettingsDialog extends StatelessWidget {
onChanged: (enable) => unawaited(
analyticsController.toggleAnalyticsEnabled(enable),
),
gaScreen: gac.settingsDialog,
gaItem: gac.analytics,
),
),
Expand All @@ -69,10 +73,29 @@ class SettingsDialog extends StatelessWidget {
title: 'Enable VM developer mode',
notifier: preferences.vmDeveloperModeEnabled,
onChanged: preferences.toggleVmDeveloperMode,
gaScreen: gac.settingsDialog,
gaItem: gac.vmDeveloperMode,
),
),
const PaddedDivider(),
if (FeatureFlags.wasmOptInSetting) ...[
const SizedBox(height: largeSpacing),
...dialogSubHeader(theme, 'Experimental features'),
Flexible(
child: CheckboxSetting(
title: 'Enable WebAssembly',
description:
'This will trigger a reload of the page to load DevTools '
'compiled with WebAssembly. This may yield better '
'performance.',
notifier: preferences.wasmEnabled,
onChanged: preferences.toggleWasmEnabled,
gaScreen: gac.settingsDialog,
gaItem: gac.wasm,
),
),
],
const SizedBox(height: largeSpacing),
...dialogSubHeader(theme, 'Troubleshooting'),
const _VerboseLoggingSetting(),
],
),
Expand All @@ -99,6 +122,7 @@ class _VerboseLoggingSetting extends StatelessWidget {
title: 'Enable verbose logging',
notifier: preferences.verboseLoggingEnabled,
onChanged: (enable) => preferences.toggleVerboseLogging(enable),
gaScreen: gac.settingsDialog,
gaItem: gac.verboseLogging,
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ const devToolsMain = 'main';
const appDisconnected = 'appDisconnected';
const init = 'init';

/// Event that signals we fell back to JS when trying to load DevTools with
/// Wasm.
const jsFallback = 'jsFallback';

// DevTools UI action selected (clicked).

// Main bar UX actions:
Expand Down Expand Up @@ -114,6 +118,7 @@ const settingsDialog = 'settings';
const darkTheme = 'darkTheme';
const analytics = 'analytics';
const vmDeveloperMode = 'vmDeveloperMode';
const wasm = 'wasm';
const verboseLogging = 'verboseLogging';
const inspectorHoverEvalMode = 'inspectorHoverEvalMode';
const clearLogs = 'clearLogs';
Expand Down
2 changes: 1 addition & 1 deletion packages/devtools_app/lib/src/shared/common_widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1557,7 +1557,7 @@ class CheckboxSetting extends StatelessWidget {
final gaScreen = this.gaScreen;
final gaItem = this.gaItem;
if (gaScreen != null && gaItem != null) {
ga.select(gaScreen, gaItem);
ga.select(gaScreen, '$gaItem-$value');
}
final onChanged = this.onChanged;
if (onChanged != null) {
Expand Down
12 changes: 9 additions & 3 deletions packages/devtools_app/lib/src/shared/feature_flags.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,23 @@ abstract class FeatureFlags {
/// https://github.com/flutter/devtools/issues/7854
static bool inspectorV2 = enableExperiments;

/// Flag to enable the DevTools setting to opt-in to WASM.
///
/// https://github.com/flutter/devtools/issues/7856
static bool wasmOptInSetting = true;

/// Stores a map of all the feature flags for debugging purposes.
///
/// When adding a new flag, you are responsible for adding it to this map as
/// well.
static final _allFlags = <String, bool>{
'widgetRebuildStats': widgetRebuildStats,
'memoryOffline': memoryDisconnectExperience,
'dapDebugging': dapDebugging,
'loggingV2': loggingV2,
'memorySaveLoad': memorySaveLoad,
'deepLinkIosCheck': deepLinkIosCheck,
'loggingV2': loggingV2,
'dapDebugging': dapDebugging,
'inspectorV2': inspectorV2,
'wasmOptInSetting': wasmOptInSetting,
};

/// A helper to print the status of all the feature flags.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import '../analytics/constants.dart' as gac;
import '../config_specific/logger/logger_helpers.dart';
import '../constants.dart';
import '../diagnostics/inspector_service.dart';
import '../feature_flags.dart';
import '../globals.dart';
import '../query_parameters.dart';
import '../utils.dart';

part '_extension_preferences.dart';
Expand All @@ -25,8 +27,19 @@ part '_memory_preferences.dart';
part '_logging_preferences.dart';
part '_performance_preferences.dart';

final _log = Logger('PreferencesController');

const _thirdPartyPathSegment = 'third_party';

/// DevTools preferences for experimental features.
enum _ExperimentPreferences {
wasm;

String get storageKey => '$storagePrefix.$name';

static const storagePrefix = 'experiment';
}

/// DevTools preferences for UI-related settings.
enum _UiPreferences {
darkMode,
Expand Down Expand Up @@ -59,6 +72,10 @@ class PreferencesController extends DisposableController

final vmDeveloperModeEnabled = ValueNotifier<bool>(false);

/// Whether DevTools should loaded with the dart2wasm + skwasm instead of
/// dart2js + canvaskit
final wasmEnabled = ValueNotifier<bool>(false);

final verboseLoggingEnabled =
ValueNotifier<bool>(Logger.root.level == verboseLoggingLevel);

Expand All @@ -83,6 +100,9 @@ class PreferencesController extends DisposableController
// Get the current values and listen for and write back changes.
await _initDarkMode();
await _initVmDeveloperMode();
if (FeatureFlags.wasmOptInSetting) {
await _initWasmEnabled();
}
await _initVerboseLogging();

await inspector.init();
Expand Down Expand Up @@ -123,6 +143,70 @@ class PreferencesController extends DisposableController
});
}

Future<void> _initWasmEnabled() async {
wasmEnabled.value = kIsWasm;
addAutoDisposeListener(wasmEnabled, () async {
final enabled = wasmEnabled.value;
_log.fine('preference update (wasmEnabled = $enabled)');

await storage.setValue(
_ExperimentPreferences.wasm.storageKey,
'$enabled',
);

// Update the wasm mode query parameter if it does not match the value of
// the setting.
final wasmEnabledFromQueryParams = DevToolsQueryParams.load().useWasm;
if (wasmEnabledFromQueryParams != enabled) {
_log.fine(
'Reloading DevTools for Wasm preference update (enabled = $enabled)',
);
updateQueryParameter(
DevToolsQueryParams.wasmKey,
enabled ? 'true' : null,
reload: true,
);
}
});

final enabledFromStorage = await boolValueFromStorage(
_ExperimentPreferences.wasm.storageKey,
defaultsTo: false,
);
final queryParams = DevToolsQueryParams.load();
final enabledFromQueryParams = queryParams.useWasm;

if (enabledFromQueryParams && !kIsWasm) {
// If we hit this case, we tried to load DevTools with WASM but we fell
// back to JS. We know this because the flutter_bootstrap.js logic always
// sets the 'wasm' query parameter to 'true' when attempting to load
// DevTools with wasm. Remove the wasm query parameter and return early.
updateQueryParameter(DevToolsQueryParams.wasmKey, null);
ga.impression(gac.devToolsMain, gac.jsFallback);

// Do not show the JS fallback notification when embedded in VS Code
// because we do not expect the WASM build to load successfully by
// default. This is because cross-origin-isolation is disabled by VS
// Code. See https://github.com/microsoft/vscode/issues/186614.
final embeddedInVsCode =
queryParams.embedMode.embedded && queryParams.ide == 'VSCode';
if (!embeddedInVsCode) {
notificationService.push(
'Something went wrong when trying to load DevTools with WebAssembly. '
'Falling back to Javascript.',
);
}
return;
}

final shouldEnableWasm = enabledFromStorage || enabledFromQueryParams;
assert(kIsWasm == shouldEnableWasm);
// This should be a no-op if the flutter_bootstrap.js logic set the
// renderer properly, but we call this to be safe in case something went
// wrong.
toggleWasmEnabled(shouldEnableWasm);
}

Future<void> _initVerboseLogging() async {
final verboseLoggingEnabledValue = await boolValueFromStorage(
_GeneralPreferences.verboseLogging.name,
Expand Down Expand Up @@ -162,6 +246,13 @@ class PreferencesController extends DisposableController
}
}

/// Change the value of the wasm mode setting.
void toggleWasmEnabled(bool? enable) {
if (enable != null) {
wasmEnabled.value = enable;
}
}

void toggleVerboseLogging(bool? enableVerboseLogging) {
if (enableVerboseLogging != null) {
verboseLoggingEnabled.value = enableVerboseLogging;
Expand Down
9 changes: 9 additions & 0 deletions packages/devtools_app/lib/src/shared/query_parameters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ extension type DevToolsQueryParams(Map<String, String?> params) {
/// The current [EmbedMode] of DevTools based on the query parameters.
EmbedMode get embedMode => ideThemeParams.embedMode;

/// Whether DevTools should be loaded using dart2wasm + skwasm instead of
/// dart2js + canvaskit.
bool get useWasm => params[wasmKey] == 'true';

static const vmServiceUriKey = 'uri';
static const hideScreensKey = 'hide';
static const hideExtensionsValue = 'extensions';
Expand All @@ -71,6 +75,11 @@ extension type DevToolsQueryParams(Map<String, String?> params) {
static const ideKey = 'ide';
static const ideFeatureKey = 'ideFeature';

// This query parameter must match the String value in the Flutter bootstrap
// logic that is used to select a web renderer. See
// devtools/packages/devtools_app/web/flutter_bootstrap.js.
static const wasmKey = 'wasm';

// TODO(kenz): remove legacy value in May of 2025 when all IDEs are not using
// these and 12 months have passed to allow users ample upgrade time.
String? get legacyPage => params[legacyPageKey];
Expand Down
5 changes: 5 additions & 0 deletions packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ To learn more about DevTools, check out the
* Fixed a bug that was causing the DevTools release notes to always
show. - [#8277](https://github.com/flutter/devtools/pull/8277)

* Add a setting that allows users to opt-in to loading DevTools
with WebAssembly. - [#8270](https://github.com/flutter/devtools/pull/8270)

![Wasm opt-in setting](images/wasm_setting.png "DevTools setting to opt into wasm.")

## Inspector updates

TODO: Remove this section if there are not any general updates.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,11 @@ void main() {
expect(enableExperiments, false);
expect(enableBeta, false);
expect(isExternalBuild, true);
expect(FeatureFlags.memorySaveLoad, false);
expect(FeatureFlags.deepLinkIosCheck, false);
expect(FeatureFlags.loggingV2, false);
expect(FeatureFlags.dapDebugging, false);
expect(FeatureFlags.inspectorV2, false);
expect(FeatureFlags.wasmOptInSetting, true);
});
}
Loading