[web] JSConfig: Add multiViewEnabled value. (#47939)
This change:
* Adds a boolean to `multiViewEnabled`.
* Removes unused `canvasKitMaximumSurfaces` value.
Part of: https://github.com/flutter/flutter/issues/137377
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
diff --git a/lib/web_ui/lib/src/engine/configuration.dart b/lib/web_ui/lib/src/engine/configuration.dart
index d875686..e47f8ed 100644
--- a/lib/web_ui/lib/src/engine/configuration.dart
+++ b/lib/web_ui/lib/src/engine/configuration.dart
@@ -267,17 +267,6 @@
'FLUTTER_WEB_CANVASKIT_FORCE_CPU_ONLY',
);
- /// This is deprecated. The CanvasKit renderer will only ever create one
- /// WebGL context, obviating the problem this configuration was meant to
- /// solve originally.
- @Deprecated('Setting canvasKitMaximumSurfaces has no effect')
- int get canvasKitMaximumSurfaces =>
- _configuration?.canvasKitMaximumSurfaces?.toInt() ?? _defaultCanvasKitMaximumSurfaces;
- static const int _defaultCanvasKitMaximumSurfaces = int.fromEnvironment(
- 'FLUTTER_WEB_MAXIMUM_SURFACES',
- defaultValue: 8,
- );
-
/// Set this flag to `true` to cause the engine to visualize the semantics tree
/// on the screen for debugging.
///
@@ -298,6 +287,16 @@
/// to render, or `null` if the user hasn't specified anything.
DomElement? get hostElement => _configuration?.hostElement;
+ /// Sets Flutter Web in "multi-view" mode.
+ ///
+ /// Multi-view mode allows apps to:
+ ///
+ /// * Start without a `hostElement`.
+ /// * Add/remove views (`hostElements`) from JS while the application is running.
+ /// * ...
+ /// * PROFIT?
+ bool get multiViewEnabled => _configuration?.multiViewEnabled ?? false;
+
/// Returns a `nonce` to allowlist the inline styles that Flutter web needs.
///
/// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce
@@ -347,16 +346,16 @@
external JSBoolean? get _canvasKitForceCpuOnly;
bool? get canvasKitForceCpuOnly => _canvasKitForceCpuOnly?.toDart;
- @JS('canvasKitMaximumSurfaces')
- external JSNumber? get _canvasKitMaximumSurfaces;
- double? get canvasKitMaximumSurfaces => _canvasKitMaximumSurfaces?.toDartDouble;
-
@JS('debugShowSemanticsNodes')
external JSBoolean? get _debugShowSemanticsNodes;
bool? get debugShowSemanticsNodes => _debugShowSemanticsNodes?.toDart;
external DomElement? get hostElement;
+ @JS('multiViewEnabled')
+ external JSBoolean? get _multiViewEnabled;
+ bool? get multiViewEnabled => _multiViewEnabled?.toDart;
+
@JS('nonce')
external JSString? get _nonce;
String? get nonce => _nonce?.toDart;
diff --git a/lib/web_ui/test/canvaskit/initialization/stores_config_test.dart b/lib/web_ui/test/canvaskit/initialization/stores_config_test.dart
index b7869d9..e708471 100644
--- a/lib/web_ui/test/canvaskit/initialization/stores_config_test.dart
+++ b/lib/web_ui/test/canvaskit/initialization/stores_config_test.dart
@@ -15,12 +15,23 @@
group('initializeEngineServices', () {
test('stores user configuration', () async {
final JsFlutterConfiguration config = JsFlutterConfiguration();
- js_util.setProperty(config, 'canvasKitMaximumSurfaces', 32.0);
+ // `canvasKitBaseUrl` is required for the test to actually run.
js_util.setProperty(config, 'canvasKitBaseUrl', '/canvaskit/');
+ // A property under test, that we'll try to read later.
+ js_util.setProperty(config, 'nonce', 'some_nonce');
+ // A non-existing property to verify our js-interop doesn't crash.
+ js_util.setProperty(config, 'canvasKitMaximumSurfaces', 32.0);
+
+ // Remove window.flutterConfiguration (if it's there)
js_util.setProperty(domWindow, 'flutterConfiguration', null);
+
+ // TODO(web): Replace the above nullification by the following assertion
+ // when wasm and JS tests initialize their config the same way:
+ // assert(js_util.getProperty<Object?>(domWindow, 'flutterConfiguration') == null);
+
await initializeEngineServices(jsConfiguration: config);
- expect(configuration.canvasKitMaximumSurfaces, 32);
+ expect(configuration.nonce, 'some_nonce');
});
});
}
diff --git a/lib/web_ui/test/engine/configuration_test.dart b/lib/web_ui/test/engine/configuration_test.dart
index 7dc5aae..60eca6c 100644
--- a/lib/web_ui/test/engine/configuration_test.dart
+++ b/lib/web_ui/test/engine/configuration_test.dart
@@ -22,16 +22,16 @@
test('initializes with null', () async {
final FlutterConfiguration config = FlutterConfiguration.legacy(null);
- expect(config.canvasKitMaximumSurfaces, 8); // _defaultCanvasKitMaximumSurfaces
+ expect(config.canvasKitBaseUrl, 'canvaskit/'); // _defaultCanvasKitBaseUrl
});
test('legacy constructor initializes with a Js Object', () async {
final FlutterConfiguration config = FlutterConfiguration.legacy(
js_util.jsify(<String, Object?>{
- 'canvasKitMaximumSurfaces': 16,
+ 'canvasKitBaseUrl': 'some_other_url/',
}) as JsFlutterConfiguration);
- expect(config.canvasKitMaximumSurfaces, 16);
+ expect(config.canvasKitBaseUrl, 'some_other_url/');
});
});
@@ -39,13 +39,13 @@
test('throws assertion error if already initialized from JS', () async {
final FlutterConfiguration config = FlutterConfiguration.legacy(
js_util.jsify(<String, Object?>{
- 'canvasKitMaximumSurfaces': 12,
+ 'canvasKitBaseUrl': 'some_other_url/',
}) as JsFlutterConfiguration);
expect(() {
config.setUserConfiguration(
js_util.jsify(<String, Object?>{
- 'canvasKitMaximumSurfaces': 16,
+ 'canvasKitBaseUrl': 'yet_another_url/',
}) as JsFlutterConfiguration);
}, throwsAssertionError);
});
@@ -55,70 +55,98 @@
config.setUserConfiguration(
js_util.jsify(<String, Object?>{
- 'canvasKitMaximumSurfaces': 16,
+ 'canvasKitBaseUrl': 'one_more_url/',
}) as JsFlutterConfiguration);
- expect(config.canvasKitMaximumSurfaces, 16);
+ expect(config.canvasKitBaseUrl, 'one_more_url/');
+ });
+
+ test('can receive non-existing properties without crashing', () async {
+ final FlutterConfiguration config = FlutterConfiguration.legacy(null);
+
+ expect(() {
+ config.setUserConfiguration(
+ js_util.jsify(<String, Object?>{
+ 'canvasKitMaximumSurfaces': 32.0,
+ }) as JsFlutterConfiguration);
+ }, returnsNormally);
});
});
- group('CanvasKit config', () {
- test('default canvasKitVariant', () {
- final FlutterConfiguration config = FlutterConfiguration();
-
- expect(config.canvasKitVariant, CanvasKitVariant.auto);
- });
-
- test('default canvasKitVariant when it is undefined', () {
- final FlutterConfiguration config = FlutterConfiguration();
- config.setUserConfiguration(
- // With an empty map, the canvasKitVariant is undefined in JS.
+ group('Default configuration values', () {
+ late FlutterConfiguration defaultConfig;
+ setUp(() {
+ defaultConfig = FlutterConfiguration();
+ defaultConfig.setUserConfiguration(
js_util.jsify(<String, Object?>{}) as JsFlutterConfiguration,
);
-
- expect(config.canvasKitVariant, CanvasKitVariant.auto);
});
- test('validates canvasKitVariant', () {
- final FlutterConfiguration config = FlutterConfiguration();
-
- config.setUserConfiguration(
- js_util.jsify(<String, Object?>{'canvasKitVariant': 'foo'}) as JsFlutterConfiguration,
- );
- expect(() => config.canvasKitVariant, throwsArgumentError);
-
- config.setUserConfiguration(
- js_util.jsify(<String, Object?>{'canvasKitVariant': 'auto'}) as JsFlutterConfiguration,
- );
- expect(config.canvasKitVariant, CanvasKitVariant.auto);
-
- config.setUserConfiguration(
- js_util.jsify(<String, Object?>{'canvasKitVariant': 'full'}) as JsFlutterConfiguration,
- );
- expect(config.canvasKitVariant, CanvasKitVariant.full);
-
- config.setUserConfiguration(
- js_util.jsify(<String, Object?>{'canvasKitVariant': 'chromium'}) as JsFlutterConfiguration,
- );
- expect(config.canvasKitVariant, CanvasKitVariant.chromium);
+ test('canvasKitVariant', () {
+ expect(defaultConfig.canvasKitVariant, CanvasKitVariant.auto);
});
+
+ test('useColorEmoji', () {
+ expect(defaultConfig.useColorEmoji, isFalse);
+ });
+
+ test('multiViewEnabled', () {
+ expect(defaultConfig.multiViewEnabled, isFalse);
+ });
+
});
- group('useColorEmoji', () {
- test('defaults to false', () {
- final FlutterConfiguration config = FlutterConfiguration();
- config.setUserConfiguration(
- js_util.jsify(<String, Object?>{}) as JsFlutterConfiguration,
- );
- expect(config.useColorEmoji, isFalse);
+ group('setUserConfiguration (values)', () {
+ group('canvasKitVariant', () {
+ test('value undefined - defaults to "auto"', () {
+ final FlutterConfiguration config = FlutterConfiguration();
+ config.setUserConfiguration(
+ // With an empty map, the canvasKitVariant is undefined in JS.
+ js_util.jsify(<String, Object?>{}) as JsFlutterConfiguration,
+ );
+
+ expect(config.canvasKitVariant, CanvasKitVariant.auto);
+ });
+
+ test('value - converts to CanvasKitVariant enum (or throw)', () {
+ final FlutterConfiguration config = FlutterConfiguration();
+
+ config.setUserConfiguration(
+ js_util.jsify(<String, Object?>{'canvasKitVariant': 'foo'}) as JsFlutterConfiguration,
+ );
+ expect(() => config.canvasKitVariant, throwsArgumentError);
+
+ config.setUserConfiguration(
+ js_util.jsify(<String, Object?>{'canvasKitVariant': 'auto'}) as JsFlutterConfiguration,
+ );
+ expect(config.canvasKitVariant, CanvasKitVariant.auto);
+
+ config.setUserConfiguration(
+ js_util.jsify(<String, Object?>{'canvasKitVariant': 'full'}) as JsFlutterConfiguration,
+ );
+ expect(config.canvasKitVariant, CanvasKitVariant.full);
+
+ config.setUserConfiguration(
+ js_util.jsify(<String, Object?>{'canvasKitVariant': 'chromium'}) as JsFlutterConfiguration,
+ );
+ expect(config.canvasKitVariant, CanvasKitVariant.chromium);
+ });
});
- test('can be set to true', () {
+ test('useColorEmoji', () {
final FlutterConfiguration config = FlutterConfiguration();
config.setUserConfiguration(
js_util.jsify(<String, Object?>{'useColorEmoji': true}) as JsFlutterConfiguration,
);
expect(config.useColorEmoji, isTrue);
});
+
+ test('multiViewEnabled', () {
+ final FlutterConfiguration config = FlutterConfiguration();
+ config.setUserConfiguration(
+ js_util.jsify(<String, Object?>{'multiViewEnabled': true}) as JsFlutterConfiguration,
+ );
+ expect(config.multiViewEnabled, isTrue);
+ });
});
}