Skip to content

Commit

Permalink
Add a dart2js section to the null safety FAQ (#3318)
Browse files Browse the repository at this point in the history
Closes #3314
  • Loading branch information
kwalrath authored Jun 24, 2021
1 parent a028274 commit 603f84d
Showing 1 changed file with 71 additions and 0 deletions.
71 changes: 71 additions & 0 deletions src/null-safety/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,77 @@ and situations where a null value is really expected. So the tool tells you what
it knows ("it looks like this condition will always be false!") and lets you
decide what to do.

## What should I know about dart2js and null safety?

For a long time, the dart2js compiler has had optimizations specifically
targeting null values and null checks. Because of that, null safety is not
expected to affect much the output of the compiler.

A few notes that are worth highlighting:

* dart2js emits `!` null assertions, but you may not notice them.
That's because pre null-safety dart2js already emitted null checks
(so they are already in the existing programs).

* dart2js emits these null assertions regardless of sound/unsound null safety
and regardless of optimization level. In fact, dart2js doesn't remove
`!` when using `-O3` or `--omit-implicit-checks`.

* dart2js may optimize away unnecessary null checks. This is because the same
optimizations done by dart2js in the past will be able to eliminate
unnecessary null checks when it knows the value is not null.

* By default dart2js would generate parameter subtype checks (runtime checks
used to ensure covariant virtual calls are given appropriate arguments).
These are elided with the `--omit-implicit-checks` flag just as before.
Recall that this flag can make programs have unexpected behavior if types
are invalid, so we continue to recommend that the code has strong test
coverage to avoid any surprises. In particular, dart2js optimizes code based
on the fact that inputs should comply with the type declaration. If
the code provides arguments of an invalid type, those optimizations would
be wrong and the program could misbehave. This was true for inconsistent
types before, and is true with inconsistent nullabilities now with sound
null-safety.

* You may notice that DDC and the Dart VM have special error
messages for null checks, but to keep applications small dart2js does not.

* You may see errors indicating that `.toString` is not found on `null`.
This is not a bug, it is how dart2js has always encoded some null checks.
That is, dart2js represents some null checks compactly by making an unguarded
access of a property of the
receiver. So instead of `if (a == null) throw`, it generates `a.toString`.
The `toString` method is defined in JavaScript Object and is a fast
way to verify that an object is not null.

If the very first action after a null check is an action that
will crash when the value is null, dart2js can remove the null check and
let the action cause the error.

For example, a Dart expression `print(a!.foo());` could turn directly into:

```js
P.print(a.foo$0());
```

This is because the call `a.foo$()` will crash if `a` is null.
If dart2js inlines `foo`, it will preserve the null check.
So for example, if `foo` was `int foo() => 1;` the compiler might generate:

```js
a.toString;
P.print(1);
```

If by chance the first thing the inlined method did was a field access on the
receiver, for example `int foo() => this.x + 1;`, then again dart2js
can remove the redundant `a.toString` null check, just like
non-inlined calls, and generate:

```js
P.print(a.x + 1);
```

## Resources

* [DartPad with Null Safety](https://nullsafety.dartpad.dev)
Expand Down

0 comments on commit 603f84d

Please sign in to comment.