servo: Merge #2931 - Add documentation for the DOM; r=jdm (from Ms2ger:dom-docs)

Source-Repo: https://github.com/servo/servo
Source-Revision: 69c49bb76437bb6dd71fe64cdf4c9da1dcaab11e
This commit is contained in:
Ms2ger 2014-07-26 17:15:12 +02:00
parent a04325dd27
commit 924e3c8a4d
10 changed files with 215 additions and 14 deletions

View File

@ -2,6 +2,8 @@
* 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/. */
//! Base classes to work with IDL callbacks.
use dom::bindings::js::JSRef;
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, global_object_for_js_object};
@ -13,17 +15,19 @@ use std::ptr;
use serialize::{Encodable, Encoder};
/// The exception handling used for a call.
pub enum ExceptionHandling {
// Report any exception and don't throw it to the caller code.
/// Report any exception and don't throw it to the caller code.
ReportExceptions,
// Throw an exception to the caller code if the thrown exception is a
// binding object for a DOMError from the caller's scope, otherwise report
// it.
/// Throw an exception to the caller code if the thrown exception is a
/// binding object for a DOMError from the caller's scope, otherwise report
/// it.
RethrowContentExceptions,
// Throw any exception to the caller code.
/// Throw any exception to the caller code.
RethrowExceptions
}
/// A common base class for representing IDL callback function types.
#[deriving(Clone,PartialEq,Encodable)]
pub struct CallbackFunction {
object: CallbackObject
@ -39,35 +43,46 @@ impl CallbackFunction {
}
}
/// A common base class for representing IDL callback interface types.
#[deriving(Clone,PartialEq,Encodable)]
pub struct CallbackInterface {
object: CallbackObject
}
/// A common base class for representing IDL callback function and
/// callback interface types.
#[allow(raw_pointer_deriving)]
#[deriving(Clone,PartialEq,Encodable)]
struct CallbackObject {
/// The underlying `JSObject`.
callback: Traceable<*mut JSObject>,
}
/// A trait to be implemented by concrete IDL callback function and
/// callback interface types.
pub trait CallbackContainer {
/// Create a new CallbackContainer object for the given `JSObject`.
fn new(callback: *mut JSObject) -> Self;
/// Returns the underlying `JSObject`.
fn callback(&self) -> *mut JSObject;
}
impl CallbackInterface {
/// Returns the underlying `JSObject`.
pub fn callback(&self) -> *mut JSObject {
*self.object.callback
}
}
impl CallbackFunction {
/// Returns the underlying `JSObject`.
pub fn callback(&self) -> *mut JSObject {
*self.object.callback
}
}
impl CallbackInterface {
/// Create a new CallbackInterface object for the given `JSObject`.
pub fn new(callback: *mut JSObject) -> CallbackInterface {
CallbackInterface {
object: CallbackObject {
@ -76,6 +91,9 @@ impl CallbackInterface {
}
}
/// Returns the property with the given `name`, if it is a callable object,
/// or `Err(())` otherwise. If it returns `Err(())`, a JSAPI exception is
/// pending.
pub fn GetCallableProperty(&self, cx: *mut JSContext, name: &str) -> Result<JSVal, ()> {
let mut callable = UndefinedValue();
unsafe {
@ -93,6 +111,7 @@ impl CallbackInterface {
}
}
/// Wraps the reflector for `p` into the compartment of `cx`.
pub fn WrapCallThisObject<T: Reflectable>(cx: *mut JSContext,
p: &JSRef<T>) -> *mut JSObject {
let mut obj = p.reflector().get_jsobject();
@ -107,12 +126,17 @@ pub fn WrapCallThisObject<T: Reflectable>(cx: *mut JSContext,
return obj;
}
/// A class that performs whatever setup we need to safely make a call while
/// this class is on the stack. After `new` returns, the call is safe to make.
pub struct CallSetup {
/// The `JSContext` used for the call.
cx: *mut JSContext,
/// The exception handling used for the call.
_handling: ExceptionHandling
}
impl CallSetup {
/// Performs the setup needed to make a call.
pub fn new<T: CallbackContainer>(callback: &T, handling: ExceptionHandling) -> CallSetup {
let global = global_object_for_js_object(callback.callback()).root();
let cx = global.root_ref().get_cx();
@ -122,6 +146,7 @@ impl CallSetup {
}
}
/// Returns the `JSContext` used for the call.
pub fn GetContext(&self) -> *mut JSContext {
self.cx
}

View File

@ -2,6 +2,8 @@
* 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/. */
//! Conversions of Rust values to and from `JSVal`.
use dom::bindings::js::{JS, JSRef, Root};
use dom::bindings::str::ByteString;
use dom::bindings::utils::{Reflectable, Reflector};
@ -33,11 +35,18 @@ pub trait IDLInterface {
fn get_prototype_depth(_: Option<Self>) -> uint;
}
/// A trait to convert Rust types to `JSVal`s.
pub trait ToJSValConvertible {
/// Convert `self` to a `JSVal`. JSAPI failure causes a task failure.
fn to_jsval(&self, cx: *mut JSContext) -> JSVal;
}
/// A trait to convert `JSVal`s to Rust types.
pub trait FromJSValConvertible<T> {
/// Convert `val` to type `Self`.
/// Optional configuration of type `T` can be passed as the `option`
/// argument.
/// If it returns `Err(())`, a JSAPI exception is pending.
fn from_jsval(cx: *mut JSContext, val: JSVal, option: T) -> Result<Self, ()>;
}
@ -228,9 +237,12 @@ impl ToJSValConvertible for DOMString {
}
}
/// Behavior for stringification of `JSVal`s.
#[deriving(PartialEq)]
pub enum StringificationBehavior {
/// Convert `null` to the string `"null"`.
Default,
/// Convert `null` to the empty string.
Empty,
}

View File

@ -2,6 +2,8 @@
* 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/. */
//! Utilities to throw exceptions from Rust bindings.
use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::global::GlobalRef;
use dom::domexception::DOMException;
@ -16,6 +18,7 @@ use js::rust::with_compartment;
use libc;
use std::ptr;
/// DOM exceptions that can be thrown by a native DOM method.
#[deriving(Show)]
pub enum Error {
IndexSize,
@ -34,10 +37,14 @@ pub enum Error {
Timeout
}
/// The return type for IDL operations that can throw DOM exceptions.
pub type Fallible<T> = Result<T, Error>;
/// The return type for IDL operations that can throw DOM exceptions and
/// return `()`.
pub type ErrorResult = Fallible<()>;
/// Set a pending DOM exception for the given `result` on `cx`.
pub fn throw_dom_exception(cx: *mut JSContext, global: &GlobalRef,
result: Error) {
assert!(unsafe { JS_IsExceptionPending(cx) } == 0);
@ -48,6 +55,7 @@ pub fn throw_dom_exception(cx: *mut JSContext, global: &GlobalRef,
}
}
/// Report a pending exception, thereby clearing it.
pub fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) {
unsafe {
if JS_IsExceptionPending(cx) != 0 {
@ -62,6 +70,8 @@ pub fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) {
}
}
/// Throw an exception to signal that a `JSVal` can not be converted to any of
/// the types in an IDL union type.
pub fn throw_not_in_union(cx: *mut JSContext, names: &'static str) -> JSBool {
assert!(unsafe { JS_IsExceptionPending(cx) } == 0);
let message = format!("argument could not be converted to any of: {}", names);
@ -71,6 +81,7 @@ pub fn throw_not_in_union(cx: *mut JSContext, names: &'static str) -> JSBool {
return 0;
}
/// Format string used to throw `TypeError`s.
static ERROR_FORMAT_STRING_STRING: [libc::c_char, ..4] = [
'{' as libc::c_char,
'0' as libc::c_char,
@ -78,12 +89,14 @@ static ERROR_FORMAT_STRING_STRING: [libc::c_char, ..4] = [
0 as libc::c_char,
];
/// Format string struct used to throw `TypeError`s.
static ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
format: &ERROR_FORMAT_STRING_STRING as *libc::c_char,
argCount: 1,
exnType: JSEXN_TYPEERR as i16,
};
/// Callback used to throw `TypeError`s.
extern fn get_error_message(_user_ref: *mut libc::c_void,
_locale: *libc::c_char,
error_number: libc::c_uint) -> *JSErrorFormatString
@ -92,6 +105,7 @@ extern fn get_error_message(_user_ref: *mut libc::c_void,
&ERROR_FORMAT_STRING as *JSErrorFormatString
}
/// Throw a `TypeError` with the given message.
pub fn throw_type_error(cx: *mut JSContext, error: &str) {
let error = error.to_c_str();
error.with_ref(|error| unsafe {

View File

@ -3,6 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Abstractions for global scopes.
//!
//! This module contains smart pointers to global scopes, to simplify writing
//! code that works in workers as well as window scopes.
use dom::bindings::js::{JS, JSRef, Root};
use dom::bindings::utils::{Reflectable, Reflector};
@ -16,16 +19,20 @@ use js::jsapi::JSContext;
use url::Url;
/// A freely-copyable reference to a rooted global object.
pub enum GlobalRef<'a> {
Window(JSRef<'a, Window>),
Worker(JSRef<'a, WorkerGlobalScope>),
}
/// A stack-based rooted reference to a global object.
pub enum GlobalRoot<'a, 'b> {
WindowRoot(Root<'a, 'b, Window>),
WorkerRoot(Root<'a, 'b, WorkerGlobalScope>),
}
/// A traced reference to a global object, for use in fields of traced Rust
/// structures.
#[deriving(Encodable)]
pub enum GlobalField {
WindowField(JS<Window>),
@ -33,6 +40,8 @@ pub enum GlobalField {
}
impl<'a> GlobalRef<'a> {
/// Get the `JSContext` for the `JSRuntime` associated with the thread
/// this global object is on.
pub fn get_cx(&self) -> *mut JSContext {
match *self {
Window(ref window) => window.get_cx(),
@ -40,6 +49,8 @@ impl<'a> GlobalRef<'a> {
}
}
/// Extract a `Window`, causing task failure if the global object is not
/// a `Window`.
pub fn as_window<'b>(&'b self) -> &'b JSRef<'b, Window> {
match *self {
Window(ref window) => window,
@ -79,6 +90,8 @@ impl<'a> Reflectable for GlobalRef<'a> {
}
impl<'a, 'b> GlobalRoot<'a, 'b> {
/// Obtain a safe reference to the global object that cannot outlive the
/// lifetime of this root.
pub fn root_ref<'c>(&'c self) -> GlobalRef<'c> {
match *self {
WindowRoot(ref window) => Window(window.root_ref()),
@ -88,6 +101,7 @@ impl<'a, 'b> GlobalRoot<'a, 'b> {
}
impl GlobalField {
/// Create a new `GlobalField` from a rooted reference.
pub fn from_rooted(global: &GlobalRef) -> GlobalField {
match *global {
Window(ref window) => WindowField(JS::from_rooted(window)),
@ -95,6 +109,7 @@ impl GlobalField {
}
}
/// Create a stack-bounded root for this reference.
pub fn root(&self) -> GlobalRoot {
match *self {
WindowField(ref window) => WindowRoot(window.root()),

View File

@ -2,6 +2,8 @@
* 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/. */
//! Smart pointers for the JS-managed DOM objects.
//!
//! The DOM is made up of Rust types whose lifetime is entirely controlled by the whims of
//! the SpiderMonkey garbage collector. The types in this module are designed to ensure
//! that any interactions with said Rust types only occur on values that will remain alive
@ -10,6 +12,7 @@
//! Here is a brief overview of the important types:
//!
//! - `JSRef<T>`: a freely-copyable reference to a rooted value.
//! - `Root<T>`: a stack-based reference to a rooted value.
//! - `JS<T>`: a pointer to JS-owned memory that can automatically be traced by the GC when
//! encountered as a field of a Rust structure.
//! - `Temporary<T>`: a value that will remain rooted for the duration of its lifetime.

View File

@ -2,6 +2,8 @@
* 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/. */
///! Utilities for the implementation of JSAPI proxy handlers.
use dom::bindings::utils::is_dom_proxy;
use js::jsapi::{JSContext, jsid, JSPropertyDescriptor, JSObject, JSString, jschar};
use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewUCString, JS_malloc, JS_free};

View File

@ -2,38 +2,49 @@
* 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 `ByteString` struct.
use std::from_str::FromStr;
use std::hash::{Hash, sip};
use std::path::BytesContainer;
use std::str;
/// Encapsulates the IDL `ByteString` type.
#[deriving(Encodable,Clone,Eq,PartialEq)]
pub struct ByteString(Vec<u8>);
impl ByteString {
/// Creates a new `ByteString`.
pub fn new(value: Vec<u8>) -> ByteString {
ByteString(value)
}
/// Returns `self` as a string, if it encodes valid UTF-8, and `None`
/// otherwise.
pub fn as_str<'a>(&'a self) -> Option<&'a str> {
let ByteString(ref vec) = *self;
str::from_utf8(vec.as_slice())
}
/// Returns the underlying vector as a slice.
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
let ByteString(ref vector) = *self;
vector.as_slice()
}
/// Returns the length.
pub fn len(&self) -> uint {
let ByteString(ref vector) = *self;
vector.len()
}
/// Compare `self` to `other`, matching AZ and az as equal.
pub fn eq_ignore_case(&self, other: &ByteString) -> bool {
// XXXManishearth make this more efficient
self.to_lower() == other.to_lower()
}
/// Returns `self` with AZ replaced by az.
pub fn to_lower(&self) -> ByteString {
let ByteString(ref vec) = *self;
ByteString::new(vec.iter().map(|&x| {
@ -45,6 +56,8 @@ impl ByteString {
}).collect())
}
/// Returns whether `self` is a `token`, as defined by
/// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-17).
pub fn is_token(&self) -> bool {
let ByteString(ref vec) = *self;
if vec.len() == 0 {
@ -64,6 +77,8 @@ impl ByteString {
})
}
/// Returns whether `self` is a `field-value`, as defined by
/// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-32).
pub fn is_field_value(&self) -> bool {
// Classifications of characters necessary for the [CRLF] (SP|HT) rule
#[deriving(PartialEq)]

View File

@ -2,6 +2,30 @@
* 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/. */
//! Utilities for tracing JS-managed values.
//!
//! The lifetime of DOM objects is managed by the SpiderMonkey Garbage
//! Collector. A rooted DOM object implementing the interface `Foo` is traced
//! as follows:
//!
//! 1. The GC calls `_trace` defined in `FooBinding` during the marking
//! phase. (This happens through `JSClass.trace` for non-proxy bindings, and
//! through `ProxyTraps.trace` otherwise.)
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`,
//! defined in `InheritTypes.rs`).
//! 3. `Foo::trace()` calls `Foo::encode()` (an implementation of `Encodable`).
//! This implementation is typically derived by a `#[deriving(Encodable)]`
//! annotation on the Rust struct.
//! 4. For all fields (except those wrapped in `Untraceable`), `Foo::encode()`
//! calls `encode()` on the field.
//!
//! For example, for fields of type `JS<T>`, `JS<T>::encode()` calls
//! `trace_reflector()`.
//! 6. `trace_reflector()` calls `trace_object()` with the `JSObject` for the
//! reflector.
//! 7. `trace_object()` calls `JS_CallTracer()` to notify the GC, which will
//! add the object to the graph, and will trace that object as well.
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector};
@ -37,10 +61,12 @@ impl<S: Encoder<E>, E> Encodable<S, E> for Reflector {
}
}
/// A trait to allow tracing (only) DOM objects.
pub trait JSTraceable {
fn trace(&self, trc: *mut JSTracer);
}
/// Trace a `JSVal`.
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: JSVal) {
if !val.is_gcthing() {
return;
@ -57,10 +83,12 @@ pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: JSVal) {
}
}
/// Trace the `JSObject` held by `reflector`.
pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Reflector) {
trace_object(tracer, description, reflector.get_jsobject())
}
/// Trace a `JSObject`.
pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: *mut JSObject) {
unsafe {
description.to_c_str().with_ref(|name| {
@ -73,8 +101,9 @@ pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: *mut JSObject
}
}
/// Encapsulates a type that cannot easily have Encodable derived automagically,
/// Encapsulates a type that cannot easily have `Encodable` derived automagically,
/// but also does not need to be made known to the SpiderMonkey garbage collector.
///
/// Use only with types that are not associated with a JS reflector and do not contain
/// fields of types associated with JS reflectors.
///
@ -104,8 +133,10 @@ impl<T> Deref<T> for Untraceable<T> {
}
}
/// Encapsulates a type that can be traced but is boxed in a type we don't control
/// (such as RefCell). Wrap a field in Traceable and implement the Encodable trait
/// Encapsulates a type that can be traced but is boxed in a type we don't
/// control (such as `RefCell`).
///
/// Wrap a field in Traceable and implement the `Encodable` trait
/// for that new concrete type to achieve magic compiler-derived trace hooks.
///
/// We always prefer this, in case the contained type ever changes to something that should be traced.

View File

@ -2,6 +2,8 @@
* 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/. */
//! Various utilities to glue JavaScript and the DOM implementation together.
use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
use dom::bindings::conversions::{FromJSValConvertible, IDLInterface};
@ -61,12 +63,14 @@ pub fn GlobalStaticData() -> GlobalStaticData {
}
}
/// Returns whether the given `clasp` is one for a DOM object.
fn is_dom_class(clasp: *JSClass) -> bool {
unsafe {
((*clasp).flags & js::JSCLASS_IS_DOMJSCLASS) != 0
}
}
/// Returns whether `obj` is a DOM object implemented as a proxy.
pub fn is_dom_proxy(obj: *mut JSObject) -> bool {
unsafe {
(js_IsObjectProxyClass(obj) || js_IsFunctionProxyClass(obj)) &&
@ -74,6 +78,10 @@ pub fn is_dom_proxy(obj: *mut JSObject) -> bool {
}
}
/// Returns the index of the slot wherein a pointer to the reflected DOM object
/// is stored.
///
/// Fails if `obj` is not a DOM object.
pub unsafe fn dom_object_slot(obj: *mut JSObject) -> u32 {
let clasp = JS_GetClass(obj);
if is_dom_class(clasp) {
@ -84,12 +92,14 @@ pub unsafe fn dom_object_slot(obj: *mut JSObject) -> u32 {
}
}
/// Get the DOM object from the given reflector.
pub unsafe fn unwrap<T>(obj: *mut JSObject) -> *T {
let slot = dom_object_slot(obj);
let val = JS_GetReservedSlot(obj, slot);
val.to_private() as *T
}
/// Get the `DOMClass` from `obj`, or `Err(())` if `obj` is not a DOM object.
pub unsafe fn get_dom_class(obj: *mut JSObject) -> Result<DOMClass, ()> {
let clasp = JS_GetClass(obj);
if is_dom_class(clasp) {
@ -106,6 +116,12 @@ pub unsafe fn get_dom_class(obj: *mut JSObject) -> Result<DOMClass, ()> {
return Err(());
}
/// Get a `JS<T>` for the given DOM object, unwrapping any wrapper around it
/// first, and checking if the object is of the correct type.
///
/// Returns Err(()) if `obj` is an opaque security wrapper or if the object is
/// not a reflector for a DOM object of the given type (as defined by the
/// proto_id and proto_depth).
pub fn unwrap_jsmanaged<T: Reflectable>(mut obj: *mut JSObject,
proto_id: PrototypeList::id::ID,
proto_depth: uint) -> Result<JS<T>, ()> {
@ -140,10 +156,13 @@ pub fn unwrap_jsmanaged<T: Reflectable>(mut obj: *mut JSObject,
}
}
/// Leak the given pointer.
pub unsafe fn squirrel_away_unique<T>(x: Box<T>) -> *T {
mem::transmute(x)
}
/// Convert the given `JSString` to a `DOMString`. Fails if the string does not
/// contain valid UTF-16.
pub fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString {
unsafe {
let mut length = 0;
@ -154,6 +173,8 @@ pub fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString {
}
}
/// Convert the given `jsid` to a `DOMString`. Fails if the `jsid` is not a
/// string, or if the string does not contain valid UTF-16.
pub fn jsid_to_str(cx: *mut JSContext, id: jsid) -> DOMString {
unsafe {
assert!(RUST_JSID_IS_STRING(id) != 0);
@ -161,6 +182,8 @@ pub fn jsid_to_str(cx: *mut JSContext, id: jsid) -> DOMString {
}
}
/// The index of the slot wherein a pointer to the reflected DOM object is
/// stored for non-proxy bindings.
// We use slot 0 for holding the raw object. This is safe for both
// globals and non-globals.
pub static DOM_OBJECT_SLOT: uint = 0;
@ -171,14 +194,17 @@ static DOM_PROXY_OBJECT_SLOT: uint = js::JSSLOT_PROXY_PRIVATE as uint;
// changes.
static DOM_PROTO_INSTANCE_CLASS_SLOT: u32 = 0;
/// The index of the slot that contains a reference to the ProtoOrIfaceArray.
// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT.
pub static DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT;
/// The flag set on the `JSClass`es for DOM global objects.
// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes.
pub static JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1;
/// Representation of an IDL constant value.
#[deriving(Clone)]
pub enum ConstantVal {
IntVal(i32),
@ -189,23 +215,28 @@ pub enum ConstantVal {
VoidVal
}
/// Representation of an IDL constant.
#[deriving(Clone)]
pub struct ConstantSpec {
pub name: &'static [u8],
pub value: ConstantVal
}
/// The struct that holds inheritance information for DOM object reflectors.
pub struct DOMClass {
// A list of interfaces that this object implements, in order of decreasing
// derivedness.
/// A list of interfaces that this object implements, in order of decreasing
/// derivedness.
pub interface_chain: [PrototypeList::id::ID, ..MAX_PROTO_CHAIN_LENGTH]
}
/// The JSClass used for DOM object reflectors.
pub struct DOMJSClass {
pub base: js::Class,
pub dom_class: DOMClass
}
/// Returns the ProtoOrIfaceArray for the given global object.
/// Fails if `global` is not a DOM global object.
pub fn GetProtoOrIfaceArray(global: *mut JSObject) -> *mut *mut JSObject {
unsafe {
assert!(((*JS_GetClass(global)).flags & JSCLASS_DOM_GLOBAL) != 0);
@ -213,6 +244,8 @@ pub fn GetProtoOrIfaceArray(global: *mut JSObject) -> *mut *mut JSObject {
}
}
/// Contains references to lists of methods, attributes, and constants for a
/// given interface.
pub struct NativeProperties {
pub methods: Option<&'static [JSFunctionSpec]>,
pub attrs: Option<&'static [JSPropertySpec]>,
@ -221,9 +254,13 @@ pub struct NativeProperties {
pub staticAttrs: Option<&'static [JSPropertySpec]>,
}
/// A JSNative that cannot be null.
pub type NonNullJSNative =
unsafe extern "C" fn (arg1: *mut JSContext, arg2: c_uint, arg3: *mut JSVal) -> JSBool;
/// Creates the *interface prototype object* and the *interface object* (if
/// needed).
/// Fails on JSAPI failure.
pub fn CreateInterfaceObjects2(cx: *mut JSContext, global: *mut JSObject, receiver: *mut JSObject,
protoProto: *mut JSObject,
protoClass: &'static JSClass,
@ -252,6 +289,8 @@ pub fn CreateInterfaceObjects2(cx: *mut JSContext, global: *mut JSObject, receiv
proto
}
/// Creates the *interface object*.
/// Fails on JSAPI failure.
fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *mut JSObject,
constructorNative: NonNullJSNative,
ctorNargs: u32, proto: *mut JSObject,
@ -295,6 +334,8 @@ fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *m
}
}
/// Defines constants on `obj`.
/// Fails on JSAPI failure.
fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: &'static [ConstantSpec]) {
for spec in constants.iter() {
let jsval = match spec.value {
@ -314,18 +355,26 @@ fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: &'static [
}
}
/// Defines methods on `obj`. The last entry of `methods` must contain zeroed
/// memory.
/// Fails on JSAPI failure.
fn DefineMethods(cx: *mut JSContext, obj: *mut JSObject, methods: &'static [JSFunctionSpec]) {
unsafe {
assert!(JS_DefineFunctions(cx, obj, methods.as_ptr()) != 0);
}
}
/// Defines attributes on `obj`. The last entry of `properties` must contain
/// zeroed memory.
/// Fails on JSAPI failure.
fn DefineProperties(cx: *mut JSContext, obj: *mut JSObject, properties: &'static [JSPropertySpec]) {
unsafe {
assert!(JS_DefineProperties(cx, obj, properties.as_ptr()) != 0);
}
}
/// Creates the *interface prototype object*.
/// Fails on JSAPI failure.
fn CreateInterfacePrototypeObject(cx: *mut JSContext, global: *mut JSObject,
parentProto: *mut JSObject,
protoClass: &'static JSClass,
@ -353,11 +402,14 @@ fn CreateInterfacePrototypeObject(cx: *mut JSContext, global: *mut JSObject,
}
}
/// A throwing constructor, for those interfaces that have neither
/// `NoInterfaceObject` nor `Constructor`.
pub extern fn ThrowingConstructor(_cx: *mut JSContext, _argc: c_uint, _vp: *mut JSVal) -> JSBool {
//XXX should trigger exception here
return 0;
}
/// Construct and cache the ProtoOrIfaceArray for the given global.
pub fn initialize_global(global: *mut JSObject) {
let protoArray = box () ([0 as *mut JSObject, ..PrototypeList::id::IDCount as uint]);
unsafe {
@ -368,10 +420,13 @@ pub fn initialize_global(global: *mut JSObject) {
}
}
/// A trait to provide access to the `Reflector` for a DOM object.
pub trait Reflectable {
fn reflector<'a>(&'a self) -> &'a Reflector;
}
/// Create the reflector for a new DOM object and yield ownership to the
/// reflector.
pub fn reflect_dom_object<T: Reflectable>
(obj: Box<T>,
global: &GlobalRef,
@ -380,6 +435,7 @@ pub fn reflect_dom_object<T: Reflectable>
wrap_fn(global.get_cx(), global, obj)
}
/// A struct to store a reference to the reflector of a DOM object.
#[allow(raw_pointer_deriving)]
#[deriving(PartialEq)]
pub struct Reflector {
@ -387,11 +443,13 @@ pub struct Reflector {
}
impl Reflector {
/// Get the reflector.
#[inline]
pub fn get_jsobject(&self) -> *mut JSObject {
self.object.get()
}
/// Initialize the reflector. (May be called only once.)
pub fn set_jsobject(&self, object: *mut JSObject) {
assert!(self.object.get().is_null());
assert!(object.is_not_null());
@ -407,6 +465,7 @@ impl Reflector {
as *mut *mut JSObject
}
/// Create an uninitialized `Reflector`.
pub fn new() -> Reflector {
Reflector {
object: Cell::new(ptr::mut_null()),
@ -437,6 +496,8 @@ pub fn GetPropertyOnPrototype(cx: *mut JSContext, proxy: *mut JSObject, id: jsid
}
}
/// Get an array index from the given `jsid`. Returns `None` if the given
/// `jsid` is not an integer.
pub fn GetArrayIndexFromId(_cx: *mut JSContext, id: jsid) -> Option<u32> {
unsafe {
if RUST_JSID_IS_INT(id) != 0 {
@ -460,6 +521,9 @@ pub fn GetArrayIndexFromId(_cx: *mut JSContext, id: jsid) -> Option<u32> {
}*/
}
/// Find the index of a string given by `v` in `values`.
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and
/// `Ok(None)` if there was no matching string.
pub fn FindEnumStringIndex(cx: *mut JSContext,
v: JSVal,
values: &[&'static str]) -> Result<Option<uint>, ()> {
@ -484,6 +548,9 @@ pub fn FindEnumStringIndex(cx: *mut JSContext,
}
}
/// Get the property with name `property` from `object`.
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and
/// `Ok(None)` if there was no property with the given name.
pub fn get_dictionary_property(cx: *mut JSContext,
object: *mut JSObject,
property: &str) -> Result<Option<JSVal>, ()> {
@ -533,12 +600,14 @@ pub fn HasPropertyOnPrototype(cx: *mut JSContext, proxy: *mut JSObject, id: jsid
return !GetPropertyOnPrototype(cx, proxy, id, &mut found, ptr::mut_null()) || found;
}
/// Returns whether `obj` can be converted to a callback interface per IDL.
pub fn IsConvertibleToCallbackInterface(cx: *mut JSContext, obj: *mut JSObject) -> bool {
unsafe {
JS_ObjectIsDate(cx, obj) == 0 && JS_ObjectIsRegExp(cx, obj) == 0
}
}
/// Create a DOM global object with the given class.
pub fn CreateDOMGlobal(cx: *mut JSContext, class: *JSClass) -> *mut JSObject {
unsafe {
let obj = JS_NewGlobalObject(cx, class, ptr::mut_null());
@ -553,12 +622,14 @@ pub fn CreateDOMGlobal(cx: *mut JSContext, class: *JSClass) -> *mut JSObject {
}
}
/// Callback to outerize windows when wrapping.
pub extern fn wrap_for_same_compartment(cx: *mut JSContext, obj: *mut JSObject) -> *mut JSObject {
unsafe {
JS_ObjectToOuterObject(cx, obj)
}
}
/// Callback to outerize windows before wrapping.
pub extern fn pre_wrap(cx: *mut JSContext, _scope: *mut JSObject,
obj: *mut JSObject, _flags: c_uint) -> *mut JSObject {
unsafe {
@ -566,6 +637,7 @@ pub extern fn pre_wrap(cx: *mut JSContext, _scope: *mut JSObject,
}
}
/// Callback to outerize windows.
pub extern fn outerize_global(_cx: *mut JSContext, obj: JSHandleObject) -> *mut JSObject {
unsafe {
debug!("outerizing");
@ -600,17 +672,20 @@ pub fn global_object_for_js_object(obj: *mut JSObject) -> GlobalField {
}
}
/// Get the `JSContext` for the `JSRuntime` associated with the thread
/// this object is on.
fn cx_for_dom_reflector(obj: *mut JSObject) -> *mut JSContext {
let global = global_object_for_js_object(obj).root();
global.root_ref().get_cx()
}
/// Get the `JSContext` for the `JSRuntime` associated with the thread
/// this DOM object is on.
pub fn cx_for_dom_object<T: Reflectable>(obj: &T) -> *mut JSContext {
cx_for_dom_reflector(obj.reflector().get_jsobject())
}
/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name
/// for details.
/// Results of `xml_name_type`.
#[deriving(PartialEq)]
pub enum XMLName {
QName,
@ -618,6 +693,8 @@ pub enum XMLName {
InvalidXMLName
}
/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name
/// for details.
pub fn xml_name_type(name: &str) -> XMLName {
fn is_valid_start(c: char) -> bool {
match c {

View File

@ -14,6 +14,8 @@
#![feature(phase)]
#![doc="The script crate contains all matters DOM."]
#![allow(non_snake_case_functions)]
#[phase(plugin, link)]
@ -43,9 +45,11 @@ extern crate sync;
extern crate servo_msg = "msg";
extern crate url = "url_";
pub mod cors;
/// The implementation of the DOM.
pub mod dom {
/// The code to expose the DOM to JavaScript through IDL bindings.
pub mod bindings {
pub mod global;
pub mod js;
@ -53,9 +57,11 @@ pub mod dom {
pub mod callback;
pub mod error;
pub mod conversions;
pub mod proxyhandler;
mod proxyhandler;
pub mod str;
pub mod trace;
/// Generated JS-Rust bindings.
pub mod codegen {
pub mod Bindings;
pub mod InterfaceTypes;
@ -190,6 +196,7 @@ pub mod dom {
pub mod testbinding;
}
/// Parsers for HTML and CSS.
pub mod html {
pub mod cssparse;
pub mod hubbub_html_parser;