mirror of
https://github.com/servo/servo.git
synced 2025-06-23 08:34:42 +01:00
implement NodeList and consolidate common scope and context retrieval
This commit is contained in:
parent
bc3eeb6f1c
commit
9fe9145be4
13 changed files with 180 additions and 72 deletions
|
@ -300,14 +300,15 @@ DOMInterfaces = {
|
|||
'nodeValue',
|
||||
'removeChild',
|
||||
'textContent',
|
||||
'childNodes'
|
||||
]
|
||||
},
|
||||
|
||||
'NodeList': [
|
||||
{
|
||||
'nativeType': 'nsINodeList',
|
||||
'prefable': True,
|
||||
'resultNotAddRefed': [ 'item' ]
|
||||
'nativeType': 'NodeList',
|
||||
'pointerType': '@mut ',
|
||||
'resultNotAddRefed': ['item']
|
||||
}],
|
||||
|
||||
'PaintRequestList': [
|
||||
|
|
|
@ -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]
|
||||
|
|
16
src/components/script/dom/bindings/codegen/NodeList.webidl
Normal file
16
src/components/script/dom/bindings/codegen/NodeList.webidl
Normal 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);
|
||||
};
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
|
|
91
src/components/script/dom/nodelist.rs
Normal file
91
src/components/script/dom/nodelist.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue