Найти в Дзене
Chris Roylance

Вышло обновление Bun v1.3.9

Запускайте несколько скриптов package.json одновременно или последовательно с выводом в стиле Foreman. Включает полную интеграцию с --filter и --workspaces для параллельного или последовательного запуска скриптов в пакетах рабочих областей. Каждая строка вывода начинается с цветной, дополненной метки, чтобы вы могли определить, какой скрипт её создал: При использовании в сочетании с --filter или --workspaces, метки содержат имя пакета: --parallel запускает все скрипты немедленно с чередующимся выводом с префиксами. --sequential запускает скрипты по одному в порядке следования. По умолчанию, сбой в любом скрипте приводит к завершению всех оставшихся скриптов — используйте --no-exit-on-error, чтобы позволить им всем завершиться. Скрипты, выполняемые до и после сборки (prebuild/postbuild), автоматически группируются вместе с основным скриптом и запускаются в правильном порядке зависимостей внутри каждой группы. bun --filter="pkg" <script> учитывает порядок зависимостей. Он не запускает
Оглавление

bun run --parallel и bun run --sequential

Запускайте несколько скриптов package.json одновременно или последовательно с выводом в стиле Foreman. Включает полную интеграцию с --filter и --workspaces для параллельного или последовательного запуска скриптов в пакетах рабочих областей.

-2

Каждая строка вывода начинается с цветной, дополненной метки, чтобы вы могли определить, какой скрипт её создал:

-3

При использовании в сочетании с --filter или --workspaces, метки содержат имя пакета:

-4

--parallel запускает все скрипты немедленно с чередующимся выводом с префиксами. --sequential запускает скрипты по одному в порядке следования. По умолчанию, сбой в любом скрипте приводит к завершению всех оставшихся скриптов — используйте --no-exit-on-error, чтобы позволить им всем завершиться.

Скрипты, выполняемые до и после сборки (prebuild/postbuild), автоматически группируются вместе с основным скриптом и запускаются в правильном порядке зависимостей внутри каждой группы.

Чем это отличается от --filter?

bun --filter="pkg" <script> учитывает порядок зависимостей. Он не запускает скрипт, пока не будут выполнены все его зависимые скрипты. Это может быть проблемой при использовании скриптов с длительным временем жизни, подобных watch. --parallel и --sequential не учитывают порядок зависимостей, поэтому они не будут ждать.

Обновление HTTP/2-соединений через net.Server

Шаблон обновления соединений net.Server → Http2SecureServer теперь работает корректно. Этот шаблон используется такими библиотеками, как http2-wrapper, crawlee и пользовательскими HTTP/2-прокси-серверами, которые принимают необработанные TCP-соединения на net.Server и перенаправляют их на Http2SecureServer через h2Server.emit('connection', rawSocket).

-5

Поддержка Symbol.dispose для mock() и spyOn()

Функция mock() и spyOn() теперь реализуют интерфейс Symbol.dispose, что позволяет ключевому слову using автоматически восстанавливать моки, когда они выходят из области видимости. Это устраняет необходимость вручную вызывать mockRestore() или полагаться на очистку afterEach.

-6

[Symbol.dispose] является псевдонимом для mockRestore, поэтому он работает как со spyOn(), так и с mock():

-7

Теперь параметр NO_PROXY учитывается для явно заданных параметров прокси.

Ранее установка NO_PROXY работала только в том случае, если прокси определялся автоматически из переменных окружения http_proxy/HTTP_PROXY. Если вы явно передавали параметр прокси в функции fetch() или new WebSocket(), переменная окружения NO_PROXY игнорировалась.

Теперь проверка NO_PROXY выполняется всегда — даже если прокси явно указан через параметр proxy.

-8

Флаг --cpu-prof-interval

Теперь Bun поддерживает флаг --cpu-prof-interval для настройки интервала выборки профилировщика ЦП в микросекундах, аналогично флагу Node.js с тем же именем. Интервал по умолчанию составляет 1000 мкс (1 мс).

# Выборка каждые 500 мкс для более точного профилирования
bun --cpu-prof --cpu-prof-interval 500 index.js

Если используется без --cpu-prof или --cpu-prof-md, Bun выдаст предупреждение.

Байт-код ESM в --compile

Теперь поддерживается использование --bytecode с --format=esm. Ранее это не поддерживалось из-за отсутствия функциональности в JavaScriptCore, а теперь поддерживается полностью.

При использовании --bytecode без явного указания --format по умолчанию используется CommonJS. В будущей версии Bun мы можем изменить это значение по умолчанию на ESM, чтобы сделать поведение более согласованным.

Спасибо @alistair!

Исправлено: Сбои, вызванные недопустимой инструкцией (SIGILL), на процессорах ARMv8.0 aarch64

Исправлены сбои на более старых процессорах ARM64 (Cortex-A53, Raspberry Pi 4, экземпляры AWS a1), вызванные тем, что mimalloc генерирует атомарные инструкции LSE, требующие ARMv8.1 или более поздней версии. Bun теперь корректно ориентирован на ARMv8.0 в Linux aarch64, используя атомарные инструкции outline для диспетчеризации во время выполнения.

Ускоренная отрисовка Markdown в HTML

Bun.Markdown теперь использует SIMD-ускоренное сканирование для поиска символов, требующих экранирования HTML (&, <, >, "), что приводит к ускорению отрисовки Markdown в HTML на 3-15%. Наибольший прирост наблюдается в документах большего размера с меньшим количеством специальных символов.

Спасибо @billywhizz за вклад!

Ускоренная работа Bun.markdown.react()

Кэширование часто используемых строковых HTML-тегов (div, p, h1-h6 и т. д.) в рендерере React для Bun.markdown.react() позволяет избежать повторного выделения строк при создании каждого элемента.

Размер входных данных До После Улучшение

  • Маленький (121 символ) 3,20 мкс 2,30 мкс На 28% быстрее
  • Средний (1039 символов) 15,09 мкс 14,02 мкс На 7% быстрее
  • Большой (20780 символов) 288,48 мкс 267,14 мкс На 7,4% быстрее

Количество строковых объектов уменьшено на 40%, а размер кучи уменьшен на 6% при типичном рендеринге.

Более быстрая обработка AbortSignal.abort() без слушателей

Теперь AbortSignal.abort() пропускает создание и отправку объекта Event, если нет зарегистрированных слушателей, избегая ненужного выделения объектов и накладных расходов на отправку. Это приводит к улучшению микротестов примерно на 6% (~16 мс экономии на 1 миллион вызовов).

Случай До После Улучшение

  • без слушателя 271 мс 255 мс ~6%
  • со слушателем 368 мс 370 мс (то же самое)

Спасибо @sosukesuzuki за вклад!

Обновление JavaScriptCore

Ускорение регулярных выражений с помощью SIMD

Регулярные выражения получили значительное повышение производительности благодаря новому ускоренному поиску префиксов с помощью SIMD, вдохновленному подходом V8. Когда регулярное выражение имеет альтернативы с известными начальными символами (например, /aaaa|bbbb/), JSC теперь использует инструкции SIMD для сканирования 16 байтов за раз, быстро отклоняя несовпадающие позиции, прежде чем вернуться к скалярному сопоставлению. Это реализовано как для ARM64 (с использованием TBL2), так и для x86_64 (с использованием PTEST), поэтому все платформы получают выгоду.

Генерация кода x86_64 также получила новые примитивы материализации констант (move128ToVector, move64ToDouble, move32ToFloat) с использованием инструкций broadcast и shuffle, которые необходимы для путей регулярных выражений SIMD и будущих оптимизаций SIMD.

579b96614b75 — Быстрый поиск префикса SIMD для регулярных выражений (ARM64)

b7ed3dae4a6a — Быстрый поиск префикса SIMD для регулярных выражений (x86_64)

aa596dded063 — Материализация констант x86_64 для маски SIMD

JIT-компиляция регулярных выражений: скобки с фиксированным количеством символов

Подшаблоны в скобках без захвата с кванторами с фиксированным количеством символов, такие как (?:abc){3}, ранее переключались на более медленный интерпретатор Yarr. Теперь они компилируются JIT-компиляцией с использованием цикла на основе счетчика, что обеспечивает ускорение примерно в 3,9 раза для затронутых шаблонов. В последующем патче также добавлена ​​поддержка JIT для подшаблонов с фиксированным количеством символов и группами захвата (например, /(a+){2}b/), корректно сохраняя и восстанавливая состояние захвата между итерациями.

ac63cc259d74 — Поддержка JIT для скобок без захвата с фиксированным количеством символов (примерно в 3,9 раза быстрее)

c8b66aa0832b — Поддержка JIT для подшаблонов с фиксированным количеством символов и группами захвата

Оптимизация String#startsWith в DFG/FTL

String.prototype.startsWith теперь является встроенной функцией в JIT-компиляторах DFG и FTL с поддержкой постоянного свертывания, когда строка и поисковый запрос известны во время компиляции.

Ускорение в бенчмарках

  • string-prototype-startswith в 1,42 раза быстрее
  • string-prototype-startswith-constant-folding в 5,76 раза быстрее
  • string-prototype-startswith-with-index в 1,22 раза быстрее

1f7d7d5a8c23

Оптимизация методов Set#size и Map#size в кэшах DFG/FTL и встроенных кэшах

Геттер .size в методах Set и Map теперь обрабатывается как встроенная функция в уровнях DFG/FTL и встроенных кэшах, что устраняет накладные расходы на вызов универсального геттера.

Ускорение в бенчмарках

  • set-size в 2,24 раза быстрее
  • map-size в 2,74 раза быстрее

2e2c23521a24

Оптимизация String#trim

String.prototype.trim, trimStart и trimEnd теперь используют прямой доступ к указателям через span8()/span16() вместо косвенного доступа к символу str[i], что позволяет избежать повторной проверки границ.

Ускорение в бенчмарках

  • string-trim в 1,17 раза быстрее
  • string-trim-end в 1,42 раза быстрее
  • string-trim-start в 1,10 раза быстрее

73a97d320d4b

Обработка Object.defineProperty в DFG/FTL

Object.defineProperty теперь распознается как встроенная функция в JIT-компиляторах DFG и FTL. Хотя этот патч сам по себе не меняет результаты бенчмарков, он закладывает основу для будущих оптимизаций, которые могут специализироваться в зависимости от формы дескриптора.

b1703ed2b97e

Метод `String.prototype.replace` возвращает объект типа «веревка» (Ropes).

При использовании `string`, `replace("search", "replacement")` со строковыми аргументами JSC теперь создает объект типа «веревка» (ленивая конкатенация) вместо немедленного копирования всего результата. Это позволяет избежать ненужных выделений памяти в распространенном случае, когда результат используется лишь кратковременно. Это соответствует поведению V8.

69162bbdb602

Исправления ошибок

Улучшения совместимости с Node.js

  • Исправлено: некорректная работа existsSync('.'), statSync('.') и других операций node:fs в Windows из-за того, что '.' нормализовался в пустую строку вместо текущего каталога.
  • Исправлено: пробел в Function.prototype.toString() теперь соответствует V8/Node.js
  • Исправлены 3 редких сбоя в node:http2

API Bun

Исправлено: Bun.stringWidth некорректно сообщал, что тайские SARA AA (U+0E32), SARA AM (U+0E33) и их лаосские эквиваленты (U+0EB2, U+0EB3) имеют нулевую ширину вместо ширины 1. Это пробельные гласные, а не комбинированные знаки, поэтому распространенные тайские слова, такие как คำ, теперь правильно возвращают ширину 2 вместо 1.

Веб-API

  • Исправлено: сбой, который мог произойти в клиенте WebSocket при использовании binaryType = "blob" и получении событий "data", если не был подключен обработчик событий.
  • Исправлено: последовательные HTTP-запросы с абсолютными URL-адресами в стиле прокси (например, GET http://example.com/path HTTP/1.1) зависали на втором и последующих запросах при использовании соединений keep-alive. Это затрагивало HTTP-прокси-серверы, созданные с помощью Bun, которые могли обрабатывать только один запрос на соединение.
  • Исправлено: проблема безопасности в парсере кодирования HTTP-сервера, которая могла привести к подмене запросов.

Типы TypeScript

  • Исправлено: Тип TypeScript Bun.Build.CompileTarget не содержал SIMD-вариантов, таких как bun-linux-x64-modern, что приводило к ошибкам типов при кросс-компиляции с определенными архитектурными целями.
  • Исправлено: Отсутствовали типы целей компиляции bun-linux-x64-baseline и bun-linux-x64-modern в определениях TypeScript, что приводило к ошибкам типов при использовании Bun.build() с этими допустимыми целями.
  • Исправлено: Типы TypeScript Socket.reload() теперь корректно ожидают { socket: handler } для соответствия поведению во время выполнения, что требует, чтобы обработчик был обернут в свойство socket.