JavaScript w AIR



Środowisko AIR wprowadza kilka zmian do typowego działania typowych obiektów JavaScript. Wiele z tych obiektów ma na celu ułatwianie zapisu bezpiecznych aplikacji w środowisku AIR. Jednocześnie te różnice w działaniu sprawiają, że wykonywanie w środowisku AIR niektórych wspólnych wzorców kodowania JavaScript i istniejących aplikacji sieci Web korzystających z tych wzorców, może być niezgodne z oczekiwaniami. Informacje na temat postępowania w przypadku takich problemów zawiera sekcja Unikanie błędów JavaScript związanych z bezpieczeństwem.

Obszary izolowane HTML

Środowisko AIR umieszcza treść do obszarów izolowanych w zależności od źródła treści. Reguły dotyczące obszarów izolowanych są spójne ze strategiami z tych samych źródeł implementowanymi przez większość przeglądarek sieci Web, a także z regułami dot. obszarów izolowanych, które są implementowane przez program Adobe Flash Player. Ponadto środowisko AIR udostępnia nowy typ obszaru izolowanego aplikacji, który może zawierać i chronić treść aplikacji. Więcej informacji na temat typów obszarów izolowanych, jakie można napotkać podczas programowania aplikacji AIR zawiera sekcja Obszary izolowane.

Dostęp do środowiska wykonawczego oraz interfejsów API AIR jest możliwy tylko dla kodu HTML i JavaScript działającego w obszarze izolowanym aplikacji. Jednocześnie dynamiczna ocena i dynamiczne wykonywanie kodu JavaScript w różnych formach jest w znacznym stopniu ograniczone w obszarze izolowanym aplikacji z powodów związanych z bezpieczeństwem. Te ograniczenia obowiązują niezależnie od tego, czy aplikacja rzeczywiście ładuje informacje bezpośrednio z serwera. (Podejrzana może być nawet zawartość pliku, wklejane ciągi znaków oraz dane wprowadzane bezpośrednio przez użytkownika).

Źródło treści w pliku określa obszar izolowany, do którego treść zostaje przekazana. Do obszaru izolowanego aplikacji wprowadzana jest tylko treść z katalogu aplikacji (katalog instalacyjny, do którego odwołuje się schemat URL app:). Zawartość ładowana z pliku systemowego jest umieszczana w obszarze izolowanym lokalnym z systemem plików oraz lokalnym zaufanym, co umożliwia dostęp i interakcje z zawartością w lokalnym obszarze z systemem plików, ale nie z zawartością zdalną. Zawartość ładowana z sieci jest umieszczana w zdalnym obszarze izolowanym odpowiadającym domenie źródła.

Aby umożliwić aplikacji swobodne oddziaływanie z zawartością w zdalnym obszarze izolowanym, strona może zostać odwzorowana do tej samej domeny, do której odwzorowana została zawartość zdalna. Przykład: po napisaniu aplikacji, która wyświetla dane mapy z serwisu internetowego, możliwe jest odwzorowanie strony aplikacji, która ładuje i wyświetla treść z usługi, na domenę usługi. Atrybuty przeznaczone do odwzorowania stron na zdalny obszar izolowany oraz domenę to nowe atrybuty, które zostały dodane do elementów HTML ramek i ramek pływających.

Aby umożliwić zawartości w nieaplikacyjnym obszarze izolowanym bezpieczne korzystanie z funkcji AIR, można ustawić most nadrzędnego obszaru izolowanego. Aby umożliwić treści aplikacji bezpieczne wywoływanie metod i dostęp do właściwości treści w innych obszarach izolowanych, należy skonfigurować most podrzędnego obszaru izolowanego. W tym przypadku bezpieczeństwo oznacza, że w treści zdalnej nie mogą przypadkowo powstać odwołania do obiektów, właściwości lub metod, które nie są jawnie udostępniane. Przez most mogą być przekazywane tylko proste typy danych, funkcje i anonimowe obiekty. Jednak należy unikać jawnego udostępniania potencjalnie niebezpiecznych funkcji. Jeśli na przykład udostępniono interfejs, który umożliwiał treści zdalnej odczytywanie i zapisywanie plików w dowolnym miejscu w systemie użytkownika, może to oznaczać, że treść zdalna może w znacznym stopniu zaszkodzić użytkownikowi.

JavaScript eval(), funkcja

Korzystanie z funkcji eval() po zakończeniu ładowania strony jest ograniczone do obszaru izolowanego aplikacji. Niektóre zastosowania są dozwolone, dzięki czemu dane w formacie JSON mogą być bezpiecznie analizowane, ale wynikowe instrukcje wykonywalne zawsze kończą się błędem. Sekcja Ograniczenia kodu dotyczące treści różnych obszarów izolowanych zawiera opisy dozwolonych zastosowań funkcji eval().

Konstruktory funkcji

W obszarze izolowanym aplikacji konstruktory funkcji mogą być używane zanim nastąpi zakończenie ładowania strony. Po zakończeniu wszystkich zdarzeń load strony nie ma możliwości tworzenia nowych funkcji.

Ładowanie skryptów zewnętrznych

Strony HTML w obszarze izolowanym aplikacji nie mogą korzystać ze znacznika script w celu ładowania plików JavaScript z zewnątrz katalogu aplikacji. Strona w aplikacji może załadować skrypt spoza katalogu aplikacji tylko wówczas, gdy strona została odwzorowana na nieaplikacyjny obszar izolowany.

Obiekt XMLHttpRequest

Środowisko AIR udostępnia obiekt XMLHttpRequest (XHR), z którego aplikacje mogą korzystać w celu wykonywania żądań danych. Poniższy przykład ilustruje proste żądanie dot. danych:

xmlhttp = new XMLHttpRequest(); 
xmlhttp.open("GET", "http:/www.example.com/file.data", true); 
xmlhttp.onreadystatechange = function() { 
    if (xmlhttp.readyState == 4) { 
        //do something with data... 
    } 
} 
xmlhttp.send(null); 

Środowisko AIR — w odróżnieniu od przeglądarki — umożliwia treści działającej w obszarze izolowanym aplikacji żądanie danych z dowolnej domeny. Wynikiem żądania XHR, który zawiera ciąg znaków JSON, mogą być dane, chyba że wynik zawiera również kod wykonywalny. Jeśli wynik żądania XHR zawiera instrukcje wykonywalne, zgłaszany jest błąd, a próba oceny kończy się niepowodzeniem.

Aby zapobiec przypadkowemu wstrzykiwaniu kodu ze źródeł zdalnych, wywoływanie synchronicznego żądania XHR przed zakończeniem ładowania strony zwraca pusty wynik. Wywołanie asynchronicznych żądań XHR po załadowaniu strony zawsze zwraca wynik.

Domyślnie środowisko AIR blokuje międzydomenowe żądania XMLHttpRequest w nieaplikacyjnych obszarach izolowanych. Okno nadrzędne w obszarze izolowanym aplikacji może zezwolić na żądania międzydomenowe w ramce podrzędnej zawierającej treść w nieaplikacyjnym obszarze izolowanym poprzez ustawienie dla atrybutu allowCrossDomainXHR (jest to atrybut dodany przez AIR) wartości true w zawierającym elemencie ramki lub ramki pływającej:

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    allowCrossDomainXHR="true" 
</iframe>
Uwaga: W razie potrzeby klasa AIR URLStream może również służyć do pobierania danych.

W przypadku wywołania żądania XMLHttpRequest do serwera zdalnego z ramki lub ramki pływającej zawierającej treść aplikacji, która została odwzorowana do zdalnego obszaru izolowanego, należy się upewnić, że URL odwzorowania nie maskuje adresu serwera używanego w żądaniu XHR. Przykład: rozważmy poniższą definicję ramki pływającej, która odwzoruje treść aplikacji do zdalnego obszaru izolowanego, np. do domeny example.com:

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    documentRoot="app:/sandbox/" 
    sandboxRoot="http://www.example.com/" 
    allowCrossDomainXHR="true" 
</iframe>

Atrybut sandboxRoot ponownie odwzorowuje główny adres URL adresu www.example.com, dlatego wszystkie żądania są ładowane z katalogu aplikacji, a nie z serwera zdalnego. Żądania są ponownie odwzorowywane niezależnie od tego, czy pochodzą ze strony nawigacji, czy z żądania XMLHttpRequest.

Aby uniknąć przypadkowego zablokowania żądań danych w serwerze zdalnym, należy odwzorować sandboxRoot na podkatalog zdalnego adresu URL, a nie na katalog główny. Katalog nie musi istnieć. Przykład: aby umożliwić ładowanie żądań skierowanych do strony www.example.com z serwera zdalnego, a nie z serwera aplikacji, należy zmienić poprzednią ramkę pływającą na:

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    documentRoot="app:/sandbox/" 
    sandboxRoot="http://www.example.com/air/" 
    allowCrossDomainXHR="true" 
</iframe>

W takim przypadku tylko treść z podkatalogu air jest ładowana lokalnie.

Więcej informacji na temat odwzorowania obszaru izolowanego zawierają sekcje Elementy ramek i ramek pływających HTML oraz Zabezpieczenia HTML.

Obiekt Canvas

Obiekt Canvas definiuje interfejs API przeznaczony do rysowania kształtów geometrycznych, takich jak linie, łuki, elipsy i wielokąty. W celu korzystania z API canvas należy najpierw dodać element canvas do dokumentu, a następnie rysować w obiekcie za pomocą API JavaScript Canvas. Pod innymi względami obiekt Canvas działa jak obraz.

Poniższy przykład rysuje trójkąt za pomocą obiektu Canvas:

<html> 
<body> 
<canvas id="triangleCanvas" style="width:40px; height:40px;"></canvas> 
<script> 
    var canvas = document.getElementById("triangleCanvas"); 
    var context = canvas.getContext("2d"); 
    context.lineWidth = 3; 
    context.strokeStyle = "#457232"; 
    context.beginPath(); 
        context.moveTo(5,5); 
        context.lineTo(35,5); 
        context.lineTo(20,35); 
        context.lineTo(5,5); 
        context.lineTo(6,5); 
    context.stroke(); 
</script> 
</body> 
</html>

Więcej informacji na temat API Canvas zawiera dokumentacja Safari JavaScript Reference firmy Apple. Niedawno w projekcie Webkit rozpoczęto zmiany API Canvas w celu standaryzacji wersji roboczej HTML 5 zaproponowanej przez grupę WHATWG (Web Hypertext Application Technology Working Group) i W3C. W rezultacie część dokumentacji Safari JavaScript Reference może być niezgodna z wersją obiektu canvas dostępną w środowisku AIR.

Pliki cookie

W aplikacjach AIR tylko zawartość w zdalnych obszarach izolowanych (zawartość ładowana ze źródeł http: i https:) może korzystać z plików cookie (właściwość document.cookie). W obszarze izolowanym aplikacji interfejsy API AIR udostępniają inne sposoby zapisu danych trwałych (np. klasy EncryptedLocalStore i FileStream).

Obiekt Clipboard

Interfejs API Clipboard WebKit jest sterowany przez następujące zdarzenia: copy, cut i paste. Obiekt event przekazywany w tych zdarzeniach zapewnia dostęp do schowka za pośrednictwem właściwości clipboardData. Poniższe metody obiektu clipboardData służą do zapisywania i odczytywania danych schowka:

Metoda

Opis

clearData(mimeType)

Czyści dane schowka. Należy ustawić parametr mimeType na typ MIME danych do wyczyszczenia.

getData(mimeType)

Pobiera dane schowka. Ta metoda może zostać wywołana wyłącznie w module obsługi dla zdarzenia paste. Należy ustawić parametr mimeType na typ MIME danych do zwrócenia.

setData(mimeType, data)

Kopiowanie tekstu do schowka. Należy ustawić parametr mimeType na typ MIME danych.

Kod JavaScript poza obszarem izolowanym aplikacji może uzyskiwać dostęp do schowka wyłącznie za pośrednictwem tych zdarzeń. Jednak zawartość w obszarze izolowanym aplikacji może uzyskiwać dostęp do schowka systemowego bezpośrednio za pomocą klasy AIR Clipboard. Przykład: możliwe jest użycie następującej instrukcji w celu pobrania danych tekstowych ze schowka:

var clipping = air.Clipboard.generalClipboard.getData("text/plain", 
                                air.ClipboardTransferMode.ORIGINAL_ONLY);

Poprawne typy danych MIME:

Typ MIME

Wartość

Tekst

"text/plain"

HTML

"text/html"

URL

"text/uri-list"

Bitmapa

"image/x-vnd.adobe.air.bitmap"

Lista plików

"application/x-vnd.adobe.air.file-list"

Ważne: Dostęp do danych plików zawartych w skryptach ma tylko treść z obszaru izolowanego aplikacji. Jeśli treść nieaplikacyjna podejmuje próbę uzyskania dostępu do obiektu pliku ze schowka, zgłoszony zostaje błąd zabezpieczeń.

Więcej informacji na temat korzystania ze schowka zawiera sekcja Kopiowanie i wklejanie oraz sekcja Using the Pasteboard from JavaScript (Apple Developer Center).

Przeciąganie i upuszczanie

Gesty przeciągania i upuszczania do kodu HTML i na zewnątrz tego kodu powodują powstanie następujących zdarzeń DOM: dragstart, drag, dragend, dragenter, dragover, dragleave i drop. Obiekt zdarzenia przekazywany w tych zdarzeniach zapewnia dostęp do przeciągniętych danych za pośrednictwem właściwości dataTransfer. Właściwość dataTransfer odwołuje się do obiektu, który udostępnia te same metody, co obiekt clipboardData skojarzony ze zdarzeniem clipboard. Na przykład: można użyć następującej funkcji w celu pobrania danych tekstowych ze zdarzenia drop:

function onDrop(dragEvent){ 
    return dragEvent.dataTransfer.getData("text/plain",  
            air.ClipboardTransferMode.ORIGINAL_ONLY); 
}

Obiekt dataTransfer zawiera następujące ważne elementy:

Element

Opis

clearData(mimeType)

Czyści dane. Należy ustawić parametr mimeType na typ MIME reprezentacji danych przeznaczonych do wyczyszczenia.

getData(mimeType)

Pobiera przeciągnięte dane. Ta metoda może zostać wywołana wyłącznie w module obsługi dla zdarzenia drop. Należy ustawić parametr mimeType na typ MIME danych do pobrania.

setData(mimeType, data)

Ustawia dane do przeciągnięcia. Należy ustawić parametr mimeType na typ MIME danych.

types

Tablica ciągów znaków zawierająca typy MIME wszystkich danych aktualnie dostępnych w obiekcie dataTransfer.

effectsAllowed

Określa, czy dane przeciągane mogą być kopiowane, przenoszone, łączone lub czy możliwe jest wykonywanie kombinacji tych czynności. Właściwość effectsAllowed w module obsługi należy ustawić na zdarzenie dragstart.

dropEffect

Określa dozwolone efekty przeciągania, które są obsługiwane przez cel przeciągania. Należy ustawić właściwość dropEffect w module obsługi na zdarzenie dragEnter. Podczas przeciągania kursor zmienia się w celu wskazania efektu, jaki będzie miało zwolnienie przycisku myszy. Jeśli nie określono wartości dropEffect, wybierany jest efekt metody effectsAllowed. Efekt kopiowania ma priorytet wyższy niż efekt przeciągania, który ma priorytet wyższy od efektu łączenia. Użytkownik może za pomocą klawiatury zmodyfikować domyślną właściwość.

Więcej informacji na temat dodawania funkcji obsługi operacji przeciągania i upuszczania do aplikacji AIR zawiera sekcja Przeciąganie i upuszczanie oraz sekcja Using the Drag-and-Drop from JavaScript (Apple Developer Center).

Właściwości innerHTML i outerHTML

Środowisko AIR definiuje ograniczenia dotyczące korzystania z właściwości innerHTML i outerHTML dla treści działającej w obszarze izolowanym aplikacji. Przed zdarzeniem ładowania strony, a także podczas działania modułów obsługi zdarzeń ładowania, korzystanie z właściwości innerHTML i outerHTML jest nieograniczone. Jednak po załadowaniu strony można korzystać tylko z właściwości innerHTML lub outerHTML w celu dodawania do dokumentu treści statycznych. Wszelkie instrukcje w ciągu znaków przypisanym do właściwości innerHTML lub outerHTML, które dotyczą kodu wykonywalnego, są ignorowane. Na przykład: w przypadku dołączenia atrybutu wywołania zdarzenia do definicji elementu detektor zdarzenia nie jest dodawany. I podobnie — osadzone znaczniki <script> również są ignorowane. Więcej informacji zawiera sekcja Zabezpieczenia HTML.

Metody Document.write() i Document.writeln()

Przed wystąpieniem zdarzenia loadstrony stosowanie metod write() i writeln() w obszarze izolowanym aplikacji nie jest ograniczone. Jednak po załadowaniu strony wywołanie dowolnej z tych metod nie powoduje wyczyszczenia strony ani utworzenia nowej. W nieaplikacyjnym obszarze izolowanym, jak w większości przeglądarek internetowych, wywołanie metody document.write() lub writeln() po zakończeniu ładowania strony powoduje wyczyszczenie bieżącej strony i otwarcie nowej, pustej.

Document.designMode, właściwość

Aby umożliwić edycję wszystkich elementów w dokumencie, należy ustawić dla właściwości document.designMode wartość on. Wbudowane funkcje obsługi edytora obsługują edytowanie, kopiowanie, wklejanie oraz przeciąganie i upuszczanie tekstu. Ustawienie dla właściwości designMode wartości on jest równoważne ustawieniu właściwości contentEditable elementu body na wartość true. Właściwość contentEditable może być używana w większości elementów HTML w celu określenia w dokumencie sekcji dostępnych do edycji. Dodatkowe informacje zawiera sekcja Atrybut contentEditable HTML.

Zdarzenia unload (dla obiektów body i frameset)

W znaczniku frameset lub body najwyższego poziomu okna (łącznie z głównym oknem aplikacji) nie należy używać zdarzenia unload w celu reagowania na zamykane okno (lub aplikację). Zamiast tego należy użyć zdarzenia exiting obiektu NativeApplication (w celu wykrycia zamykania aplikacji). Lub należy użyć zdarzenia closing obiektu NativeWindow (w celu wykrycia zamykania okna). Przykład: poniższy kod JavaScript wyświetla komunikat ("Goodbye."), gdy użytkownik zamyka aplikację:

var app = air.NativeApplication.nativeApplication; 
app.addEventListener(air.Event.EXITING, closeHandler); 
function closeHandler(event) 
{ 
    alert("Goodbye."); 
}

Jednak skrypty mogą pomyślnie odpowiadać na zdarzenie unload wywołane poprzez nawigowanie w ramce, ramce pływającej lub w treści w oknie najwyższego poziomu.

Uwaga: Te ograniczenia mogą zostać usunięte w przyszłych wersjach środowiska Adobe AIR.

Obiekt JavaScript Window

Obiekt Window pozostaje globalnym obiektem w kontekście wykonywania kodu JavaScript. W obszarze izolowanym aplikacji środowisko AIR dodaje nowe właściwości do obiektu JavaScript Window w celu zapewnienia dostępu do wbudowanych klas AIR, a także ważnych obiektów obsługiwanych. Ponadto niektóre metody i właściwości działają różnie w zależności od tego, czy znajdują się w obszarze izolowanym aplikacji, czy nie.

Window.runtime, właściwość
Właściwość runtime umożliwia tworzenie instancji oraz korzystanie z wbudowanych klas środowiska wykonawczego z obszaru izolowanego aplikacji. Do tych klas należą interfejsy API AIR i Flash Player (ale nie należy np. struktura Flex). Na przykład: poniższa instrukcja tworzy obiekt pliku AIR:
var preferencesFile = new window.runtime.flash.filesystem.File();

Plik AIRAliases.js dostępny w pakiecie SDK AIR zawiera definicje aliasów, które umożliwiają skrócenie takich odwołań. Na przykład: jeśli plik AIRAliases.js zostanie zaimportowany na stronę, wówczas obiekt File może zostać utworzony za pomocą poniższej instrukcji:

var preferencesFile = new air.File();

Właściwość window.runtime jest zdefiniowana tylko dla treści w obszarze izolowanym aplikacji oraz tylko dla dokumentu nadrzędnego strony w ramkach i ramkach pływających.

Patrz Korzystanie z pliku AIRAliases.js.

Właściwość Window.nativeWindow
Właściwość nativeWindow udostępnia odwołanie do podstawowego rodzimego obiektu window. Za pomocą tej właściwości można pisać skrypty dot. funkcji okien oraz właściwości, takich jak położenie na ekranie, wielkość i widoczność. Ta właściwość służy również do obsługi zdarzeń window, takich jak zamykanie, zmiana wielkości i przenoszenie. Na przykład: poniższa instrukcja zamyka okno:
window.nativeWindow.close();
Uwaga: Funkcje sterowania oknami udostępnione przez obiekt NativeWindow zastępują funkcje udostępnione przez obiekt JavaScript Window. W takich przypadkach możliwe jest korzystanie z dowolnej metody.

Właściwość window.nativeWindow jest zdefiniowana tylko dla treści w obszarze izolowanym aplikacji oraz tylko dla dokumentu nadrzędnego strony w ramkach i ramkach pływających.

Właściwość Window.htmlLoader
Właściwość htmlLoader udostępnia odwołanie do obiektu AIR HTMLLoader, który zawiera treść HTML. Za pomocą tej właściwości można tworzyć skrypty określające wygląd i działanie środowiska HTML. Na przykład: za pomocą właściwości htmlLoader.paintsDefaultBackground można określić, czy element sterowania będzie miał domyślne białe tło:
window.htmlLoader.paintsDefaultBackground = false;
Uwaga: Obiekt HTMLLoader ma właściwość window, która odwołuje się do obiektu JavaScript Window treści HTML, jaką zawiera. Za pomocą tej właściwości można uzyskać dostęp do środowiska JavaScript za pośrednictwem odwołania do zawierającego obiektu HTMLLoader.

Właściwość window.htmlLoader jest zdefiniowana tylko dla treści w obszarze izolowanym aplikacji oraz tylko dla dokumentu nadrzędnego strony w ramkach i ramkach pływających.

Właściwości Window.parentSandboxBridge i Window.childSandboxBridge
Właściwości parentSandboxBridge i childSandboxBridge umożliwiają zdefiniowanie połączenia między ramką nadrzędną i podrzędną. Więcej informacji zawiera sekcja Treść odwołująca się do skryptów w różnych bezpiecznych obszarach izolowanych.

Funkcje Window.setTimeout() i Window.setInterval()
Środowisko AIR definiuje ograniczenia dotyczące korzystania z funkcji setTimeout() i setInterval() w obszarze izolowanym aplikacji. Poprzez wywołanie funkcji setTimeout() lub setInterval() nie można zdefiniować kodu, jaki powinien zostać wywołany, w postaci ciągu znaków. W tym celu należy użyć odwołania do funkcji. Więcej informacji zawiera sekcja setTimeout() i setInterval().

Funkcja Window.open()
Metoda open() wywołana przez kod działający w nieaplikacyjnym obszarze izolowanym otwiera okno tylko wówczas, gdy zostaje wywołana w wyniku interakcji użytkownika (np. kliknięcia lub naciśnięcia klawisza). Ponadto przed tytułem okna umieszczony zostaje tytuł aplikacji (dzięki czemu okna otwierane przez treści zdalne nie uosabiają okien otwieranych przez aplikację). Więcej informacji zawiera sekcja Ograniczenia dotyczące wywoływania metody window.open() JavaScript.

Obiekt air.NativeApplication

Obiekt NativeApplication udostępnia informacje o stanie aplikacji, wywołuje kilka ważnych zdarzeń na poziomie aplikacji oraz udostępnia użyteczne funkcje przeznaczone do kontrolowania działania aplikacji. Pojedyncza instancja obiektu NativeApplication jest tworzona automatycznie i można do niej uzyskać dostęp przez właściwość NativeApplication.nativeApplication zdefiniowaną przez klasę.

Aby uzyskać dostęp do obiektu z kodu JavaScript można użyć kodu:

var app = window.runtime.flash.desktop.NativeApplication.nativeApplication;

Lub jeśli zaimportowano skrypt AIRAliases.js, można użyć krótszej formy:

var app = air.NativeApplication.nativeApplication;

Dostęp do obiektu NativeApplication można uzyskać tylko z obszaru izolowanego aplikacji. Sekcja Praca z informacjami o środowisku wykonawczym i systemie operacyjnym opisuje szczegółowo obiekt NativeApplication.

Schemat URL JavaScript

Wykonywanie kodu zdefiniowanego w schemacie JavaScript URL (np. href="javascript:alert('Test')") jest blokowane w obszarze izolowanym aplikacji. Nie jest zgłaszany żaden błąd.