Skip to content

Commit f62ac70

Browse files
authored
Add compiler=js escape hatch to revert to dart2js compilation (#9406)
1 parent 234849f commit f62ac70

File tree

4 files changed

+55
-18
lines changed

4 files changed

+55
-18
lines changed

packages/devtools_app/benchmark/test_infra/common.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
/// found" in DevTools.
1111
const _benchmarkInitialPage = '';
1212

13-
const _wasmQueryParameters = {'wasm': 'true'};
13+
const _wasmQueryParameters = {'compiler': 'wasm'};
1414

1515
String benchmarkPath({required bool useWasm}) => Uri(
1616
path: _benchmarkInitialPage,

packages/devtools_app/lib/src/shared/preferences/preferences.dart

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,16 @@ class PreferencesController extends DisposableController
171171

172172
Future<void> _initWasmEnabled() async {
173173
wasmEnabled.value = kIsWasm;
174+
175+
// If the user forced the dart2js-compiled DevTools via query parameter,
176+
// then set the storage value to match. This will persist across multiple
177+
// sessions of DevTools.
178+
if (DevToolsQueryParams.load().useJs) {
179+
safeUnawaited(
180+
storage.setValue(_ExperimentPreferences.wasm.storageKey, 'false'),
181+
);
182+
}
183+
174184
addAutoDisposeListener(wasmEnabled, () async {
175185
final enabled = wasmEnabled.value;
176186
_log.fine('preference update (wasmEnabled = $enabled)');
@@ -188,8 +198,8 @@ class PreferencesController extends DisposableController
188198
'Reloading DevTools for Wasm preference update (enabled = $enabled)',
189199
);
190200
updateQueryParameter(
191-
DevToolsQueryParams.wasmKey,
192-
enabled ? 'true' : null,
201+
DevToolsQueryParams.compilerKey,
202+
enabled ? 'wasm' : null,
193203
reload: true,
194204
);
195205
}
@@ -207,7 +217,7 @@ class PreferencesController extends DisposableController
207217
// back to JS. We know this because the flutter_bootstrap.js logic always
208218
// sets the 'wasm' query parameter to 'true' when attempting to load
209219
// DevTools with wasm. Remove the wasm query parameter and return early.
210-
updateQueryParameter(DevToolsQueryParams.wasmKey, null);
220+
updateQueryParameter(DevToolsQueryParams.compilerKey, null);
211221
ga.impression(gac.devToolsMain, gac.jsFallback);
212222

213223
// Do not show the JS fallback notification when embedded in VS Code

packages/devtools_app/lib/src/shared/primitives/query_parameters.dart

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,14 @@ extension type DevToolsQueryParams(Map<String, String?> params) {
6464

6565
/// Whether DevTools should be loaded using dart2wasm + skwasm instead of
6666
/// dart2js + canvaskit.
67-
bool get useWasm => params[wasmKey] == 'true';
67+
bool get useWasm => params[compilerKey] == 'wasm';
68+
69+
/// Whether DevTools should be loaded using dart2js + canvaskit instead of
70+
/// dart2wasm + skwasm.
71+
///
72+
/// This should only ever be explicitly set by the user if their app fails to
73+
/// load using wasm.
74+
bool get useJs => params[compilerKey] == 'js';
6875

6976
static const vmServiceUriKey = 'uri';
7077
static const hideScreensKey = 'hide';
@@ -75,10 +82,14 @@ extension type DevToolsQueryParams(Map<String, String?> params) {
7582
static const ideKey = 'ide';
7683
static const ideFeatureKey = 'ideFeature';
7784

78-
// This query parameter must match the String value in the Flutter bootstrap
79-
// logic that is used to select a web renderer. See
80-
// devtools/packages/devtools_app/web/flutter_bootstrap.js.
81-
static const wasmKey = 'wasm';
85+
/// Query parameter key to determine whether to use dart2wasm or dart2js.
86+
///
87+
/// This query parameter must match the String value in the Flutter bootstrap
88+
/// logic that is used to select a web renderer. See
89+
/// devtools/packages/devtools_app/web/flutter_bootstrap.js.
90+
///
91+
/// Valid values are "js" or "wasm".
92+
static const compilerKey = 'compiler';
8293

8394
// TODO(kenz): remove legacy value in May of 2025 when all IDEs are not using
8495
// these and 12 months have passed to allow users ample upgrade time.

packages/devtools_app/web/flutter_bootstrap.js

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,15 @@ function unregisterDevToolsServiceWorker() {
2222
}
2323

2424
// This query parameter must match the String value specified by
25-
// `DevToolsQueryParameters.wasmKey`. See
25+
// `DevToolsQueryParameters.compilerKey`. See
2626
// devtools/packages/devtools_app/lib/src/shared/query_parameters.dart
27-
const wasmQueryParameterKey = 'wasm';
27+
const compilerQueryParameterKey = 'compiler';
28+
29+
// Returns the value for the given search param.
30+
function getSearchParam(searchParamKey) {
31+
const searchParams = new URLSearchParams(window.location.search);
32+
return searchParams.get(searchParamKey);
33+
}
2834

2935
// Calls the DevTools server API to read the user's wasm preference.
3036
async function getDevToolsWasmPreference() {
@@ -49,12 +55,20 @@ async function getDevToolsWasmPreference() {
4955
}
5056
}
5157

58+
// The query parameter compiler=js gives us an escape hatch we can offer users if their
59+
// dart2wasm app fails to load.
60+
const forceUseJs = () => getSearchParam(compilerQueryParameterKey) === 'js';
61+
5262
// Returns whether DevTools should be loaded with the skwasm renderer based on the
5363
// value of the 'wasm' query parameter or the wasm setting from the DevTools
5464
// preference file.
5565
async function shouldUseSkwasm() {
56-
const searchParams = new URLSearchParams(window.location.search);
57-
const wasmEnabledFromQueryParameter = searchParams.get(wasmQueryParameterKey) === 'true';
66+
// If dart2js has specifically been requested via query parameter, then do not try to
67+
// use skwasm (even if the local setting is for wasm).
68+
if (forceUseJs()) {
69+
return false;
70+
}
71+
const wasmEnabledFromQueryParameter = getSearchParam(compilerQueryParameterKey) === 'wasm';
5872
const wasmEnabledFromDevToolsPreference = await getDevToolsWasmPreference();
5973
return wasmEnabledFromQueryParameter === true || wasmEnabledFromDevToolsPreference === true;
6074
}
@@ -64,9 +78,9 @@ async function shouldUseSkwasm() {
6478
function updateWasmQueryParameter(useSkwasm) {
6579
const url = new URL(window.location.href);
6680
if (useSkwasm) {
67-
url.searchParams.set(wasmQueryParameterKey, 'true');
81+
url.searchParams.set(compilerQueryParameterKey, 'wasm');
6882
} else {
69-
url.searchParams.delete(wasmQueryParameterKey);
83+
url.searchParams.delete(compilerQueryParameterKey);
7084
}
7185
// Update the browser's history without reloading. This is a no-op if the wasm
7286
// query parameter does not actually need to be updated.
@@ -77,9 +91,11 @@ function updateWasmQueryParameter(useSkwasm) {
7791
async function bootstrapAppFor3P() {
7892
const useSkwasm = await shouldUseSkwasm();
7993

80-
// Ensure the 'wasm' query parameter in the URL is accurate for the renderer
81-
// DevTools will be loaded with.
82-
updateWasmQueryParameter(useSkwasm);
94+
if (!forceUseJs()) {
95+
// Ensure the 'wasm' query parameter in the URL is accurate for the renderer
96+
// DevTools will be loaded with.
97+
updateWasmQueryParameter(useSkwasm);
98+
}
8399

84100
const rendererForLog = useSkwasm ? 'skwasm' : 'canvaskit';
85101
console.log('Attempting to load DevTools with ' + rendererForLog + ' renderer.');

0 commit comments

Comments
 (0)