Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lots of work on bindings #397

Merged
merged 10 commits into from Apr 24, 2013

Several orthogonal changes that all got tangled up:

* Split ClientRect, ClientRectList, and HTMLCollection blobs into separate DOM implementation and binding-related files.
* Enforce wrapper initialization at creation time for all DOM objects
* Set up the basis for triggering reflow on DOM changes, such as Element.setAttribute
* Fix crashes stemming from storing pointers to stack-local AbstractNode objects in DOM node wrappers
* Add untested trace hooks for DOM nodes
* Implement proper CharacterData inheritance for Text and Comment nodes
  • Loading branch information
jdm committed Apr 23, 2013
commit 56c4efde7c61279f0589204942b123b3556318e8
@@ -151,14 +151,30 @@ pub fn Content(layout_task: LayoutTask,
};

cx.set_cx_private(ptr::to_unsafe_ptr(&*content) as *());
unsafe { task::local_data::local_data_set(global_content_key, cast::transmute(content)); }

content
}

fn global_content_key(_: @Content) {}

pub fn global_content() -> @Content {
unsafe {
return task::local_data::local_data_get(global_content_key).get();
}
}

pub fn task_from_context(cx: *JSContext) -> *mut Content {
JS_GetContextPrivate(cx) as *mut Content
}

#[unsafe_destructor]
impl Drop for Content {
fn finalize(&self) {
unsafe { task::local_data::local_data_pop(global_content_key) };
}
}

#[allow(non_implicitly_copyable_typarams)]
pub impl Content {
fn start(&mut self) {
@@ -185,6 +201,8 @@ pub impl Content {
ParseMsg(url) => {
debug!("content: Received url `%s` to parse", url_to_str(&url));

define_bindings(self.compartment.get());

// Note: we can parse the next document in parallel
// with any previous documents.

@@ -209,8 +227,13 @@ pub impl Content {
let js_scripts = result.js_port.recv();
debug!("js_scripts: %?", js_scripts);

let document = @mut Document(root);
let window = @mut Window(self.control_chan.clone());
let window = Window(self.control_chan.clone(),
self.event_chan.clone());
let document = Document(root, Some(window));

do root.with_mut_node |node| {
node.add_to_doc(document);
}

self.damage.add(MatchSelectorsDamage);
self.relayout(document, &url);
@@ -221,7 +244,6 @@ pub impl Content {

let compartment = self.compartment.expect(~"TODO error checking");
compartment.define_functions(debug_fns);
define_bindings(compartment, document, window);

do vec::consume(js_scripts) |_i, bytes| {
self.cx.evaluate_script(compartment.global_obj, bytes, ~"???", 1u);
@@ -2,63 +2,25 @@
* 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 content::content_task::task_from_context;
use content::content_task::{task_from_context, global_content};
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
use dom::bindings::codegen::ClientRectBinding;
use dom::clientrect::ClientRect;
use js::jsapi::{JSObject, JSContext, JSVal};
use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;

pub trait ClientRect {
fn Top(&self) -> f32;
fn Bottom(&self) -> f32;
fn Left(&self) -> f32;
fn Right(&self) -> f32;
fn Width(&self) -> f32;
fn Height(&self) -> f32;
}

pub struct ClientRectImpl {
wrapper: WrapperCache,
top: f32,
bottom: f32,
left: f32,
right: f32,
}

impl ClientRect for ClientRectImpl {
fn Top(&self) -> f32 {
self.top
}

fn Bottom(&self) -> f32 {
self.bottom
}

fn Left(&self) -> f32 {
self.left
}

fn Right(&self) -> f32 {
self.right
}

fn Width(&self) -> f32 {
f32::abs(self.right - self.left)
}

fn Height(&self) -> f32 {
f32::abs(self.bottom - self.top)
}
}

pub fn ClientRect(top: f32, bottom: f32, left: f32, right: f32) -> ClientRectImpl {
ClientRectImpl {
top: top, bottom: bottom, left: left, right: right,
wrapper: WrapperCache::new()
pub impl ClientRect {
pub fn init_wrapper(@mut self) {
let content = global_content();
let cx = content.compartment.get().cx.ptr;
let owner = content.window.get();
let cache = owner.get_wrappercache();
let scope = cache.get_wrapper();
self.wrap_object_shared(cx, scope);
}
}

impl CacheableWrapper for ClientRectImpl {
impl CacheableWrapper for ClientRect {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
unsafe { cast::transmute(&self.wrapper) }
}
@@ -73,14 +35,14 @@ impl CacheableWrapper for ClientRectImpl {
}
}

impl BindingObject for ClientRectImpl {
impl BindingObject for ClientRect {
fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
let content = task_from_context(cx);
unsafe { (*content).window.get() as @mut CacheableWrapper }
}
}

impl DerivedWrapper for ClientRectImpl {
impl DerivedWrapper for ClientRect {
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, _vp: *mut JSVal) -> i32 {
fail!(~"nyi")
}
@@ -2,53 +2,24 @@
* 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 content::content_task::task_from_context;
use dom::bindings::clientrect::{ClientRect, ClientRectImpl};
use content::content_task::{task_from_context, global_content};
use dom::bindings::codegen::ClientRectListBinding;
use dom::bindings::utils::{WrapperCache, CacheableWrapper, BindingObject};
use dom::clientrectlist::ClientRectList;
use js::jsapi::{JSObject, JSContext};

pub trait ClientRectList {
fn Length(&self) -> u32;
fn Item(&self, index: u32) -> Option<@mut ClientRectImpl>;
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<@mut ClientRectImpl>;
}

pub struct ClientRectListImpl {
wrapper: WrapperCache,
rects: ~[(f32, f32, f32, f32)]
}

impl ClientRectList for ClientRectListImpl {
fn Length(&self) -> u32 {
self.rects.len() as u32
}

fn Item(&self, index: u32) -> Option<@mut ClientRectImpl> {
if index < self.rects.len() as u32 {
let (top, bottom, left, right) = self.rects[index];
Some(@mut ClientRect(top, bottom, left, right))
} else {
None
}
}

fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<@mut ClientRectImpl> {
*found = index < self.rects.len() as u32;
self.Item(index)
}
}

pub impl ClientRectListImpl {
fn new() -> ClientRectListImpl {
ClientRectListImpl {
wrapper: WrapperCache::new(),
rects: ~[(5.6, 80.2, 3.7, 4.8), (800.1, 8001.1, -50.000001, -45.01)]
}
pub impl ClientRectList {
fn init_wrapper(@mut self) {
let content = global_content();
let cx = content.compartment.get().cx.ptr;
let owner = content.window.get();
let cache = owner.get_wrappercache();
let scope = cache.get_wrapper();
self.wrap_object_shared(cx, scope);
}
}

impl CacheableWrapper for ClientRectListImpl {
impl CacheableWrapper for ClientRectList {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
unsafe { cast::transmute(&self.wrapper) }
}
@@ -63,7 +34,7 @@ impl CacheableWrapper for ClientRectListImpl {
}
}

impl BindingObject for ClientRectListImpl {
impl BindingObject for ClientRectList {
fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
let content = task_from_context(cx);
unsafe { (*content).window.get() as @mut CacheableWrapper }
@@ -115,13 +115,13 @@ DOMInterfaces = {

'ClientRect': [
{
'nativeType': 'ClientRectImpl',
'nativeType': 'ClientRect',
'pointerType': '@mut '
}],

'ClientRectList': [
{
'nativeType': 'ClientRectListImpl',
'nativeType': 'ClientRectList',
'pointerType': '@mut '
}],

@@ -3906,9 +3906,9 @@ def makeEnumTypedef(e):
'dom::document::Document', #XXXjdm
'dom::bindings::utils::*',
'dom::bindings::conversions::*',
'dom::bindings::clientrect::*', #XXXjdm
'dom::bindings::clientrectlist::*', #XXXjdm
'dom::bindings::htmlcollection::*', #XXXjdm
'dom::clientrect::*', #XXXjdm
'dom::clientrectlist::*', #XXXjdm
'dom::htmlcollection::*', #XXXjdm
'dom::bindings::proxyhandler::*',
'dom::domparser::*', #XXXjdm
'content::content_task::task_from_context',
@@ -17,11 +17,10 @@ use core::libc::c_uint;
use content::content_task::task_from_context;
use dom::bindings::utils::{DOMString, rust_box, squirrel_away, str};
use dom::bindings::utils::{jsval_to_str, WrapNewBindingObject, CacheableWrapper};
use dom::bindings::utils::WrapperCache;
use dom::bindings::utils::{WrapperCache, DerivedWrapper};

use dom::document::Document;
use dom::bindings::htmlcollection::HTMLCollection;
use dom::bindings::node;
use dom::htmlcollection::HTMLCollection;
use dom::bindings::utils;

extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
@@ -32,7 +31,9 @@ extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> J
}

let doc = &mut (*unwrap(obj)).payload;
*vp = RUST_OBJECT_TO_JSVAL(node::create(cx, &mut doc.root).ptr);
let root = &mut doc.root;
assert!(root.is_element());
root.wrap(cx, ptr::null(), vp); //XXXjdm proper scope at some point
return 1;
}
}
@@ -80,7 +81,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
}
}

pub fn init(compartment: @mut Compartment, doc: @mut Document) {
pub fn init(compartment: @mut Compartment) {
let obj = utils::define_empty_prototype(~"Document", None, compartment);

let attrs = @~[
@@ -115,14 +116,9 @@ pub fn init(compartment: @mut Compartment, doc: @mut Document) {
JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns);
});

compartment.register_class(utils::instance_jsclass(~"DocumentInstance", finalize));

let ptr = create(compartment, doc);

compartment.define_property(~"document", RUST_OBJECT_TO_JSVAL(ptr),
GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
JSPROP_ENUMERATE);
compartment.register_class(utils::instance_jsclass(~"DocumentInstance",
finalize,
ptr::null()));
}

pub fn create(compartment: @mut Compartment, doc: @mut Document) -> *JSObject {
@@ -135,6 +131,12 @@ pub fn create(compartment: @mut Compartment, doc: @mut Document) -> *JSObject {
let raw_ptr: *libc::c_void = cast::reinterpret_cast(&squirrel_away(doc));
JS_SetReservedSlot(instance.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr));
}

compartment.define_property(~"document", RUST_OBJECT_TO_JSVAL(instance.ptr),
GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
JSPROP_ENUMERATE);

instance.ptr
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.