Wydano Node.js 20.0, platformę do uruchamiania aplikacji sieciowych w języku JavaScript. Node.js 20.0 należy do gałęzi z długoterminowym wsparciem, jednak ten status zostanie przyznany dopiero w październiku, po stabilizacji. Wsparcie dla Node.js 20.x będzie realizowane do 30 kwietnia 2026 roku. Wsparcie dla poprzedniej gałęzi LTS Node.js 18.x potrwa do kwietnia 2025 roku, a dla jeszcze wcześniejszej LTS 16.x do września 2023 roku. Wsparcie dla gałęzi LTS 14.x zakończy się 30 kwietnia, a dla gałęzi pośredniej Node.js 19.x - 1 czerwca.
Zaimplementowano wywołania systemowe waitid (oczekiwanie na zmianę stanu procesu), pinsyscall (do przekazywania informacji o punkcie wejścia execve w celu ochrony przed exploitami ROP), getthrname i setthrname (uzyskiwanie i ustalanie nazwy wątku).
- Silnik V8 zaktualizowano do wersji 11.3, stosowanej w Chromium 113. Wśród zmian w porównaniu do gałęzi Node.js 19, w której używano silnika Chromium 107, wyróżniają się funkcje String.prototype.isWellFormed i toWellFormed, metody Array.prototype i TypedArray.prototype do pracy z kopią przy modyfikacji obiektów Array i TypedArray, flaga „v” w RegExp, wsparcie dla zmiany rozmiaru ArrayBuffer i zwiększenia rozmiaru SharedArrayBuffer, a także rekurencja ogonowa (tail-call) w WebAssembly.
- Предложен экспериментальный механизм Permission Model, позволяющий ограничить доступ к определённым ресурсам в процессе исполнения. Поддержка Permission Model включается через указание при запуске флага «—experimental-permission». В начальной реализации предложены опции для ограничения доступа на запись (—allow-fs-write) и чтение (—allow-fs-read) к определённым частям ФС, дочерним процессам (—allow-child-process), дополнениям (—no-addons) и потокам (—allow-worker). Например, чтобы разрешить запись в каталог /tmp и чтение файла /home/index.js можно указать: node —experimental-permission —allow-fs-write=/tmp/ —allow-fs-read=/home/index.js index.js
Do sprawdzenia dostępu sugeruje się użycie metody process.permission.has(), przykładowo, „process.permission.has(‘fs.write’, 'tmp/test’).
- Obsługa zewnętrznych modułów ECMAScript (ESM), ładowanych za pomocą opcji „—experimental-loader”, teraz działa w osobnym wątku, odizolowanym od głównego wątku, co wyklucza nakładanie się kodu aplikacji i ładowanych modułów ESM. Podobnie jak w przeglądarkach, metoda import.meta.resolve() wywoływana z aplikacji teraz działa w trybie synchronicznym. W jednej z przyszłych gałęzi Node.js planowane jest przeniesienie wsparcia dla ładowania ESM do kategorii stabilnych funkcji.
- Do kategorii stabilnych przeniesiono moduł node:test (test_runner), przeznaczony do tworzenia i uruchamiania testów w języku JavaScript, zwracających wyniki w formacie TAP (Test Anything Protocol).
- Stworzono osobny zespół deweloperów odpowiedzialny za optymalizację wydajności, który podczas przygotowywania nowej gałęzi przeprowadził prace nad przyspieszeniem różnych komponentów runtime, w tym analizy URL, fetch() i EventTarget. Na przykład, narzuty przy inicjalizacji EventTarget zostały zredukowane o połowę, znacznie poprawiła się wydajność metody URL.canParse(), a efektywność pracy timerów wzrosła. Poza tym, do składu włączono wydanie wysokowydajnego parsera URL — Ada 2.0, napisanego w języku C++.
- Kontynuowano rozwój eksperymentalnej możliwości dostarczania aplikacji w postaci jednego pliku wykonywalnego (SEA, Single Executable Applications). Tworzenie pliku wykonywalnego teraz wymaga podstawienia blobu, generowanego na podstawie pliku konfiguracyjnego w formacie JSON (zamiast podstawienia pliku JavaScript).
- Poprawiono zgodność API Web Crypto z implementacjami z innych projektów.
- Dodano oficjalne wsparcie dla systemu Windows na platformach ARM64.
- Kontynuowano wdrażanie wsparcia dla rozszerzeń WASI (WebAssembly System Interface) w celu tworzenia odizolowanych aplikacji WebAssembly. Usunięto konieczność podawania specjalnego flagi wiersza poleceń w celu włączenia wsparcia WASI.
Platforma Node.js może być wykorzystana zarówno do serwerowego wsparcia prac Web-aplikacji, jak i do tworzenia zwykłych klientskich oraz serwerowych programów sieciowych. Dla rozszerzenia funkcjonalności aplikacji do Node.js przygotowano dużą kolekcję modułów, w której można znaleźć moduły z realizacją serwerów klientów HTTP, SMTP, XMPP, DNS, FTP, IMAP, POP3, moduły do integracji z różnymi frameworkami webowymi, obsługiwacze WebSocket i Ajax, konektory do baz danych (MySQL, PostgreSQL, SQLite, MongoDB), silniki szablonów, silniki CSS, realizacje algorytmów kryptograficznych oraz systemów autoryzacji (OAuth), parsery XML.
Aby obsłużyć dużą liczbę równoległych zapytań, Node.js wykorzystuje asynchroniczny model uruchamiania kodu oparty na przetwarzaniu zdarzeń w trybie non-blocking oraz definiowaniu callbacków. Wsparcie dla multiplexing połączeń obejmuje takie metody jak epoll, kqueue, /dev/poll i select. Do multiplexing połączeń używana jest biblioteka libuv, która jest dodatkową warstwą nad libev w systemach Unix oraz nad IOCP w Windows. Do tworzenia puli wątków (thread pool) wykorzystana jest biblioteka libeio, a do wykonywania zapytań DNS w trybie non-blocking zintegrowano c-ares. Wszystkie wywołania systemowe, które powodują blokowanie, są realizowane w obrębie puli wątków, a następnie, podobnie jak obsługa sygnałów, przekazują wyniki swojej pracy z powrotem przez niestrunną rynnę (pipe). Wykonanie kodu JavaScript zapewnia stworzony przez firmę Google silnik V8 (dodatkowo Microsoft rozwija wersję Node.js z silnikiem Chakra-Core).
Zasadniczo Node.js przypomina frameworki Perl AnyEvent, Ruby Event Machine, Python Twisted oraz implementację zdarzeń w Tcl, ale pętla zdarzeń (event loop) w Node.js jest ukryta przed deweloperem i przypomina przetwarzanie zdarzeń w aplikacji webowej działającej w przeglądarce. Przy pisaniu aplikacji dla Node.js należy uwzględnić specyfikę programowania opartego na zdarzeniach, na przykład zamiast wykonywać „var result = db.query(„select..”);” z oczekiwaniem na zakończenie pracy i dalszą obróbką wyników, w Node.js stosuje się zasadę asynchronicznego wykonania, tj. kod przekształca się w „db.query(„select..”, function (result) {obróbka wyniku});”, przy czym kontrola natychmiast przechodzi do dalszego kodu, a wynik zapytania jest przetwarzany na bieżąco.
Źródło: opennet.ru
