Улучшены языковые возможности и опыт разработчиков, а также обновлена информация о веб-приложениях и Wasm

Авторы: Kevin Moore & Michael Thomsen

Сегодня мы анонсируем Dart 3.2, в котором появилась новая языковая функция для non-null продвижения приватных конечных полей, улучшен опыт разработчиков за счет новых возможностей взаимодействия, поддержка расширений в DevTools, а также обновлен дорожный план веб-разработки, включающий поддержку Wasm (aka WebAssembly).

Non-null продвижение для приватных конечных полей

Прошло несколько лет с тех пор, как в Dart 2.12 мы ввели sound null safety. С помощью null safety можно объявить, какие типы являются nullable (могут содержать значение или null), а какие - non-nullable (всегда содержат значение). Безопасность null-переменных в сочетании с анализом потока позволяет определить, когда такие переменные могут быть "переведены" в более безопасные, non-null типы:

int definitelyInt(int? aNullableInt) {
  if (aNullableInt == null) {
    return 0;
  }
  // Если анализ потока достигает этой точки, 
  // aNullableInt может безопасно переходить в не-null-евой int.
  return aNullableInt; 
}

Продвижение типов было основной частью null safety начиная с Dart 2.12, но ограничивалось локальными переменными. Поля или переменные верхнего уровня не могли быть продвинуты, например, в таком случае:

class Container {
  final int? _fillLevel;
  Container(this._fillLevel);
  check() {
    if (_fillLevel != null) {
      int i = _fillLevel; // До версии Dart 3.2 приводит к ошибке.
    }
  }
}

Это ограничение было связано с несколькими сложными случаями, когда анализ потока не мог надежно определить, когда и как может измениться поле. Например, в случае продвижения полей в классе может возникнуть проблема, если подкласс переопределит поле с геттером, который иногда возвращает null.

В Dart 3.2 мы усовершенствовали механизм анализа потока и теперь можем продвигать приватные конечные поля. Теперь приведенный выше фрагмент кода выполняется без ошибок. При этом используется понимание того, что для приватного конечного поля значение никогда не меняется после первоначального присвоения, поэтому проверка его только один раз считается безопасной. Продвижение приватного финального поля доступно начиная с версии Dart 3.2 и распространяется на проекты, имеющие нижнюю границу Dart SDK версии 3.2 или выше.

Новые возможности анализа кода в package:lints 3.0

Говоря об анализе кода, мы также внесли ряд улучшений в наши стандартные правила анализа кода в package:lints. Этот пакет содержит стандартный и рекомендуемый набор правил статического анализа, который поставляется с любым новым проектом, созданным с помощью dart create или flutter create (через package:flutter_lints - расширение package:lints).

В настоящее время доступна новая основная версия этого набора линтов - версия 3.0. В этой редакции добавлено шесть линтов в основной набор и два линта в рекомендуемый набор. В нем имеются линты для проверки URL-адресов pubspec, проверки того, что методы коллекции вызываются с правильными аргументами, и многое другое. Полный список изменений приведен в журнале изменений. Версия 3.0 будет использоваться по умолчанию для новых проектов в ближайшем релизе. Для существующих проектов обновление можно выполнить уже сейчас.

(Прим. переводчика: рассмотрите также полезный материал от @alexeyinkin: Новый линт в Dart 3.2 (линт annotate_redeclares))

Обновление совместимости Dart

Многоплатформенная поддержка широкого спектра платформ всегда была одним из основных принципов Dart. Но даже если строка кода Dart может работать без изменений на всех этих платформах, крупные приложения все равно часто нуждаются во взаимодействии с существующим кодом. Это может быть код из старых проектов или API, доступный в других библиотеках или системных API. Мы сделали ряд инвестиций в эту область, начиная с FFI для взаимодействия с родными API на языке C. В настоящее время мы работаем над расширением этой возможности для поддержки взаимодействия с Java и Kotlin, Objective C и Swift. О новых интересных событиях, связанных с JS-взаимодействием, читайте в веб-разделе, посвященном Dart, ниже.

Начиная с версии Dart 3.2, мы внесли ряд улучшений в нативное взаимодействие:

  • Мы ввели конструктор NativeCallable.isolateLocal для C FFI, который создает указатель функции C из произвольной функции Dart. Это расширение функциональности Pointer.fromFunction, который может создавать указатели функций только из функций верхнего уровня.

  • Мы обновили генератор привязок Objective-C для использования NativeCallable.listener, который мы добавили в Dart 3.1. Генератор теперь может автоматически обрабатывать API, содержащие асинхронные обратные вызовы, как, например, Core Motion. Ранее такие API требовали написания части кода привязки вручную.

  • Мы продолжаем совершенствовать package:jnigen для взаимодействия с Java и Kotlin. Это позволило нам перенести package:cronet_http - обертку для HTTP-клиента Cronet в Android - с рукописного кода привязки на автоматически генерируемую обёртку.

  • Мы значительно продвинулись в работе над функцией Native Assets, которая призвана решить ряд проблем, связанных с распространением пакетов Dart, зависящих от нативного кода. Это достигается за счет предоставления унифицированных хуков для интеграции с различными системами сборки, участвующими в создании Flutter и автономных Dart-приложений. Для предварительного просмотра ознакомьтесь с документацией.

Расширения DevTools для Dart пакетов

Dart DevTools - это набор инструментов для отладки и повышения производительности, поддерживающий приложения на чистом Dart и Flutter. В Dart 3.2 и Flutter 3.16 мы анонсируем новый фреймворк расширений, который позволяет авторам пакетов создавать пользовательские инструменты для своих пакетов, размещаемые непосредственно в DevTools. Это позволяет пакетам pub.dev, содержащим фреймворки, предлагать пользовательские инструменты, специфичные для их использования. Например, авторы Serverpod активно работают над созданием инструментов разработчика для своего пакета и с нетерпением ждут выхода расширения DevTools в ближайшей версии 1.2.

Расширение DevTools, запланированное к выпуску в ближайшем будущем ServerPod 1.2
Расширение DevTools, запланированное к выпуску в ближайшем будущем ServerPod 1.2

Обновление Dart web и Wasm

Wasm (также известный как WebAssembly) - это новый формат инструкций для веб-браузеров, который обеспечивает переносимый, платформенно-нейтральный формат двоичного кода для исполнения в современных браузерах. Высокоуровневые управляемые языки, такие как Dart, используют сборку мусора, которая в настоящее время добавляется в стандарт Wasm. Начиная с Chrome 119, поддержка сборки мусора для Wasm (известная как Wasm-GC) включена по умолчанию. Поддержка Wasm-GC также появится в Firefox 120, следующем стабильном выпуске. Как обстоят дела с Dart, Flutter и Wasm-GC?

Компилятор Dart-to-Wasm практически завершен. Команда очень довольна производительностью и совместимостью. Сейчас мы сосредоточились на краевых случаях, чтобы убедиться в быстродействии наших результатов в широком диапазоне сценариев.

Для веб-версии Flutter мы завершили разработку нового движка рендеринга "Skwasm". Для достижения максимальной производительности Swasm подключает скомпилированный код приложения непосредственно к пользовательскому модулю CanvasKit Wasm с помощью привязки wasm-to-wasm. Кроме того, это первая версия поддержки многопоточного рендеринга для Flutter web, которая ещё больше улучшает время обработки кадров.

До выхода Flutter web with Wasm из текущего экспериментального статуса осталось сделать еще несколько вещей:

  • Двойная компиляция: Генерирование выходных данных на основе Wasm и JavaScript и включение функции обнаружения признаков во время выполнения для поддержки браузеров с поддержкой и без поддержки Wasm-GC.

  • Современная JavaScript-интероперабельность: Новый механизм взаимодействия с JS, основанный на типах расширений и позволяющий осуществлять краткие, безопасные для типов вызовы между кодом Dart, API браузера и JS-библиотеками при работе с JavaScript и Wasm.

  • Браузерные API с поддержкой Wasm: Новый package:web, заменяющий dart:html (и связанные с ним библиотеки), основан на современном механизме взаимодействия с JS. Это обеспечит удобный доступ к браузерным API с поддержкой как JS, так и Wasm целей.

Мы начинаем переводить ряд внутренних проектов на package:web и новый механизм взаимодействия с JS и ожидаем новых обновлений в следующем стабильном релизе. Тем временем последние подробности можно получить на странице Support for WebAssembly.

Завершая
Это всё, что мы имеем на сегодня. Dart 3.2 доступен сейчас с сайта dart.dev или в составе сегодняшнего выпуска Flutter 3.16 (прим. переводчика: материал доступен также на Habr: Flutter 3.16: что нового). До следующего раза, развлекайтесь с Dart!

Комментарии (5)


  1. whoisking
    19.11.2023 10:58

    И сидишь весь в нулсейфти такой по уши и оборачиваешь каждую бедную переменную, вместо того, чтоб логику писать. Может для энтерпрайза и классно, но как раньше от флаттер-дарта такого кайфа уже не испытываешь, попиливая небольшое приложение.


    1. aaabramenko
      19.11.2023 10:58
      +1

      Оператор ! вам в помощь.


      1. MrCheater
        19.11.2023 10:58
        +1

        Расшифровка для тех, кто не слишком сильно знаком с typescript. Оператор ! значит "я лично гарантирую, что там не null или undefined, мамой клянусь"


  1. axelmaker
    19.11.2023 10:58
    +1

    Когда выходит новая версия Dart, сразу жду от Вас перевода, зная, что он будет)


  1. nameisBegemot
    19.11.2023 10:58

    Интересно, а у ассемблера выходят обновления? Или там от регистров процессора все зависит