Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[html] HTML renderer fails on test with addRetained with clip #155717

Closed
harryterkelsen opened this issue Sep 25, 2024 · 1 comment
Closed

[html] HTML renderer fails on test with addRetained with clip #155717

harryterkelsen opened this issue Sep 25, 2024 · 1 comment
Labels
e: web_html HTML rendering backend for Web P3 Issues that are less important to the Flutter project platform-web Web applications specifically team-web Owned by Web platform team triaged-web Triaged by Web platform team

Comments

@harryterkelsen
Copy link
Contributor

harryterkelsen commented Sep 25, 2024

Steps to reproduce

flutter/engine#55402 introduces a test for the case when addRetained is used on a layer with pictures which are clipped in one frame and visible in a later frame.

    test('picture clipped but scrolls back in', () async {
      // Frame 1: Clip out the right circle
      final ui.SceneBuilder sceneBuilder = ui.SceneBuilder();
      sceneBuilder.pushClipRect(const ui.Rect.fromLTRB(0, 0, 125, 300));
      // Save this offsetLayer to add back in so we are using the same
      // picture layers on the next scene.
      final ui.OffsetEngineLayer offsetLayer = sceneBuilder.pushOffset(0, 0);
      sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) {
        canvas.drawCircle(const ui.Offset(50, 150), 50,
            ui.Paint()..color = const ui.Color(0xFFFF0000));
      }));
      sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) {
        canvas.drawCircle(const ui.Offset(200, 150), 50,
            ui.Paint()..color = const ui.Color(0xFFFF0000));
      }));
      sceneBuilder.pop();
      sceneBuilder.pop();
      await renderScene(sceneBuilder.build());

      // Frame 2: Clip out the left circle
      final ui.SceneBuilder sceneBuilder2 = ui.SceneBuilder();
      sceneBuilder2.pushClipRect(const ui.Rect.fromLTRB(150, 0, 300, 300));
      sceneBuilder2.addRetained(offsetLayer);
      sceneBuilder2.pop();
      sceneBuilder2.pop();
      await renderScene(sceneBuilder2.build());

      // Frame 3: Clip out the right circle again
      final ui.SceneBuilder sceneBuilder3 = ui.SceneBuilder();
      sceneBuilder3.pushClipRect(const ui.Rect.fromLTRB(0, 0, 125, 300));
      sceneBuilder3.addRetained(offsetLayer);
      sceneBuilder3.pop();
      sceneBuilder3.pop();
      await renderScene(sceneBuilder3.build());

      await matchGoldenFile(
          'scene_builder_picture_clipped_out_then_clipped_in.png',
          region: region);
    });

Expected results

The test should pass and the screenshot should show the red circle on the left (the red circle on the right is clipped out).

Actual results

The HTML renderer crashes on this test with this stack trace:

00:40 +117 ~23 -1: scene_builder_test.dart: SceneBuilder picture clipped but scrolls back in [E]                                                                                                       
  Bad state: No element
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/js_helper.dart 1209:19      Object.wrapException
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/js_array.dart 448:5         JavaScriptObject.first
  ../../../../flutter/lib/web_ui/lib/src/engine/html/scene_builder.dart 42:26  SurfaceSceneBuilder._persistedScene
  ../../../../flutter/lib/web_ui/lib/src/engine/html/scene_builder.dart 485:7  SurfaceSceneBuilder.build.<fn>
  ../../../../flutter/lib/web_ui/lib/src/engine/profiler.dart 44:12            Object.timeAction
  ../../../../flutter/lib/web_ui/lib/src/engine/html/scene_builder.dart 480:5  SurfaceSceneBuilder.build
  ../../../../flutter/lib/web_ui/test/ui/scene_builder_test.dart 363:25        <fn>
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/async_patch.dart 311:19     _wrapJsFunctionForAsync.closure.$protected
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/async_patch.dart 336:23     _wrapJsFunctionForAsync.<fn>
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/async_patch.dart 287:19     _awaitOnObject.<fn>

Code sample

  test('picture clipped but scrolls back in', () async {
      // Frame 1: Clip out the right circle
      final ui.SceneBuilder sceneBuilder = ui.SceneBuilder();
      sceneBuilder.pushClipRect(const ui.Rect.fromLTRB(0, 0, 125, 300));
      // Save this offsetLayer to add back in so we are using the same
      // picture layers on the next scene.
      final ui.OffsetEngineLayer offsetLayer = sceneBuilder.pushOffset(0, 0);
      sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) {
        canvas.drawCircle(const ui.Offset(50, 150), 50,
            ui.Paint()..color = const ui.Color(0xFFFF0000));
      }));
      sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) {
        canvas.drawCircle(const ui.Offset(200, 150), 50,
            ui.Paint()..color = const ui.Color(0xFFFF0000));
      }));
      sceneBuilder.pop();
      sceneBuilder.pop();
      await renderScene(sceneBuilder.build());

      // Frame 2: Clip out the left circle
      final ui.SceneBuilder sceneBuilder2 = ui.SceneBuilder();
      sceneBuilder2.pushClipRect(const ui.Rect.fromLTRB(150, 0, 300, 300));
      sceneBuilder2.addRetained(offsetLayer);
      sceneBuilder2.pop();
      sceneBuilder2.pop();
      await renderScene(sceneBuilder2.build());

      // Frame 3: Clip out the right circle again
      final ui.SceneBuilder sceneBuilder3 = ui.SceneBuilder();
      sceneBuilder3.pushClipRect(const ui.Rect.fromLTRB(0, 0, 125, 300));
      sceneBuilder3.addRetained(offsetLayer);
      sceneBuilder3.pop();
      sceneBuilder3.pop();
      await renderScene(sceneBuilder3.build());

      await matchGoldenFile(
          'scene_builder_picture_clipped_out_then_clipped_in.png',
          region: region);
    });

Screenshots or Video

No response

Logs

00:40 +117 ~23 -1: scene_builder_test.dart: SceneBuilder picture clipped but scrolls back in [E]                                                                                                       
  Bad state: No element
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/js_helper.dart 1209:19      Object.wrapException
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/js_array.dart 448:5         JavaScriptObject.first
  ../../../../flutter/lib/web_ui/lib/src/engine/html/scene_builder.dart 42:26  SurfaceSceneBuilder._persistedScene
  ../../../../flutter/lib/web_ui/lib/src/engine/html/scene_builder.dart 485:7  SurfaceSceneBuilder.build.<fn>
  ../../../../flutter/lib/web_ui/lib/src/engine/profiler.dart 44:12            Object.timeAction
  ../../../../flutter/lib/web_ui/lib/src/engine/html/scene_builder.dart 480:5  SurfaceSceneBuilder.build
  ../../../../flutter/lib/web_ui/test/ui/scene_builder_test.dart 363:25        <fn>
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/async_patch.dart 311:19     _wrapJsFunctionForAsync.closure.$protected
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/async_patch.dart 336:23     _wrapJsFunctionForAsync.<fn>
  org-dartlang-sdk:///lib/_internal/js_runtime/lib/async_patch.dart 287:19     _awaitOnObject.<fn>

Flutter Doctor output

❯ flutter doctor -v
[✓] Flutter (Channel main, 3.26.0-1.0.pre.193, on Debian GNU/Linux rodete 6.9.10-1rodete5-amd64, locale en_US.UTF-8)
    • Flutter version 3.26.0-1.0.pre.193 on channel main at /usr/local/google/home/het/Projects/flutter
    • Upstream repository [email protected]:flutter/flutter.git
    • Framework revision f83b08495a (28 hours ago), 2024-09-24 14:23:26 -0400
    • Engine revision dc44f95b70
    • Dart version 3.6.0 (build 3.6.0-273.0.dev)
    • DevTools version 2.40.0-dev.1

[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /usr/local/google/home/het/Android/Sdk
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/to/linux-android-setup for more details.

[✓] Chrome - develop for the web
    • Chrome at google-chrome

[✗] Linux toolchain - develop for Linux desktop
    • Debian clang version 16.0.6 (26)
    • cmake version 3.29.6
    • ninja version 1.11.1
    • pkg-config version 1.8.1
    ✗ GTK 3.0 development libraries are required for Linux development.
      They are likely available from your distribution (e.g.: apt install libgtk-3-dev)

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/to/linux-android-setup for detailed instructions).

[✓] Connected device (2 available)
    • Linux (desktop) • linux  • linux-x64      • Debian GNU/Linux rodete 6.9.10-1rodete5-amd64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 129.0.6668.70

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 3 categories.
@harryterkelsen harryterkelsen added platform-web Web applications specifically e: web_html HTML rendering backend for Web team-web Owned by Web platform team labels Sep 25, 2024
@yjbanov yjbanov added P3 Issues that are less important to the Flutter project triaged-web Triaged by Web platform team labels Sep 25, 2024
@harryterkelsen
Copy link
Contributor Author

The test was bugged due to too many pop() calls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
e: web_html HTML rendering backend for Web P3 Issues that are less important to the Flutter project platform-web Web applications specifically team-web Owned by Web platform team triaged-web Triaged by Web platform team
Projects
None yet
Development

No branches or pull requests

2 participants