CSC/ECE 517 Spring 2017/M1702 Implement the Mutation Observer API Design
Mutation Observer API Project with SERVO & RUST
Servo is a prototype web browser engine written in the RUST language. The DOM standard defines a MutationObserver API that allows web content to receive callbacks when the page contents are mutated. In simple words, MutationObserver facilitates the developers with a technique to react to the changes in DOM. MutationObserver is designed to replace the Mutation Events defined in the DOM3 Events specification. The goal of this project is to implement the fundamental pieces required to support the Mutation Observer API.
Introduction
Servo
Servo is an open source web browser engine designed for application and embedded use. It is a high performance browser engine created by Mozilla Research and is written in the Rust language. The main idea behind the Servo is to create a parallel environment where the components are handle by isolated and fine grained tasks. These components can be rendering, HTML parsing etc.
Rust
Rust is an open source systems programming language developed by Mozilla. Servo is written in Rust. The main purpose behind it's design is to be thread safe and concurrent. The emphasis is also on speed, safety and control of memory layout.
Setting up and Building the Project
Follow the Guidelines mentioned in the read me page of the project's Wiki Page for building the Project in a Linux Environment.
Project Description
The purpose of this project is to implement the basic functionality required to implement a Mutation Observer API as defined in the DOM Specifications. In the First Phase of the Project, we implemented the initial Steps as described in the Project Specification. The initial implementation is merged in the original Servo Repository and the code can be found here. For the next phase of the project, we have to implement the functionality for supporting Mutation Observers. We plan on acheiving that in the following steps:
Add support for mutation observer microtasks
- We will add a
mutation_observer_compound_microtask_queued
member toScriptThread
. This will be used later to implement the queue a mutation observer compound microtask algorithm described below. - Next, we are going to implement the queue a mutation observer compound microtask algorithm by adding a new variant to the Microtask enum for mutation observers.
- Initially, if mutation observer compound microtask queued flag is set, then we return.
- We have to set mutation observer compound microtask queued flag.
- The later step will be to queue a compound microtask to notify mutation observers.
- We will implement the notify mutation observers algorithm (ignoring the specific text about "execute a compound microtask") using the vector of observers previously added to
ScriptThread
. The notify mutation observers algorithm is as below:- For this, we need to unset mutation observer compound microtask queued flag set in the previous algorithm.
- We will declare notifyList to be a copy of unit of related similar-origin browsing contexts' list of MutationObserver objects.
- Also, we will declare signalList to be a copy of unit of related similar-origin browsing contexts' signal slot list.
- We need to empty unit of related similar-origin browsing contexts' signal slot list.
- For each MutationObserver object mo in notifyList, we shall execute a compound microtask subtask to run these steps:
- Declare queue to contain mo's record queue.
- mo's record queue will be emptied.
- All transient registered observers whose observer is mo will be removed.
- If queue is non-empty, invoke mo’s callback with a list of arguments consisting of queue and mo, and mo as the callback this value. If this throws an exception, report the exception.
- For each slot slot in signalList, in order, we shall fire an event named slotchange, with its bubbles attribute set to true, at slot.
Add support for observing specific mutations
- Firstly we will add a vector of
MutationObserver
objects toNode
. - Then we will implement observe method of MutationObserver. As per the DOM specification, the observe method has the following behaviour:
- If either options’
attributeOldValue
orattributeFilter
is present and options’attributes
is omitted, then we set the options’ attributes totrue
. - If options’ characterDataOldValue is present and options’ characterData is omitted, then we set options’ characterData to true.
- If none of options’ childList, attributes, and characterData is true, then we throw a TypeError.
- If options’ attributeOldValue is true and options’ attributes is false, then we throw a TypeError.
- If options’ attributeFilter is present and options’ attributes is false, then we throw a TypeError.
- If options’ characterDataOldValue is true and options’ characterData is false, then we throw a TypeError.
- For each observer registered in target’s list of registered observers whose observer is the context object we perform the following steps:
- We remove all transient registered observers whose source is registered.
- We also replace registered’s options with options.
- Otherwise, we add a new registered observer to target’s list of registered observers with the context object as the observer and options as the options, and then also, we add target to context object’s list of nodes on which it is registered.
- If either options’
- The last two steps above mean we replace an existing matching entry with the new options, or add a new entry if there is no match.
- We will implement the queue a mutation record algorithm.
- We will make changing/appending/removing/replacing an attribute queue a mutation record via Attr::set_value, Element::push_attribute, and Element::remove_first_matching_attribute.
Test Plan
In the First Phase of the Project,, our tests were written with regard to attributes, Childlist, Character data and records of a Mutation Observer. These tests are present in web-platform-tests directory (i.e .tests/wpt/web-platform-tests/dom/nodes
).
For this part of the project, our test plan is to check the following:
- Test the micro task for mutation observer.
- Check if microtask queued flag is initially unset.
- Check if the task returns on setting the microtask queued flag.
The web-platform tests can be run by giving the following command at the root directory of the project:
./mach test-wpt tests/wpt/web-platform-tests/dom/nodes.
We have Updated the corresponding test expectations as per the given guidelines in the tests/wpt/metadata/dom/nodes/
directory.
Design Pattern
Our Project follows the Observer Pattern, where a list of the objects dependent on the current object is maintained and the dependents are notified of any state changes. The Mutation Observer helps in achieving this functionality.
References
1. https://doc.rust-lang.org/stable/book/
2. https://en.wikipedia.org/wiki/Rust_(programming_language)
3. https://en.wikipedia.org/wiki/Servo_(layout_engine)
4. https://github.com/servo/servo
5. https://github.com/servo/servo/wiki/Mutation-observer-project
6. https://dom.spec.whatwg.org/