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

Conversation

@liyuqian
Copy link
Contributor

@tvolkert
Copy link
Contributor

Please add a compositing_test.dart in https://github.com/flutter/engine/tree/master/testing/dart that would have caught this regression.

throw new ArgumentError('"matrix4" argument cannot be null');
if (matrix4.length != 16)
throw new ArgumentError('"matrix4" must have 16 entries.');
for (double number in matrix4) {
Copy link
Contributor

Choose a reason for hiding this comment

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

if (matrix4.any((double value) => value.isInfinite || value.isNaN))
  throw new ArgumentError('"matrix4" cannot have infinite or NaN elements');

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor Author

@liyuqian liyuqian left a comment

Choose a reason for hiding this comment

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

Unit test added. Thanks for the suggestion of using any!

throw new ArgumentError('"matrix4" argument cannot be null');
if (matrix4.length != 16)
throw new ArgumentError('"matrix4" must have 16 entries.');
for (double number in matrix4) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

matrix4[0] = double.nan;
expect(
() => builder.pushTransform(matrix4),
throwsA(TypeMatcher<ArgumentError>())
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: const TypeMatcher<ArgumentError> and below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in the new version. I just realized that this comment was made before I uploaded the new patch...

if (matrix4.length != 16)
throw new ArgumentError('"matrix4" must have 16 entries.');
if (matrix4.any((double value) => value.isInfinite || value.isNaN))
throw new ArgumentError('"matrix4" cannot have infinite or NaN elements');
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add this to the _validateMatrix4 in painting.dart, and just call that from here?

Even though it's private, it's available here because this is all part of dart:ui

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is outdated. We're now calling _throwIfMarix4IsInvalid.

assert(matrix4 != null, 'Matrix4 argument was null.');
assert(matrix4.length == 16, 'Matrix4 must have 16 entries.');
assert(matrix4.every((double value) => value.isFinite), 'Matrix4 entries must be finite.');
return true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Wont this mean that in profile and release modes, the engine will still end up with invalid matrices?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, but as a general principle, we do a ton of validation in debug mode only via asserts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but we're calling _throwIfMarix4IsInvalid in pushTransform.

Copy link
Contributor

Choose a reason for hiding this comment

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

This was already true - if someone decided to pass null for example, or use NaN in a Rect or Offset.

assert(matrix4 != null, 'Matrix4 argument was null.');
assert(matrix4.length == 16, 'Matrix4 must have 16 entries.');
assert(matrix4.every((double value) => value.isFinite), 'Matrix4 entries must be finite.');
return true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, but as a general principle, we do a ton of validation in debug mode only via asserts.

throw new ArgumentError('"matrix4" argument cannot be null');
if (matrix4.length != 16)
throw new ArgumentError('"matrix4" must have 16 entries.');
_throwIfMatrix4IsInvalid(matrix4);
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than creating _throwIfMatrix4IsInvalid() which duplicates the checks in _matrix4IsValid(), I think we should either (a) just do an if check on _matrix4IsValid() here and throw ArgumentError saying the matrix is invalid, or (b) just call assert(_matrix4IsValid(matrix4)) here.

B is more in keeping with our existing data validation in the framework, which is to catch these types of problems at development time and optimize out the checks in release builds.

/// See [pop] for details about the operation stack.
EngineLayer pushTransform(Float64List matrix4) {
_throwIfMatrix4IsInvalid(matrix4);
_matrix4IsValid(matrix4);
Copy link
Contributor

Choose a reason for hiding this comment

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

assert(_matrix4IsValid(matrix4)) just to make it clear (which works since the method also returns a bool)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

throwsA(const TypeMatcher<AssertionError>()),
);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

(trivial nit: looks like some indentation in this file is off. maybe the finals are one space too much indented?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@Hixie
Copy link
Contributor

Hixie commented Apr 26, 2019

Bonus points if you can figure out where on the wiki we should be documenting this pattern (and other things we discussed in chat).

@liyuqian liyuqian merged commit 50de469 into flutter:master Apr 26, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 26, 2019
engine-flutter-autoroll added a commit to flutter/flutter that referenced this pull request Apr 26, 2019
flutter/engine@7df8b7a...50de469

git log 7df8b7a..50de469 --no-merges --oneline
50de469 Check the matrix in pushTransform (flutter/engine#8758)

The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff (liyuqian@google.com), and stop
the roller if necessary.
@liyuqian liyuqian deleted the transform_matrix branch June 10, 2019 22:16
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Engine crash during unconstrained layout

6 participants