Skip to content

Commit

Permalink
auto merge of #1018 : ttaubert/servo/nodelist, r=jdm
Browse files Browse the repository at this point in the history
This should fix #652 and #775. I'm not sure if that's all that is needed to properly implement NodeList? Should we add tests somewhere? Sorry for any stupid stuff I might have done :)

r? @jdm
  • Loading branch information
bors-servo committed Oct 11, 2013
2 parents bc3eeb6 + 9fe9145 commit fc9fdf3
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 72 deletions.
7 changes: 4 additions & 3 deletions src/components/script/dom/bindings/codegen/Bindings.conf
Expand Up @@ -300,14 +300,15 @@ DOMInterfaces = {
'nodeValue',
'removeChild',
'textContent',
'childNodes'
]
},

'NodeList': [
{
'nativeType': 'nsINodeList',
'prefable': True,
'resultNotAddRefed': [ 'item' ]
'nativeType': 'NodeList',
'pointerType': '@mut ',
'resultNotAddRefed': ['item']
}],

'PaintRequestList': [
Expand Down
4 changes: 2 additions & 2 deletions src/components/script/dom/bindings/codegen/Node.webidl
Expand Up @@ -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]
Expand Down
16 changes: 16 additions & 0 deletions src/components/script/dom/bindings/codegen/NodeList.webidl
@@ -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);
};
14 changes: 3 additions & 11 deletions src/components/script/dom/element.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}

Expand Down
13 changes: 1 addition & 12 deletions src/components/script/dom/htmldatalistelement.rs
Expand Up @@ -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)
}
}
7 changes: 0 additions & 7 deletions src/components/script/dom/htmldocument.rs
Expand Up @@ -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 {
Expand Down
14 changes: 2 additions & 12 deletions src/components/script/dom/htmlfieldsetelement.rs
Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}

Expand Down
14 changes: 2 additions & 12 deletions src/components/script/dom/htmlformelement.rs
Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}

Expand Down
15 changes: 3 additions & 12 deletions src/components/script/dom/htmlmapelement.rs
Expand Up @@ -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
Expand All @@ -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)
}
}
25 changes: 24 additions & 1 deletion src/components/script/dom/node.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -496,6 +500,7 @@ impl Node<ScriptView> {
prev_sibling: None,

owner_doc: doc,
child_list: None,

layout_data: LayoutData::new(),
}
Expand Down Expand Up @@ -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>> {
Expand Down Expand Up @@ -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>,
Expand Down
91 changes: 91 additions & 0 deletions src/components/script/dom/nodelist.rs
@@ -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)
}
}
1 change: 1 addition & 0 deletions src/components/script/script.rc
Expand Up @@ -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;
Expand Down

0 comments on commit fc9fdf3

Please sign in to comment.