///|
fn Parser::active_formatting_index_by_node(
self : Parser,
target : @dom.Node,
) -> Int {
let mut index = self.active_formatting.length()
while index > 0 {
index -= 1
let entry = self.active_formatting[index]
if !entry.marker && physical_equal(entry.node, target) {
return index
}
}
-1
}
///|
fn Parser::stack_index_by_node(self : Parser, target : @dom.Node) -> Int {
let mut index = 0
while index < self.stack.length() {
if physical_equal(self.stack[index], target) {
return index
}
index += 1
}
-1
}
///|
fn Parser::adoption_agency(
self : Parser,
subject : StringView,
pos : Int,
) -> Unit {
let subject_name = subject.to_owned()
match self.stack.last() {
Some(current) if current.kind == Element &&
current.name == subject_name &&
self.active_formatting_index(subject) < 0 => {
ignore(self.close_open_element(subject_name))
return
}
_ => ()
}
for _ in 0..<8 {
let formatting_index = self.active_formatting_index(subject)
if formatting_index < 0 {
self.error_at("adoption-agency-1.3", pos)
return
}
let formatting_element = self.active_formatting[formatting_index].node
let formatting_open_index = self.stack_index_by_node(formatting_element)
if formatting_open_index < 0 {
self.error_at("adoption-agency-1.3", pos)
self.remove_active_formatting_index(formatting_index)
return
}
if !self.has_open_element_in_default_scope(formatting_element.name) {
self.error_at("adoption-agency-1.3", pos)
return
}
match self.stack.last() {
Some(current) if !physical_equal(current, formatting_element) =>
self.error_at("adoption-agency-1.3", pos)
_ => ()
}
let mut furthest_block_index = -1
let mut index = formatting_open_index + 1
while index < self.stack.length() {
let candidate = self.stack[index]
if candidate.kind == Element &&
is_special_element_for_any_other_end_tag(candidate.name) {
furthest_block_index = index
break
}
index += 1
}
if furthest_block_index < 0 {
while self.stack.length() > 1 {
match self.stack.pop() {
Some(node) if physical_equal(node, formatting_element) => break
_ => ()
}
}
self.remove_active_formatting_index(formatting_index)
return
}
let furthest_block = self.stack[furthest_block_index]
let mut bookmark = formatting_index + 1
let mut last_node = furthest_block
let mut node_index = furthest_block_index
let mut inner_loop_counter = 0
while true {
inner_loop_counter += 1
node_index -= 1
let node = self.stack[node_index]
if physical_equal(node, formatting_element) {
break
}
let mut node_formatting_index = self.active_formatting_index_by_node(node)
if inner_loop_counter > 3 && node_formatting_index >= 0 {
self.remove_active_formatting_index(node_formatting_index)
if node_formatting_index < bookmark {
bookmark -= 1
}
node_formatting_index = -1
}
if node_formatting_index < 0 {
ignore(self.stack.remove(node_index))
continue
}
let entry = self.active_formatting[node_formatting_index]
let new_node = element_from_formatting_entry(entry)
self.active_formatting[node_formatting_index] = formatting_entry_with_node(
entry, new_node,
)
self.stack[node_index] = new_node
if physical_equal(last_node, furthest_block) {
bookmark = node_formatting_index + 1
}
new_node.append_child(last_node)
last_node = new_node
}
let common_ancestor = self.stack[formatting_open_index - 1]
common_ancestor.append_child(last_node)
let entry = self.active_formatting[formatting_index]
let new_formatting_element = element_from_formatting_entry(entry)
self.active_formatting[formatting_index] = formatting_entry_with_node(
entry, new_formatting_element,
)
let moved_children = furthest_block.children.copy()
for child in moved_children {
new_formatting_element.append_child(child)
}
furthest_block.append_child(new_formatting_element)
let replacement_entry = self.active_formatting[formatting_index]
self.remove_active_formatting_index(formatting_index)
bookmark -= 1
self.active_formatting.insert(bookmark, replacement_entry)
ignore(self.remove_open_node(formatting_element))
let furthest_index = self.stack_index_by_node(furthest_block)
self.stack.insert(furthest_index + 1, new_formatting_element)
}
}