mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 17:25:36 +00:00
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:
parent
a04325dd27
commit
924e3c8a4d
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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()),
|
||||
|
@ -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.
|
||||
|
@ -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};
|
||||
|
@ -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 A–Z and a–z 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 A–Z replaced by a–z.
|
||||
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)]
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user