Implement ProcessingInstruction DOM interface

Spec:
http://dom.spec.whatwg.org/#interface-processinginstruction

Closes #1619.
This commit is contained in:
Bruno de Oliveira Abinader 2014-02-05 11:14:47 -04:00
parent 5a7d22c437
commit aa4b5bb948
8 changed files with 153 additions and 56 deletions

View file

@ -36,7 +36,8 @@ use layout::wrapper::{PostorderNodeMutTraversal, TLayoutNode, ThreadSafeLayoutNo
use gfx::font_context::FontContext;
use script::dom::element::{HTMLIframeElementTypeId, HTMLImageElementTypeId};
use script::dom::node::{CommentNodeTypeId, DoctypeNodeTypeId, DocumentFragmentNodeTypeId};
use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, TextNodeTypeId};
use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId};
use script::dom::node::{TextNodeTypeId};
use style::computed_values::{display, position, float, white_space};
use style::ComputedValues;
@ -633,7 +634,8 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
CommentNodeTypeId |
DoctypeNodeTypeId |
DocumentFragmentNodeTypeId |
DocumentNodeTypeId(_) => (display::none, float::none, position::static_),
DocumentNodeTypeId(_) |
ProcessingInstructionNodeTypeId => (display::none, float::none, position::static_),
};
debug!("building flow for node: {:?} {:?}", display, float);
@ -701,6 +703,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
fn is_replaced_content(self) -> bool {
match self.type_id() {
TextNodeTypeId |
ProcessingInstructionNodeTypeId |
CommentNodeTypeId |
DoctypeNodeTypeId |
DocumentFragmentNodeTypeId |

View file

@ -583,6 +583,7 @@ def addExternalIface(iface, nativeType=None, headerFile=None, pointerType=None):
domInterface['pointerType'] = pointerType
DOMInterfaces[iface] = domInterface
# FIXME: This should be renamed: https://github.com/mozilla/servo/issues/1625
def addHTMLElement(element, concrete=None, needsAbstract=[]):
DOMInterfaces[element] = {
'nativeType': 'AbstractNode',
@ -596,6 +597,7 @@ addHTMLElement('Comment')
addHTMLElement('DocumentFragment', concrete='DocumentFragment')
addHTMLElement('DocumentType')
addHTMLElement('Text')
addHTMLElement('ProcessingInstruction')
addHTMLElement('HTMLAnchorElement')
addHTMLElement('HTMLAppletElement')

View file

@ -107,6 +107,9 @@ generate_traceable_node!(DocumentType)
generate_cacheable_wrapper!(Text, TextBinding::Wrap)
generate_traceable!(Text)
generate_cacheable_wrapper!(ProcessingInstruction, ProcessingInstruction::Wrap)
generate_traceable!(ProcessingInstruction)
generate_cacheable_wrapper_htmlelement!(HTMLHeadElement, HTMLHeadElementBinding::Wrap)
generate_traceable_htmlelement!(HTMLHeadElement)

View file

@ -5,7 +5,9 @@
use servo_util::namespace;
use dom::attr::Attr;
use dom::node::NodeIterator;
use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId, DocumentNodeTypeId, ElementNodeTypeId, TextNodeTypeId, AbstractNode};
use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId};
use dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId};
use dom::node::{TextNodeTypeId, AbstractNode};
pub fn serialize(iterator: &mut NodeIterator) -> ~str {
let mut html = ~"";
@ -29,6 +31,9 @@ pub fn serialize(iterator: &mut NodeIterator) -> ~str {
DoctypeNodeTypeId => {
serialize_doctype(node)
}
ProcessingInstructionNodeTypeId => {
serialize_processing_instruction(node)
}
DocumentFragmentNodeTypeId => {
~""
}
@ -70,6 +75,12 @@ fn serialize_text(node: AbstractNode) -> ~str {
})
}
fn serialize_processing_instruction(node: AbstractNode) -> ~str {
node.with_imm_processing_instruction(|processing_instruction| {
~"<?" + processing_instruction.target + " " + processing_instruction.element.data + "?>"
})
}
fn serialize_doctype(node: AbstractNode) -> ~str {
node.with_imm_doctype(|doctype| {
~"<!DOCTYPE" + doctype.name + ">"

View file

@ -18,6 +18,7 @@ use dom::htmliframeelement::HTMLIFrameElement;
use dom::htmlimageelement::HTMLImageElement;
use dom::nodelist::{NodeList};
use dom::text::Text;
use dom::processinginstruction::ProcessingInstruction;
use layout_interface::{LayoutChan, ReapLayoutDataMsg, UntrustedNodeAddress};
use js::jsapi::{JSContext, JSObject, JSRuntime};
@ -199,6 +200,7 @@ pub enum NodeTypeId {
DocumentNodeTypeId(DocumentTypeId),
ElementNodeTypeId(ElementTypeId),
TextNodeTypeId,
ProcessingInstructionNodeTypeId,
}
impl Clone for AbstractNode {
@ -362,8 +364,7 @@ impl<'a> AbstractNode {
// FIXME: This should be doing dynamic borrow checking for safety.
pub fn is_characterdata(self) -> bool {
// FIXME: ProcessingInstruction
self.is_text() || self.is_comment()
self.is_text() || self.is_comment() || self.is_processing_instruction()
}
pub fn with_imm_characterdata<R>(self, f: |&CharacterData| -> R) -> R {
@ -432,6 +433,18 @@ impl<'a> AbstractNode {
self.transmute_mut(f)
}
#[inline]
pub fn is_processing_instruction(self) -> bool {
self.type_id() == ProcessingInstructionNodeTypeId
}
pub fn with_imm_processing_instruction<R>(self, f: |&ProcessingInstruction| -> R) -> R {
if !self.is_processing_instruction() {
fail!("node is not processing instruction");
}
self.transmute(f)
}
// FIXME: This should be doing dynamic borrow checking for safety.
pub fn with_imm_element<R>(self, f: |&Element| -> R) -> R {
if !self.is_element() {
@ -920,8 +933,9 @@ impl Node {
match self.type_id {
ElementNodeTypeId(_) => 1,
TextNodeTypeId => 3,
ProcessingInstructionNodeTypeId => 7,
CommentNodeTypeId => 8,
DocumentNodeTypeId(_)=> 9,
DocumentNodeTypeId(_) => 9,
DoctypeNodeTypeId => 10,
DocumentFragmentNodeTypeId => 11,
}
@ -934,8 +948,13 @@ impl Node {
element.TagName()
})
}
CommentNodeTypeId => ~"#comment",
TextNodeTypeId => ~"#text",
ProcessingInstructionNodeTypeId => {
abstract_self.with_imm_processing_instruction(|processing_instruction| {
processing_instruction.Target()
})
}
CommentNodeTypeId => ~"#comment",
DoctypeNodeTypeId => {
abstract_self.with_imm_doctype(|doctype| {
doctype.name.clone()
@ -955,6 +974,7 @@ impl Node {
ElementNodeTypeId(..) |
CommentNodeTypeId |
TextNodeTypeId |
ProcessingInstructionNodeTypeId |
DoctypeNodeTypeId |
DocumentFragmentNodeTypeId => Some(self.owner_doc()),
DocumentNodeTypeId(_) => None
@ -991,8 +1011,9 @@ impl Node {
pub fn GetNodeValue(&self, abstract_self: AbstractNode) -> Option<DOMString> {
match self.type_id {
// ProcessingInstruction
CommentNodeTypeId | TextNodeTypeId => {
CommentNodeTypeId |
TextNodeTypeId |
ProcessingInstructionNodeTypeId => {
abstract_self.with_imm_characterdata(|characterdata| {
Some(characterdata.Data())
})
@ -1010,7 +1031,8 @@ impl Node {
pub fn GetTextContent(&self, abstract_self: AbstractNode) -> Option<DOMString> {
match self.type_id {
DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => {
DocumentFragmentNodeTypeId |
ElementNodeTypeId(..) => {
let mut content = ~"";
for node in abstract_self.traverse_preorder() {
if node.is_text() {
@ -1021,12 +1043,15 @@ impl Node {
}
Some(content)
}
CommentNodeTypeId | TextNodeTypeId => {
CommentNodeTypeId |
TextNodeTypeId |
ProcessingInstructionNodeTypeId => {
abstract_self.with_imm_characterdata(|characterdata| {
Some(characterdata.Data())
})
}
DoctypeNodeTypeId | DocumentNodeTypeId(_) => {
DoctypeNodeTypeId |
DocumentNodeTypeId(_) => {
None
}
}
@ -1101,7 +1126,7 @@ impl Node {
}
DocumentFragmentNodeTypeId |
ElementNodeTypeId(_) |
// ProcessingInstructionNodeTypeId |
ProcessingInstructionNodeTypeId |
CommentNodeTypeId => (),
DocumentNodeTypeId(..) => return Err(HierarchyRequest)
}
@ -1175,7 +1200,7 @@ impl Node {
}
},
TextNodeTypeId |
// ProcessingInstructionNodeTypeId |
ProcessingInstructionNodeTypeId |
CommentNodeTypeId => (),
DocumentNodeTypeId(_) => unreachable!(),
}
@ -1319,7 +1344,8 @@ impl Node {
-> ErrorResult {
let value = null_str_as_empty(&value);
match self.type_id {
DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => {
DocumentFragmentNodeTypeId |
ElementNodeTypeId(..) => {
// Step 1-2.
let node = if value.len() == 0 {
None
@ -1330,7 +1356,9 @@ impl Node {
// Step 3.
Node::replace_all(node, abstract_self);
}
CommentNodeTypeId | TextNodeTypeId => {
CommentNodeTypeId |
TextNodeTypeId |
ProcessingInstructionNodeTypeId => {
self.wait_until_safe_to_modify_dom();
abstract_self.with_mut_characterdata(|characterdata| {
@ -1341,7 +1369,8 @@ impl Node {
document.document().content_changed();
})
}
DoctypeNodeTypeId | DocumentNodeTypeId(_) => {}
DoctypeNodeTypeId |
DocumentNodeTypeId(_) => {}
}
Ok(())
}
@ -1390,7 +1419,7 @@ impl Node {
DoctypeNodeTypeId |
ElementNodeTypeId(..) |
TextNodeTypeId |
// ProcessingInstructionNodeTypeId |
ProcessingInstructionNodeTypeId |
CommentNodeTypeId => (),
DocumentNodeTypeId(..) => return Err(HierarchyRequest)
}
@ -1443,7 +1472,7 @@ impl Node {
}
},
TextNodeTypeId |
// ProcessingInstructionNodeTypeId |
ProcessingInstructionNodeTypeId |
CommentNodeTypeId => (),
DocumentNodeTypeId(..) => unreachable!()
}

View file

@ -0,0 +1,36 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::ProcessingInstructionBinding;
use dom::bindings::utils::DOMString;
use dom::characterdata::CharacterData;
use dom::document::AbstractDocument;
use dom::node::{AbstractNode, Node, ProcessingInstructionNodeTypeId};
/// An HTML processing instruction node.
pub struct ProcessingInstruction {
// FIXME: s/element/characterdata/ https://github.com/mozilla/servo/issues/1594
element: CharacterData,
target: DOMString,
}
impl ProcessingInstruction {
pub fn new_inherited(target: DOMString, data: DOMString, document: AbstractDocument) -> ProcessingInstruction {
ProcessingInstruction {
element: CharacterData::new_inherited(ProcessingInstructionNodeTypeId, data, document),
target: target
}
}
pub fn new(target: DOMString, data: DOMString, document: AbstractDocument) -> AbstractNode {
let node = ProcessingInstruction::new_inherited(target, data, document);
Node::reflect_node(@mut node, document, ProcessingInstructionBinding::Wrap)
}
}
impl ProcessingInstruction {
pub fn Target(&self) -> DOMString {
self.target.clone()
}
}

View file

@ -0,0 +1,12 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://dom.spec.whatwg.org/#interface-processinginstruction
*/
interface ProcessingInstruction : CharacterData {
readonly attribute DOMString target;
};

View file

@ -140,6 +140,7 @@ pub mod dom {
pub mod navigator;
pub mod node;
pub mod nodelist;
pub mod processinginstruction;
pub mod uievent;
pub mod text;
pub mod validitystate;