implement NodeList and consolidate common scope and context retrieval

This commit is contained in:
Tim Taubert 2013-10-05 19:17:52 -07:00
parent bc3eeb6f1c
commit 9fe9145be4
13 changed files with 180 additions and 72 deletions

View file

@ -300,14 +300,15 @@ DOMInterfaces = {
'nodeValue',
'removeChild',
'textContent',
'childNodes'
]
},
'NodeList': [
{
'nativeType': 'nsINodeList',
'prefable': True,
'resultNotAddRefed': [ 'item' ]
'nativeType': 'NodeList',
'pointerType': '@mut ',
'resultNotAddRefed': ['item']
}],
'PaintRequestList': [

View file

@ -42,8 +42,8 @@ interface Node /*: EventTarget*/ {
[Pure]
readonly attribute Element? parentElement;
boolean hasChildNodes();
/*[Constant]
readonly attribute NodeList childNodes;*/
[Constant]
readonly attribute NodeList childNodes;
[Pure]
readonly attribute Node? firstChild;
[Pure]

View file

@ -0,0 +1,16 @@
/* -*- 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://www.w3.org/TR/2012/WD-dom-20120105/
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface NodeList {
readonly attribute unsigned long length;
getter Node? item(unsigned long index);
};

View file

@ -192,14 +192,6 @@ impl<'self> Element {
}
}
}
fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
let doc = self.node.owner_doc;
let win = doc.with_base(|doc| doc.window.unwrap());
let cx = win.page.js_info.get_ref().js_compartment.cx.ptr;
let scope = win.reflector().get_jsobject();
(scope, cx)
}
}
impl Element {
@ -251,17 +243,17 @@ impl Element {
}
pub fn GetElementsByTagName(&self, _localname: &DOMString) -> @mut HTMLCollection {
let (scope, cx) = self.get_scope_and_cx();
let (scope, cx) = self.node.get_scope_and_cx();
HTMLCollection::new(~[], cx, scope)
}
pub fn GetElementsByTagNameNS(&self, _namespace: &DOMString, _localname: &DOMString) -> Fallible<@mut HTMLCollection> {
let (scope, cx) = self.get_scope_and_cx();
let (scope, cx) = self.node.get_scope_and_cx();
Ok(HTMLCollection::new(~[], cx, scope))
}
pub fn GetElementsByClassName(&self, _names: &DOMString) -> @mut HTMLCollection {
let (scope, cx) = self.get_scope_and_cx();
let (scope, cx) = self.node.get_scope_and_cx();
HTMLCollection::new(~[], cx, scope)
}

View file

@ -2,27 +2,16 @@
* 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::utils::Reflectable;
use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElement;
use js::jsapi::{JSObject, JSContext};
pub struct HTMLDataListElement {
htmlelement: HTMLElement
}
impl HTMLDataListElement {
fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
let doc = self.htmlelement.element.node.owner_doc;
let win = doc.with_base(|doc| doc.window.unwrap());
let cx = win.page.js_info.get_ref().js_compartment.cx.ptr;
let scope = win.reflector().get_jsobject();
(scope, cx)
}
pub fn Options(&self) -> @mut HTMLCollection {
let (scope, cx) = self.get_scope_and_cx();
let (scope, cx) = self.htmlelement.element.node.get_scope_and_cx();
HTMLCollection::new(~[], cx, scope)
}
}

View file

@ -32,13 +32,6 @@ impl HTMLDocument {
let compartment = window.get_ref().page.js_info.get_ref().js_compartment;
AbstractDocument::as_abstract(compartment.cx.ptr, doc)
}
fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
let win = self.parent.window.get_ref();
let cx = win.page.js_info.get_ref().js_compartment.cx.ptr;
let scope = win.reflector().get_jsobject();
(scope, cx)
}
}
impl ReflectableDocument for HTMLDocument {

View file

@ -2,14 +2,12 @@
* 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::utils::{DOMString, ErrorResult, Reflectable};
use dom::bindings::utils::{DOMString, ErrorResult};
use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElement;
use dom::node::{AbstractNode, ScriptView};
use dom::validitystate::ValidityState;
use js::jsapi::{JSContext, JSObject};
pub struct HTMLFieldSetElement {
htmlelement: HTMLElement
}
@ -39,16 +37,8 @@ impl HTMLFieldSetElement {
None
}
fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
let doc = self.htmlelement.element.node.owner_doc;
let win = doc.with_base(|doc| doc.window.unwrap());
let cx = win.page.js_info.get_ref().js_compartment.cx.ptr;
let scope = win.reflector().get_jsobject();
(scope, cx)
}
pub fn Elements(&self) -> @mut HTMLCollection {
let (scope, cx) = self.get_scope_and_cx();
let (scope, cx) = self.htmlelement.element.node.get_scope_and_cx();
HTMLCollection::new(~[], cx, scope)
}

View file

@ -2,26 +2,16 @@
* 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::utils::{Reflectable, DOMString, ErrorResult};
use dom::bindings::utils::{DOMString, ErrorResult};
use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElement;
use dom::node::{AbstractNode, ScriptView};
use js::jsapi::{JSObject, JSContext};
pub struct HTMLFormElement {
htmlelement: HTMLElement
}
impl HTMLFormElement {
fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
let doc = self.htmlelement.element.node.owner_doc;
let win = doc.with_base(|doc| doc.window.unwrap());
let cx = win.page.js_info.get_ref().js_compartment.cx.ptr;
let scope = win.reflector().get_jsobject();
(scope, cx)
}
pub fn AcceptCharset(&self) -> DOMString {
None
}
@ -95,7 +85,7 @@ impl HTMLFormElement {
}
pub fn Elements(&self) -> @mut HTMLCollection {
let (scope, cx) = self.get_scope_and_cx();
let (scope, cx) = self.htmlelement.element.node.get_scope_and_cx();
HTMLCollection::new(~[], cx, scope)
}

View file

@ -2,10 +2,9 @@
* 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::utils::{DOMString, ErrorResult, Reflectable};
use dom::bindings::utils::{DOMString, ErrorResult};
use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElement;
use js::jsapi::{JSObject, JSContext};
pub struct HTMLMapElement {
htmlelement: HTMLElement
@ -20,16 +19,8 @@ impl HTMLMapElement {
Ok(())
}
fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
let doc = self.htmlelement.element.node.owner_doc;
let win = doc.with_base(|doc| doc.window.unwrap());
let cx = win.page.js_info.get_ref().js_compartment.cx.ptr;
let scope = win.reflector().get_jsobject();
(scope, cx)
}
pub fn Areas(&self) -> @mut HTMLCollection {
let (scope, cx) = self.get_scope_and_cx();
HTMLCollection::new(~[], cx, scope)
let (scope, cx) = self.htmlelement.element.node.get_scope_and_cx();
HTMLCollection::new(~[], cx, scope)
}
}

View file

@ -12,6 +12,7 @@ use dom::document::AbstractDocument;
use dom::documenttype::DocumentType;
use dom::element::{Element, ElementTypeId, HTMLImageElementTypeId, HTMLIframeElementTypeId};
use dom::element::{HTMLStyleElementTypeId};
use dom::nodelist::{NodeList};
use dom::htmlimageelement::HTMLImageElement;
use dom::htmliframeelement::HTMLIFrameElement;
use dom::text::Text;
@ -89,6 +90,9 @@ pub struct Node<View> {
/// The document that this node belongs to.
owner_doc: AbstractDocument,
/// The live list of children return by .childNodes.
child_list: Option<@mut NodeList>,
/// Layout information. Only the layout task may touch this data.
priv layout_data: LayoutData,
}
@ -496,6 +500,7 @@ impl Node<ScriptView> {
prev_sibling: None,
owner_doc: doc,
child_list: None,
layout_data: LayoutData::new(),
}
@ -570,7 +575,7 @@ impl Node<ScriptView> {
}
pub fn HasChildNodes(&self) -> bool {
false
self.first_child.is_some()
}
pub fn GetFirstChild(&self) -> Option<AbstractNode<ScriptView>> {
@ -632,6 +637,24 @@ impl Node<ScriptView> {
}
}
pub fn ChildNodes(&mut self, abstract_self: AbstractNode<ScriptView>) -> @mut NodeList {
match self.child_list {
None => {
let (scope, cx) = self.get_scope_and_cx();
let list = NodeList::new_child_list(abstract_self, cx, scope);
self.child_list = Some(list);
list
}
Some(list) => list
}
}
pub fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
let win = self.owner_doc.with_base(|doc| doc.window.unwrap());
let cx = win.page.js_info.get_ref().js_compartment.cx.ptr;
(win.reflector().get_jsobject(), cx)
}
// http://dom.spec.whatwg.org/#concept-node-replace-all
pub fn replace_all(&mut self,
abstract_self: AbstractNode<ScriptView>,

View file

@ -0,0 +1,91 @@
/* 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::NodeListBinding;
use dom::bindings::utils::{Reflectable, BindingObject, Reflector};
use dom::node::{AbstractNode, ScriptView};
use script_task::page_from_context;
use js::jsapi::{JSObject, JSContext};
enum NodeListType {
Simple(~[AbstractNode<ScriptView>]),
Children(AbstractNode<ScriptView>)
}
pub struct NodeList {
list_type: NodeListType,
reflector_: Reflector
}
impl NodeList {
pub fn new_simple_list(elements: ~[AbstractNode<ScriptView>], cx: *JSContext, scope: *JSObject) -> @mut NodeList {
let list = @mut NodeList {
list_type: Simple(elements),
reflector_: Reflector::new()
};
list.init_wrapper(cx, scope);
list
}
pub fn new_child_list(node: AbstractNode<ScriptView>, cx: *JSContext, scope: *JSObject) -> @mut NodeList {
let list = @mut NodeList {
list_type: Children(node),
reflector_: Reflector::new()
};
list.init_wrapper(cx, scope);
list
}
fn init_wrapper(@mut self, cx: *JSContext, scope: *JSObject) {
self.wrap_object_shared(cx, scope);
}
pub fn Length(&self) -> u32 {
match self.list_type {
Simple(ref elems) => elems.len() as u32,
Children(ref node) => node.children().len() as u32
}
}
pub fn Item(&self, index: u32) -> Option<AbstractNode<ScriptView>> {
match self.list_type {
_ if index >= self.Length() => None,
Simple(ref elems) => Some(elems[index]),
Children(ref node) => node.children().nth(index as uint)
}
}
pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<AbstractNode<ScriptView>> {
let item = self.Item(index);
*found = item.is_some();
item
}
}
impl BindingObject for NodeList {
fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> {
let page = page_from_context(cx);
unsafe {
Some((*page).frame.get_ref().window as @mut Reflectable)
}
}
}
impl Reflectable for NodeList {
fn reflector<'a>(&'a self) -> &'a Reflector {
&self.reflector_
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
&mut self.reflector_
}
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
let mut unused = false;
NodeListBinding::Wrap(cx, scope, self, &mut unused)
}
}

View file

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