Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@yjbanov
Copy link
Contributor

@yjbanov yjbanov commented Nov 21, 2023

Implement multi-view for semantics. Main changes:

  • EngineSemanticsOwner singleton is split into two classes:
    • EngineSemantics is a singleton that manages global properties of the semantics tree, such as whether semantics is currently enabled, and what gesture mode is used.
    • EngineSemanticsOwner now supports creating multiple instances of the class. EngineFlutterView now points a EngineSemanticsOwner that it owns.
  • Fix a number of issues with disposal logic. Now that views can come in and out disposal has to be more robust than previously. EngineSemanticsOwner and SemanticsObject acquired a dispose() method that cleans up the tree and individual nodes respectively.
    • In particular, this fixes an issue in Skwasm mode where slight differences in asynchrony caused the semantics test to fail because old nodes continued firing events after they were removed from the document due to improper disposal.

@yjbanov yjbanov requested review from ditman and mdebbar November 21, 2023 00:06
@github-actions github-actions bot added the platform-web Code specifically for the web engine label Nov 21, 2023
''')
void updateSemantics(ui.SemanticsUpdate update) {
EngineSemanticsOwner.instance.updateSemantics(update);
implicitView?.semantics.updateSemantics(update);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point, we need the framework to pass a view parameter here, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the deprecation message above this method is going away forever.

Comment on lines 128 to 130
final Zone zone = Zone.current;
_scrollListener = createDomEventListener((_) {
_recomputeScrollPosition();
zone.run(_recomputeScrollPosition);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? If so, could you add a comment explaining why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! This was left-over from my experimentation. Will clean up.

for (int i = 0; i < len; i++) {
_detachObject(keys[i]);
for (final EngineFlutterView view in EnginePlatformDispatcher.instance.views) {
view.semantics.dispose();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if semantics is enabled again later? Is there a way to revive view.semantics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a production setting semantics is only enabled one-way; there's no going back. However, our tests do rely on being able to dispose of the old tree to set up a clean environment for the following tests, so the object is revivable after it is disposed. This is more like "reset" than it is "dispose". I'll rename it.

auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Nov 22, 2023
`FakeView` wraps the same underlying `FlutterView`. Sending semantics updates and Scene objects from multiple fake views into the same engine `FlutterView` violates contracts with the engine. This PR stubs out `render` and `updateSemantics` methods in `FakeView` classes to prevent that.

This unblocks flutter/engine#48251, which implements multi-view semantics for web.
@yjbanov yjbanov requested a review from mdebbar November 22, 2023 22:02
Copy link
Contributor

@mdebbar mdebbar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! But I'm not sure if we should keep the flt-view-id attribute. It doesn't seem to be used in any meaningful way in this PR. Do you have plans to use it in the future?

Comment on lines +55 to +56
expect(domDocument.querySelectorAll('flutter-view[flt-view-id="${view1.viewId}"]'), hasLength(1));
expect(domDocument.querySelectorAll('flutter-view[flt-view-id="${view2.viewId}"]'), hasLength(1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still unsure what the purpose of the flt-view-id attribute is. These checks seem to be equivalent to:

Suggested change
expect(domDocument.querySelectorAll('flutter-view[flt-view-id="${view1.viewId}"]'), hasLength(1));
expect(domDocument.querySelectorAll('flutter-view[flt-view-id="${view2.viewId}"]'), hasLength(1));
expect(view1.dom.rootElement.isConnected, isTrue);
expect(view2.dom.rootElement.isConnected, isTrue);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed offline, this attribute is useful for manual inspection, testing, etc. I left some docs about it.

Copy link
Member

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Comments are minor, and we can tweak/fix later.

bool _isDisposed = false;

void dispose() {
assert(!_isDisposed);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assert goes away at build time, should this also if (_isDisposed) return;? Or is this only expected to fail at dev time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. I'm just following an established convention. This pattern is used everywhere else. I'd be on board to revisit it, but that's probably outside the scope of this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely out of scope, I didn't realize this pattern was the standard :P

// Example:
//
// document.querySelector('flutter-view[flt-view-id="$viewId"]')
rootElement.setAttribute('flt-view-id', viewId);
Copy link
Member

@ditman ditman Nov 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The embedding strategy is setting most of the flt values in the hostElement:

// Initializes the embeddingStrategy so it can host a single-view Flutter app.
window.embeddingStrategy.initialize(
hostElementAttributes: <String, String>{
'flt-renderer': '${renderer.rendererTag} ($rendererSelection)',
'flt-build-mode': buildMode,
// TODO(mdebbar): Disable spellcheck until changes in the framework and
// engine are complete.
'spellcheck': 'false',
},
);

It is likely that this will eventually move there once it is made view-aware.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM. Feel free to move it around when the embedder becomes multi-view aware.

Comment on lines +23 to +30
// TODO(yjbanov): see https://github.com/flutter/flutter/issues/138906
// This test tests multi-view mode only, but currently there's
// no way to cleanly boot into pure multi-view mode. As a
// workaroud we boot into a mode that includes the implicit
// view, but we then remove the implicit view.
await bootstrapAndRunApp();
final EngineFlutterWindow implicitView = EnginePlatformDispatcher.instance.implicitView!;
EnginePlatformDispatcher.instance.viewManager.disposeAndUnregisterView(implicitView.viewId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mouad has landed the bit of code that disables the implicit view when multiViewEnabled is true. He's writing other tests for that, so he might be able to revisit this one!

@flutter-dashboard
Copy link

Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change).

If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review.

Changes reported for pull request #48251 at sha a8f95c6

@yjbanov
Copy link
Contributor Author

yjbanov commented Dec 1, 2023

Landing manually. The gold check seems to be a false alarm. It likely complains about existing non-triaged goldens in the engine repo, but the triage for this PR is empty (and it should be).

@yjbanov
Copy link
Contributor Author

yjbanov commented Dec 1, 2023

I'll still keep an eye on it after I merge.

engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 1, 2023
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Dec 1, 2023
…139388)

flutter/engine@69f0e55...95995c4

2023-12-01 [email protected] [web] Implement multi-view for semantics (flutter/engine#48251)
2023-12-01 [email protected] [Impeller] Fix size of squares in DrawPoints(PointMode). (flutter/engine#48547)
2023-12-01 [email protected] Roll Skia from ecf10008c8bd to 5849e2b1aa8f (2 revisions) (flutter/engine#48569)
2023-12-01 [email protected] Roll Skia from 0ed7f26b3adb to ecf10008c8bd (1 revision) (flutter/engine#48568)
2023-12-01 [email protected] Roll Skia from e69fbf086bb6 to 0ed7f26b3adb (1 revision) (flutter/engine#48565)
2023-12-01 [email protected] Roll Skia from 57c6a5a97dc5 to e69fbf086bb6 (1 revision) (flutter/engine#48562)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
caseycrogers pushed a commit to caseycrogers/flutter that referenced this pull request Dec 29, 2023
)

`FakeView` wraps the same underlying `FlutterView`. Sending semantics updates and Scene objects from multiple fake views into the same engine `FlutterView` violates contracts with the engine. This PR stubs out `render` and `updateSemantics` methods in `FakeView` classes to prevent that.

This unblocks flutter/engine#48251, which implements multi-view semantics for web.
caseycrogers pushed a commit to caseycrogers/flutter that referenced this pull request Dec 29, 2023
…lutter#139388)

flutter/engine@69f0e55...95995c4

2023-12-01 [email protected] [web] Implement multi-view for semantics (flutter/engine#48251)
2023-12-01 [email protected] [Impeller] Fix size of squares in DrawPoints(PointMode). (flutter/engine#48547)
2023-12-01 [email protected] Roll Skia from ecf10008c8bd to 5849e2b1aa8f (2 revisions) (flutter/engine#48569)
2023-12-01 [email protected] Roll Skia from 0ed7f26b3adb to ecf10008c8bd (1 revision) (flutter/engine#48568)
2023-12-01 [email protected] Roll Skia from e69fbf086bb6 to 0ed7f26b3adb (1 revision) (flutter/engine#48565)
2023-12-01 [email protected] Roll Skia from 57c6a5a97dc5 to e69fbf086bb6 (1 revision) (flutter/engine#48562)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

platform-web Code specifically for the web engine will affect goldens

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants