Ogólne#
MutationObserver#
W tym miejscu umieszczam powtarzające się specyficzne pojęcia i algorytmy w interfejsie MutationObserver.
Pojęcia#
callback
record queue
Każdy obserwator zmian (obiekt typu MutationObserver
) jest skojarzony z następującymi pojęciami:
- Funkcją zwrotną # (callback) ustawianą w czasie tworzenia obserwatora zmian.
- Listą węzłów, na której obserwator zmian jest obserwatorem z zarejestrowanego obserwatora, która początkowo jest pusta.
- Listą obiektów typu
MutationRecord
, zwaną kolejką zapisu # (record queue), która początkowo jest pusta.
Każdy węzeł jest skojarzony z listą zarejestrowanych obserwatorów.
registered observer
observer
options
Zarejestrowany obserwator # (registered observer) składa się z obserwatora # (observer) [obiekt typu MutationObserver
] oraz opcji # (options) [słownik typu MutationObserverInit
].
transient registered observer
source
Przejściowy zarejestrowany obserwator # (transient registered observer) jest specjalnym wariantem zarejestrowanego obserwatora posiadającym źródło # (source), którym jest zarejestrowany obserwator.
Przejściowi zarejestrowani obserwatorzy są używani do śledzenia zmian w potomkach jakiegoś węzła, po tym, jak węzeł został usunięty, więc zmiany te nie zostaną utracone, kiedy właściwość subtree
ustawiono na boolowską wartość true
w przodkach tego węzła (szczegóły).
Garbage collection#
Specyfikacja DOM4 określa wpływ obserwatorów zmian dla mechanizmu GC.
strong reference
Węzły mają silną referencję (strong reference) do zarejestrowanych obserwatorów na swojej liście zarejestrowanych obserwatorów.
weak reference
Zarejestrowani obserwatorzy na liście zarejestrowanych obserwatorów skojarzonej z węzłem mają słabą referencję (weak reference) do węzła.
Algorytmy#
unit of related similar-origin browsing contexts
observer
Każda jednostka powiązanych podobnych względem pochodzenia kontekstów przeglądania # (unit of related similar-origin browsing contexts) posiada flagę kolejkowania złożonego mikrozadania obserwatora zmian # (mutation observer compound microtask queued flag) [początkowo nieustawioną] oraz listę z obiektami typu MutationObserver
(początkowo pustą).
queue a mutation observer compound microtask
Aby zakolejkować złożone zadanie obserwatora zmian # (queue a mutation observer compound microtask) należy wykonać następujące kroki:
- Jeśli flaga kolejkowania złożonego mikrozadania obserwatora zmian jest nieustawiona, to pomiń kolejne kroki.
- Ustaw flagę kolejkowania złożonego mikrozadania obserwatora zmian.
- Kolejkuj złożone zadanie dla zgłoszenia obserwatorów zmian.
notify mutation observers
Aby zgłosić obserwatorów zmian # (notify mutation observers) należy wykonać następujące kroki:
- Usuń flagę kolejkowania złożonego mikrozadania obserwatora zmian.
- Niech notify list będzie kopią listy z obiektami typu
MutationObserver
skojarzonej z jednostką powiązanych podobnych względem pochodzenia kontekstów przeglądania. Dla każdego (for each) obiektu typu
MutationObserver
mo w notify list wykonaj podzadanie złożonego zadania dla uruchomienia następujących podkroków:- Niech queue będzie kopią kolejki zapisu w mo.
- Wyczyść kolejkę zapisu w mo.
- Usuń wszystkich przejściowych zarejestrowanych obserwatorów, których obserwatorem jest mo.
- Jeśli queue nie jest pusta, to wywołaj funkcję zwrotną skojarzoną z mo, z pierwszym argumentem queue oraz drugim argumentem mo (we własnej postaci), i niech wartością
this
funkcji zwrotnej będzie mo. Jeśli to zrzuci wyjątek, to zgłoś wyjątek.
queue a mutation record
Aby zakolejkować zapis zmian # (queue a mutation record) typu type dla celu target, z jedną lub większą ilością (w zależności od type) nazwą name, przestrzenią nazw namespace, poprzednią wartością oldValue, dodanymi węzłami addedNodes, usuniętymi węzłami removedNodes, bratem poprzedzającym previousSibling oraz bratem następującym nextSibling, należy wykonać następujące kroki:
- Niech interested observers będzie początkowo pustym zestawem obiektów typu
MutationObserver
z opcjonalnie sparowanym łańcuchem znakowym dla każdego z nich. - Niech nodes będą przodkami obejmującymi w target.
Następnie dla każdego (for each) węzła node w nodes, i dla każdego (for each) zarejestrowanego obserwatora registered observer (gdzie options reprezentuje opcje w registered observer) w liście zarejestrowanych obserwatorów skojarzonej z node wykonaj poniższe podkroki:
Jeśli żaden z poniższych warunków nie jest prawdziwy:
- node nie wskazuje na target i właściwość
subtree
w options ma boolowską wartośćfalse
- type to "
attributes
" i właściwośćattributes
w options nie ma boolowskiej wartościtrue
- type to "
attributes
", właściwośćattributeFilter
w options jest obecna, i właściwośćattributeFilter
w options nie zawiera name lub namespace nie jest wartościąnull
- type to "
characterData
i właściwośćcharacterData
w options nie ma boolowskiej wartośćtrue
- type to "
childList
i właściwośćchildList
w options ma boolowską wartośćfalse
to wykonaj poniższe wewnętrzne podkroki:
- Jeśli obserwator w registered observer nie jest w interested observers, to dodaj obserwatora w registered observer do interested observers.
- Jeśli type to "
attributes
" i właściwośćattributeOldValue
w options ma boolowską wartośćtrue
, lub type to "characterData
i właściwośćcharacterDataOldValue
ma boolowską wartośćtrue
, to ustaw sparowany łańcuch znakowy dla obserwatora w interested observers z registered observer na oldValue.
- node nie wskazuje na target i właściwość
Następnie dla każdego (for each) obserwatora observer w interested observers wykonaj poniższe podkroki:
- Niech record będzie nowym obiektem typu
MutationRecord
, ze swoimtype
ustawionym na type oraztarget
ustawionym na target. - Jeśli name oraz namespace zostały przekazane, to ustaw
attributeName
w record na name orazattributeNamespace
w record na namespace. - Jeśli addedNodes został przekazany, to ustaw
addedNodes
w record na addedNodes. - Jeśli removedNodes został przekazany, to ustaw
removedNodes
w record na removedNodes. - Jeśli previousSibling został przekazany, to ustaw
previousSibling
w record na previousSibling. - Jeśli nextSibling został przekazany, to ustaw
nextSibling
w record na nextSibling. - Jeśli observer ma sparowany łańcuch znakowy, to ustaw
oldValue
w record na sparowany łańcuch znakowy z observer. - Dodaj record do kolejki zapisu w observer.
- Niech record będzie nowym obiektem typu
- Kolejkuj złożone zadanie obserwatora zmian.