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 Jun 12, 2020

Description

Convert the web version of dart:ui to null safety syntax.

Related Issues

flutter/flutter#53661

Copy link
Contributor

@vsmenon vsmenon left a comment

Choose a reason for hiding this comment

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

Nice!

// TODO(yjbanov): The code in this file was temporarily moved to lib/web_ui/lib/ui.dart
// during the NNBD migration so that `dart:ui` does not have to export
// `dart:_engine`. NNBD does not allow exported non-migrated libraries
// from migrated libraries.
Copy link
Contributor

Choose a reason for hiding this comment

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

@leafpetersen - is this a bug or an intended restriction?

Choose a reason for hiding this comment

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

This was intentional. We could remove the restriction, but I was aiming to have the property that opted in packages had no legacy types in their public interface, so that if you migrated relative to an opted in package you could be confident that you were done.


void _setLabel(html.Element element) {
if (semanticsObject.hasLabel) {
print('>>> semanticsObject.label = ${semanticsObject.label}');
Copy link
Contributor

Choose a reason for hiding this comment

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

Dead code?

Copy link
Contributor

Choose a reason for hiding this comment

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

And a few more 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.

This is just a draft PR. I exported it early to help reproduce dart-lang/sdk#42324. Sorry if it wasn't clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cleaned it up.

/// Return value should be null on success, and a string error message on
/// failure.
typedef Callbacker<T> = String Function(Callback<T> callback);
typedef Callbacker<T> = String/*?*/ Function(Callback<T> callback);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you mean to keep comment syntax here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For now. This PR only migrates dart:ui. dart:_engine will follow next.

final T item = _queue.removeFirst();
if (_dropItemCallback != null) {
_dropItemCallback(item);
_dropItemCallback!(item);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could replace if block with:

_dropItemCallback?.call(item);

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.

engine.AssetManager/*?*/ _assetManager;
engine.FontCollection _fontCollection;
engine.AssetManager? _assetManager;
engine.FontCollection? _fontCollection;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be a late?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Haven't been lucky with late yet, but maybe I'm not trying hard enough. The issue is most of our initialization patterns rely on null checks, e.g. if (foo == null) initializeFoo();. However, late non-null variables cannot be null checked.

It's OK for this PR to be incomplete. The goal is to move to the new syntax and to have a more or less correct public API surface. Internal parts can be revisited later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Filed flutter/flutter#59371 to revisit this.

Choose a reason for hiding this comment

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

Looks to me like it could be late final engine.FontCollection _fontCollection = engine.FontCollection();

SkiaFontCollection skiaFontCollection;

/// Initializes [skiaFontCollection].
void ensureSkiaFontCollectionInitialized() {

Choose a reason for hiding this comment

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

Once this file is opted in, can this become late SkiaFontCollection = skiaFontCollection? Maybe final if it doesn't get reset?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hopefully. Filed flutter/flutter#59371 to revisit this.

void clipRect(Rect/*!*/ rect,
{ClipOp clipOp/*!*/ = ClipOp.intersect, bool/*!*/ doAntiAlias = true});
void clipRect(Rect rect,
{ClipOp clipOp/*!*/ = ClipOp.intersect, bool doAntiAlias = true});

Choose a reason for hiding this comment

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

Leftover comment syntax?

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. The comment syntax was on the variable, not on the type, so the migration tool missed it. Fixed.

@yjbanov yjbanov marked this pull request as ready for review June 12, 2020 23:19
/// * [BlendMode], which discusses the use of [Paint.blendMode] with
/// [saveLayer].
void saveLayer(Rect/*?*/ bounds, Paint/*!*/ paint);
void saveLayer(Rect? bounds, Paint paint);
Copy link
Contributor

Choose a reason for hiding this comment

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

How are you validating that these APIs migrated to the same types as the other 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.

Fixed api_confrom_test.dart, but I'm not sure how to validate parameters. Can't find the right fields in the AST nodes 🤔 (maybe just tired at the end of the week)


dependencies:
meta: 1.1.8
meta: ^1.1.8
Copy link
Contributor

Choose a reason for hiding this comment

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

do you still need meta?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, we have tests and dev tools using it.

}
expect(semantics().semanticsEnabled, true);
});

Copy link
Contributor

Choose a reason for hiding this comment

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

Assuming that if tests pass they were migrated correctly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Of course 😎

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

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

LGTM

@jonahwilliams
Copy link
Contributor

(But not to CI)

static Rect/*?*/ lerp(Rect/*?*/ a, Rect/*?*/ b, double/*!*/ t) {
static Rect? lerp(Rect? a, Rect? b, double t) {
assert(t != null);
if (b == null) {

Choose a reason for hiding this comment

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

Ok, I just have to say - how cool is it that this code just worked with no changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did change this function in a previous PR to assist with type inference: f581f42#diff-3afaf9265618b9fee97b10a7de58cc76

But it's still pretty cool that despite both a and b being nullable, there are no ! in the body of the function.

Choose a reason for hiding this comment

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

Ah, I almost asked why it wasn't written the way it was pre-refactor... :)

If avoiding the extra instructions is important, you could write it as:

if (a == null) return (b == null) ? null : b * t;
if (b == null) return (a == null) ? null : a * (1.0 - t)
return ....

I also noticed that there were places where this was called with what looked like definitely non-nullable arguments, which made me wonder whether it was worth having a specialized version. But I have no idea which pieces of this are perf sensitive, so...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would be nice to have an annotation instructing the compiler to specialize automatically, similar to Scala's @specialized.

Copy link
Member

Choose a reason for hiding this comment

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

Consider filing a feature request for @specialized.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

a ??= 0.0;
b ??= 0.0;
return a + (b - a) * t;
return a + (b - a) * t as double?;

Choose a reason for hiding this comment

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

just as double. The result can't be null.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@stereotype441 good feedback for the tool?

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.

callback(codec.encodeSuccessEnvelope(null));
}

// TODO(yjbanov): remove _Callback, _Callbacker, and _futurize. They are here only

Choose a reason for hiding this comment

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

I think this bug just got fixed in master, but probably hasn't rolled to you yet.

@yjbanov
Copy link
Contributor Author

yjbanov commented Jun 13, 2020

(But not to CI)

I keep forgetting that non-nullable experiment in analysis_options.yaml is not enough. You also have to pass it to dartanalyzer via command-line options.

@yjbanov yjbanov force-pushed the nnbd-migrate-apply-web-ui branch from 8822517 to f0259c0 Compare June 15, 2020 16:34
await chromeDriverInstaller.install(alwaysInstall: true);
// TODO(yjbanov): remove this dynamic hack when chromeDriverInstaller.install returns Future<void>
// https://github.com/flutter/flutter/issues/59376
dynamic installationFuture = chromeDriverInstaller.install(alwaysInstall: true) as dynamic;
Copy link
Member

Choose a reason for hiding this comment

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

final?

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.

///
/// The `center` argument is assumed to be an offset from the origin.
Rect.fromCenter({ Offset center/*!*/, double/*!*/ width, double/*!*/ height }) : this.fromLTRB(
Rect.fromCenter({ required Offset center/*!*/, required double width, required double height }) : this.fromLTRB(
Copy link
Member

Choose a reason for hiding this comment

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

Stray /*!*/ ?

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.

static Rect/*?*/ lerp(Rect/*?*/ a, Rect/*?*/ b, double/*!*/ t) {
static Rect? lerp(Rect? a, Rect? b, double t) {
assert(t != null);
if (b == null) {
Copy link
Member

Choose a reason for hiding this comment

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

Consider filing a feature request for @specialized.

/// [Locale] objects.
String/*!*/ get languageCode => _deprecatedLanguageSubtagMap[_languageCode] ?? _languageCode;
final String/*!*/ _languageCode;
String get languageCode => _deprecatedLanguageSubtagMap[_languageCode] ?? _languageCode;
Copy link
Member

Choose a reason for hiding this comment

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

Should the value type of _deprecatedLanguageSubtagMap be String?? Or does the ? get tacked onto e.g. the return type of operator[]?

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, operator[] always returns nullable type, no matter what type arguments the map has.

@yjbanov
Copy link
Contributor Author

yjbanov commented Jun 16, 2020

@zanderso

Consider filing a feature request for @specialized.

dart-lang/sdk#42361

engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 18, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 18, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 18, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 18, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 18, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 18, 2020
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.

6 participants