mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
servo: Merge #8569 - Rustfmt some of script (from Ms2ger:fmt-script); r=metajack
Source-Repo: https://github.com/servo/servo Source-Revision: 7a87312121a69b590b364f9b5095f3145554e24b
This commit is contained in:
parent
4fb6893be4
commit
f0af48c824
@ -27,13 +27,13 @@ impl ClipboardProvider for ConstellationChan {
|
||||
}
|
||||
|
||||
pub struct DummyClipboardContext {
|
||||
content: String
|
||||
content: String,
|
||||
}
|
||||
|
||||
impl DummyClipboardContext {
|
||||
pub fn new(s: &str) -> DummyClipboardContext {
|
||||
DummyClipboardContext {
|
||||
content: s.to_owned()
|
||||
content: s.to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ pub struct CORSRequest {
|
||||
pub headers: Headers,
|
||||
/// CORS preflight flag (https://fetch.spec.whatwg.org/#concept-http-fetch)
|
||||
/// Indicates that a CORS preflight request and/or cache check is to be performed
|
||||
pub preflight_flag: bool
|
||||
pub preflight_flag: bool,
|
||||
}
|
||||
|
||||
/// https://fetch.spec.whatwg.org/#concept-request-mode
|
||||
@ -55,15 +55,18 @@ pub struct CORSRequest {
|
||||
#[derive(PartialEq, Copy, Clone, HeapSizeOf)]
|
||||
pub enum RequestMode {
|
||||
CORS, // CORS
|
||||
ForcedPreflight // CORS-with-forced-preflight
|
||||
ForcedPreflight, // CORS-with-forced-preflight
|
||||
}
|
||||
|
||||
impl CORSRequest {
|
||||
/// Creates a CORS request if necessary. Will return an error when fetching is forbidden
|
||||
pub fn maybe_new(referer: Url, destination: Url, mode: RequestMode,
|
||||
method: Method, headers: Headers) -> Result<Option<CORSRequest>, ()> {
|
||||
if referer.scheme == destination.scheme &&
|
||||
referer.host() == destination.host() &&
|
||||
pub fn maybe_new(referer: Url,
|
||||
destination: Url,
|
||||
mode: RequestMode,
|
||||
method: Method,
|
||||
headers: Headers)
|
||||
-> Result<Option<CORSRequest>, ()> {
|
||||
if referer.scheme == destination.scheme && referer.host() == destination.host() &&
|
||||
referer.port() == destination.port() {
|
||||
return Ok(None); // Not cross-origin, proceed with a normal fetch
|
||||
}
|
||||
@ -72,7 +75,8 @@ impl CORSRequest {
|
||||
// we can fetch a data URL normally. about:blank can also be fetched by XHR
|
||||
"http" | "https" => {
|
||||
let mut req = CORSRequest::new(referer, destination, mode, method, headers);
|
||||
req.preflight_flag = !is_simple_method(&req.method) || mode == RequestMode::ForcedPreflight;
|
||||
req.preflight_flag = !is_simple_method(&req.method) ||
|
||||
mode == RequestMode::ForcedPreflight;
|
||||
if req.headers.iter().all(|h| is_simple_header(&h)) {
|
||||
req.preflight_flag = true;
|
||||
}
|
||||
@ -82,10 +86,14 @@ impl CORSRequest {
|
||||
}
|
||||
}
|
||||
|
||||
fn new(mut referer: Url, destination: Url, mode: RequestMode, method: Method,
|
||||
headers: Headers) -> CORSRequest {
|
||||
fn new(mut referer: Url,
|
||||
destination: Url,
|
||||
mode: RequestMode,
|
||||
method: Method,
|
||||
headers: Headers)
|
||||
-> CORSRequest {
|
||||
match referer.scheme_data {
|
||||
SchemeData::Relative(ref mut data) => data.path = vec!(),
|
||||
SchemeData::Relative(ref mut data) => data.path = vec![],
|
||||
_ => {}
|
||||
};
|
||||
referer.fragment = None;
|
||||
@ -96,7 +104,7 @@ impl CORSRequest {
|
||||
mode: mode,
|
||||
method: method,
|
||||
headers: headers,
|
||||
preflight_flag: false
|
||||
preflight_flag: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,12 +189,13 @@ impl CORSRequest {
|
||||
preflight.headers.set(AccessControlRequestMethod(self.method.clone()));
|
||||
|
||||
// Step 5 - 7
|
||||
let mut header_names = vec!();
|
||||
let mut header_names = vec![];
|
||||
for header in self.headers.iter() {
|
||||
header_names.push(header.name().to_owned());
|
||||
}
|
||||
header_names.sort();
|
||||
preflight.headers.set(AccessControlRequestHeaders(header_names.into_iter().map(UniCase).collect()));
|
||||
preflight.headers
|
||||
.set(AccessControlRequestHeaders(header_names.into_iter().map(UniCase).collect()));
|
||||
|
||||
// Step 8 unnecessary, we don't use the request body
|
||||
// Step 9, 10 unnecessary, we're writing our own fetch code
|
||||
@ -195,7 +204,7 @@ impl CORSRequest {
|
||||
let preflight_request = Request::new(preflight.method, preflight.destination);
|
||||
let mut req = match preflight_request {
|
||||
Ok(req) => req,
|
||||
Err(_) => return error
|
||||
Err(_) => return error,
|
||||
};
|
||||
|
||||
let host = req.headers().get::<Host>().unwrap().clone();
|
||||
@ -203,37 +212,36 @@ impl CORSRequest {
|
||||
req.headers_mut().set(host);
|
||||
let stream = match req.start() {
|
||||
Ok(s) => s,
|
||||
Err(_) => return error
|
||||
Err(_) => return error,
|
||||
};
|
||||
let response = match stream.send() {
|
||||
Ok(r) => r,
|
||||
Err(_) => return error
|
||||
Err(_) => return error,
|
||||
};
|
||||
|
||||
// Step 12
|
||||
match response.status.class() {
|
||||
Success => {}
|
||||
_ => return error
|
||||
_ => return error,
|
||||
}
|
||||
cors_response.headers = response.headers.clone();
|
||||
// Substeps 1-3 (parsing rules: https://fetch.spec.whatwg.org/#http-new-header-syntax)
|
||||
let methods_substep4 = [self.method.clone()];
|
||||
let mut methods = match response.headers.get() {
|
||||
Some(&AccessControlAllowMethods(ref v)) => &**v,
|
||||
_ => return error
|
||||
_ => return error,
|
||||
};
|
||||
let headers = match response.headers.get() {
|
||||
Some(&AccessControlAllowHeaders(ref h)) => h,
|
||||
_ => return error
|
||||
_ => return error,
|
||||
};
|
||||
// Substep 4
|
||||
if methods.is_empty() || preflight.mode == RequestMode::ForcedPreflight {
|
||||
methods = &methods_substep4;
|
||||
}
|
||||
// Substep 5
|
||||
if !is_simple_method(&self.method) &&
|
||||
!methods.iter().any(|m| m == &self.method) {
|
||||
return error;
|
||||
if !is_simple_method(&self.method) && !methods.iter().any(|m| m == &self.method) {
|
||||
return error;
|
||||
}
|
||||
// Substep 6
|
||||
for h in self.headers.iter() {
|
||||
@ -247,25 +255,31 @@ impl CORSRequest {
|
||||
// Substep 7, 8
|
||||
let max_age = match response.headers.get() {
|
||||
Some(&AccessControlMaxAge(num)) => num,
|
||||
None => 0
|
||||
None => 0,
|
||||
};
|
||||
// Substep 9: Impose restrictions on max-age, if any (unimplemented)
|
||||
// Substeps 10-12: Add a cache (partially implemented, XXXManishearth)
|
||||
// This cache should come from the user agent, creating a new one here to check
|
||||
// for compile time errors
|
||||
let cache = &mut CORSCache(vec!());
|
||||
let cache = &mut CORSCache(vec![]);
|
||||
for m in methods {
|
||||
let cache_match = cache.match_method_and_update(self, m, max_age);
|
||||
if !cache_match {
|
||||
cache.insert(CORSCacheEntry::new(self.origin.clone(), self.destination.clone(),
|
||||
max_age, false, HeaderOrMethod::MethodData(m.clone())));
|
||||
cache.insert(CORSCacheEntry::new(self.origin.clone(),
|
||||
self.destination.clone(),
|
||||
max_age,
|
||||
false,
|
||||
HeaderOrMethod::MethodData(m.clone())));
|
||||
}
|
||||
}
|
||||
for h in response.headers.iter() {
|
||||
let cache_match = cache.match_header_and_update(self, h.name(), max_age);
|
||||
if !cache_match {
|
||||
cache.insert(CORSCacheEntry::new(self.origin.clone(), self.destination.clone(),
|
||||
max_age, false, HeaderOrMethod::HeaderData(h.to_string())));
|
||||
cache.insert(CORSCacheEntry::new(self.origin.clone(),
|
||||
self.destination.clone(),
|
||||
max_age,
|
||||
false,
|
||||
HeaderOrMethod::HeaderData(h.to_string())));
|
||||
}
|
||||
}
|
||||
cors_response
|
||||
@ -275,21 +289,21 @@ impl CORSRequest {
|
||||
|
||||
pub struct CORSResponse {
|
||||
pub network_error: bool,
|
||||
pub headers: Headers
|
||||
pub headers: Headers,
|
||||
}
|
||||
|
||||
impl CORSResponse {
|
||||
fn new() -> CORSResponse {
|
||||
CORSResponse {
|
||||
network_error: false,
|
||||
headers: Headers::new()
|
||||
headers: Headers::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn new_error() -> CORSResponse {
|
||||
CORSResponse {
|
||||
CORSResponse {
|
||||
network_error: true,
|
||||
headers: Headers::new()
|
||||
headers: Headers::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -305,21 +319,21 @@ pub struct CORSCache(Vec<CORSCacheEntry>);
|
||||
#[derive(Clone)]
|
||||
pub enum HeaderOrMethod {
|
||||
HeaderData(String),
|
||||
MethodData(Method)
|
||||
MethodData(Method),
|
||||
}
|
||||
|
||||
impl HeaderOrMethod {
|
||||
fn match_header(&self, header_name: &str) -> bool {
|
||||
match *self {
|
||||
HeaderOrMethod::HeaderData(ref s) => s.eq_ignore_ascii_case(header_name),
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn match_method(&self, method: &Method) -> bool {
|
||||
match *self {
|
||||
HeaderOrMethod::MethodData(ref m) => m == method,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,7 +346,7 @@ pub struct CORSCacheEntry {
|
||||
pub max_age: u32,
|
||||
pub credentials: bool,
|
||||
pub header_or_method: HeaderOrMethod,
|
||||
created: Timespec
|
||||
created: Timespec,
|
||||
}
|
||||
|
||||
impl CORSCacheEntry {
|
||||
@ -340,14 +354,15 @@ impl CORSCacheEntry {
|
||||
url: Url,
|
||||
max_age: u32,
|
||||
credentials: bool,
|
||||
header_or_method: HeaderOrMethod) -> CORSCacheEntry {
|
||||
header_or_method: HeaderOrMethod)
|
||||
-> CORSCacheEntry {
|
||||
CORSCacheEntry {
|
||||
origin: origin,
|
||||
url: url,
|
||||
max_age: max_age,
|
||||
credentials: credentials,
|
||||
header_or_method: header_or_method,
|
||||
created: time::now().to_timespec()
|
||||
created: time::now().to_timespec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -377,15 +392,16 @@ impl CORSCache {
|
||||
/// https://fetch.spec.whatwg.org/#concept-cache-match-header
|
||||
fn find_entry_by_header<'a>(&'a mut self,
|
||||
request: &CORSRequest,
|
||||
header_name: &str) -> Option<&'a mut CORSCacheEntry> {
|
||||
header_name: &str)
|
||||
-> Option<&'a mut CORSCacheEntry> {
|
||||
self.cleanup();
|
||||
let CORSCache(ref mut buf) = *self;
|
||||
// Credentials are not yet implemented here
|
||||
let entry = buf.iter_mut().find(|e| e.origin.scheme == request.origin.scheme &&
|
||||
e.origin.host() == request.origin.host() &&
|
||||
e.origin.port() == request.origin.port() &&
|
||||
e.url == request.destination &&
|
||||
e.header_or_method.match_header(header_name));
|
||||
let entry = buf.iter_mut().find(|e| {
|
||||
e.origin.scheme == request.origin.scheme && e.origin.host() == request.origin.host() &&
|
||||
e.origin.port() == request.origin.port() && e.url == request.destination &&
|
||||
e.header_or_method.match_header(header_name)
|
||||
});
|
||||
entry
|
||||
}
|
||||
|
||||
@ -393,22 +409,27 @@ impl CORSCache {
|
||||
self.find_entry_by_header(request, header_name).is_some()
|
||||
}
|
||||
|
||||
fn match_header_and_update(&mut self, request: &CORSRequest, header_name: &str, new_max_age: u32) -> bool {
|
||||
fn match_header_and_update(&mut self,
|
||||
request: &CORSRequest,
|
||||
header_name: &str,
|
||||
new_max_age: u32)
|
||||
-> bool {
|
||||
self.find_entry_by_header(request, header_name).map(|e| e.max_age = new_max_age).is_some()
|
||||
}
|
||||
|
||||
fn find_entry_by_method<'a>(&'a mut self,
|
||||
request: &CORSRequest,
|
||||
method: &Method) -> Option<&'a mut CORSCacheEntry> {
|
||||
method: &Method)
|
||||
-> Option<&'a mut CORSCacheEntry> {
|
||||
// we can take the method from CORSRequest itself
|
||||
self.cleanup();
|
||||
let CORSCache(ref mut buf) = *self;
|
||||
// Credentials are not yet implemented here
|
||||
let entry = buf.iter_mut().find(|e| e.origin.scheme == request.origin.scheme &&
|
||||
e.origin.host() == request.origin.host() &&
|
||||
e.origin.port() == request.origin.port() &&
|
||||
e.url == request.destination &&
|
||||
e.header_or_method.match_method(method));
|
||||
let entry = buf.iter_mut().find(|e| {
|
||||
e.origin.scheme == request.origin.scheme && e.origin.host() == request.origin.host() &&
|
||||
e.origin.port() == request.origin.port() && e.url == request.destination &&
|
||||
e.header_or_method.match_method(method)
|
||||
});
|
||||
entry
|
||||
}
|
||||
|
||||
@ -417,7 +438,11 @@ impl CORSCache {
|
||||
self.find_entry_by_method(request, method).is_some()
|
||||
}
|
||||
|
||||
fn match_method_and_update(&mut self, request: &CORSRequest, method: &Method, new_max_age: u32) -> bool {
|
||||
fn match_method_and_update(&mut self,
|
||||
request: &CORSRequest,
|
||||
method: &Method,
|
||||
new_max_age: u32)
|
||||
-> bool {
|
||||
self.find_entry_by_method(request, method).map(|e| e.max_age = new_max_age).is_some()
|
||||
}
|
||||
|
||||
@ -429,8 +454,8 @@ impl CORSCache {
|
||||
}
|
||||
|
||||
fn is_simple_header(h: &HeaderView) -> bool {
|
||||
//FIXME: use h.is::<HeaderType>() when AcceptLanguage and
|
||||
//ContentLanguage headers exist
|
||||
// FIXME: use h.is::<HeaderType>() when AcceptLanguage and
|
||||
// ContentLanguage headers exist
|
||||
match &*h.name().to_ascii_lowercase() {
|
||||
"accept" | "accept-language" | "content-language" => true,
|
||||
"content-type" => match h.value() {
|
||||
@ -438,17 +463,17 @@ fn is_simple_header(h: &HeaderView) -> bool {
|
||||
Some(&ContentType(Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, _))) |
|
||||
Some(&ContentType(Mime(TopLevel::Multipart, SubLevel::FormData, _))) => true,
|
||||
|
||||
_ => false
|
||||
_ => false,
|
||||
|
||||
},
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_simple_method(m: &Method) -> bool {
|
||||
match *m {
|
||||
Method::Get | Method::Head | Method::Post => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,6 +484,6 @@ pub fn allow_cross_origin_request(req: &CORSRequest, headers: &Headers) -> bool
|
||||
Some(&AccessControlAllowOrigin::Any) => true, // Not always true, depends on credentials mode
|
||||
Some(&AccessControlAllowOrigin::Value(ref url)) => req.origin.serialize() == *url,
|
||||
Some(&AccessControlAllowOrigin::Null) |
|
||||
None => false
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@
|
||||
use devtools_traits::{CONSOLE_API, CachedConsoleMessage, CachedConsoleMessageTypes, PAGE_ERROR};
|
||||
use devtools_traits::{ComputedNodeLayout, ConsoleAPI, PageError, ScriptToDevtoolsControlMsg};
|
||||
use devtools_traits::{EvaluateJSReply, Modification, NodeInfo, TimelineMarker, TimelineMarkerType};
|
||||
use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods};
|
||||
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
|
||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||
use dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods};
|
||||
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||
use dom::bindings::conversions::{FromJSValConvertible, jsstring_to_str};
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::inheritance::Castable;
|
||||
@ -39,8 +39,8 @@ pub fn handle_evaluate_js(global: &GlobalRef, eval: String, reply: IpcSender<Eva
|
||||
} else if rval.ptr.is_boolean() {
|
||||
EvaluateJSReply::BooleanValue(rval.ptr.to_boolean())
|
||||
} else if rval.ptr.is_double() || rval.ptr.is_int32() {
|
||||
EvaluateJSReply::NumberValue(
|
||||
FromJSValConvertible::from_jsval(cx, rval.handle(), ()).unwrap())
|
||||
EvaluateJSReply::NumberValue(FromJSValConvertible::from_jsval(cx, rval.handle(), ())
|
||||
.unwrap())
|
||||
} else if rval.ptr.is_string() {
|
||||
EvaluateJSReply::StringValue(String::from(jsstring_to_str(cx, rval.ptr.to_string())))
|
||||
} else if rval.ptr.is_null() {
|
||||
@ -69,7 +69,9 @@ pub fn handle_get_root_node(page: &Rc<Page>, pipeline: PipelineId, reply: IpcSen
|
||||
reply.send(node.summarize()).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_get_document_element(page: &Rc<Page>, pipeline: PipelineId, reply: IpcSender<NodeInfo>) {
|
||||
pub fn handle_get_document_element(page: &Rc<Page>,
|
||||
pipeline: PipelineId,
|
||||
reply: IpcSender<NodeInfo>) {
|
||||
let page = get_page(&*page, pipeline);
|
||||
let document = page.document();
|
||||
let document_element = document.GetDocumentElement().unwrap();
|
||||
@ -92,11 +94,14 @@ fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String
|
||||
panic!("couldn't find node with unique id {}", node_id)
|
||||
}
|
||||
|
||||
pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: IpcSender<Vec<NodeInfo>>) {
|
||||
pub fn handle_get_children(page: &Rc<Page>,
|
||||
pipeline: PipelineId,
|
||||
node_id: String,
|
||||
reply: IpcSender<Vec<NodeInfo>>) {
|
||||
let parent = find_node_by_unique_id(&*page, pipeline, node_id);
|
||||
let children = parent.children().map(|child| {
|
||||
child.summarize()
|
||||
}).collect();
|
||||
let children = parent.children()
|
||||
.map(|child| child.summarize())
|
||||
.collect();
|
||||
reply.send(children).unwrap();
|
||||
}
|
||||
|
||||
@ -109,16 +114,20 @@ pub fn handle_get_layout(page: &Rc<Page>,
|
||||
let rect = elem.GetBoundingClientRect();
|
||||
let width = rect.Width() as f32;
|
||||
let height = rect.Height() as f32;
|
||||
reply.send(ComputedNodeLayout { width: width, height: height }).unwrap();
|
||||
reply.send(ComputedNodeLayout {
|
||||
width: width,
|
||||
height: height,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
|
||||
message_types: CachedConsoleMessageTypes,
|
||||
reply: IpcSender<Vec<CachedConsoleMessage>>) {
|
||||
//TODO: check the messageTypes against a global Cache for console messages and page exceptions
|
||||
// TODO: check the messageTypes against a global Cache for console messages and page exceptions
|
||||
let mut messages = Vec::new();
|
||||
if message_types.contains(PAGE_ERROR) {
|
||||
//TODO: make script error reporter pass all reported errors
|
||||
// TODO: make script error reporter pass all reported errors
|
||||
// to devtools and cache them for returning here.
|
||||
let msg = PageError {
|
||||
_type: "PageError".to_owned(),
|
||||
@ -138,7 +147,7 @@ pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
|
||||
messages.push(CachedConsoleMessage::PageError(msg));
|
||||
}
|
||||
if message_types.contains(CONSOLE_API) {
|
||||
//TODO: do for real
|
||||
// TODO: do for real
|
||||
let msg = ConsoleAPI {
|
||||
_type: "ConsoleAPI".to_owned(),
|
||||
level: "error".to_owned(),
|
||||
@ -164,7 +173,8 @@ pub fn handle_modify_attribute(page: &Rc<Page>,
|
||||
for modification in modifications {
|
||||
match modification.newValue {
|
||||
Some(string) => {
|
||||
let _ = elem.SetAttribute(DOMString::from(modification.attributeName), DOMString::from(string));
|
||||
let _ = elem.SetAttribute(DOMString::from(modification.attributeName),
|
||||
DOMString::from(string));
|
||||
},
|
||||
None => elem.RemoveAttribute(DOMString::from(modification.attributeName)),
|
||||
}
|
||||
@ -182,8 +192,7 @@ pub fn handle_set_timeline_markers(page: &Rc<Page>,
|
||||
window.set_devtools_timeline_markers(marker_types, reply);
|
||||
}
|
||||
|
||||
pub fn handle_drop_timeline_markers(page: &Rc<Page>,
|
||||
marker_types: Vec<TimelineMarkerType>) {
|
||||
pub fn handle_drop_timeline_markers(page: &Rc<Page>, marker_types: Vec<TimelineMarkerType>) {
|
||||
let window = page.window();
|
||||
window.drop_devtools_timeline_markers(marker_types);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
//! Tracking of pending loads in a document.
|
||||
//! https://html.spec.whatwg.org/multipage/#the-end
|
||||
|
||||
use msg::constellation_msg::{PipelineId};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::AsyncResponseTarget;
|
||||
use net_traits::{PendingAsyncLoad, ResourceTask};
|
||||
use std::sync::Arc;
|
||||
@ -86,7 +86,7 @@ impl DocumentLoader {
|
||||
}
|
||||
|
||||
pub fn is_blocked(&self) -> bool {
|
||||
//TODO: Ensure that we report blocked if parsing is still ongoing.
|
||||
// TODO: Ensure that we report blocked if parsing is still ongoing.
|
||||
!self.blocking_loads.is_empty()
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,11 @@ pub trait Activatable {
|
||||
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps
|
||||
fn synthetic_click_activation(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) {
|
||||
fn synthetic_click_activation(&self,
|
||||
ctrlKey: bool,
|
||||
shiftKey: bool,
|
||||
altKey: bool,
|
||||
metaKey: bool) {
|
||||
let element = self.as_element();
|
||||
// Step 1
|
||||
if element.click_in_progress() {
|
||||
@ -46,10 +50,22 @@ pub trait Activatable {
|
||||
// https://html.spec.whatwg.org/multipage/#fire-a-synthetic-mouse-event
|
||||
let win = window_from_node(element);
|
||||
let target = element.upcast();
|
||||
let mouse = MouseEvent::new(win.r(), DOMString::from("click"),
|
||||
EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, Some(win.r()), 1,
|
||||
0, 0, 0, 0, ctrlKey, shiftKey, altKey, metaKey,
|
||||
0, None);
|
||||
let mouse = MouseEvent::new(win.r(),
|
||||
DOMString::from("click"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable,
|
||||
Some(win.r()),
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
ctrlKey,
|
||||
shiftKey,
|
||||
altKey,
|
||||
metaKey,
|
||||
0,
|
||||
None);
|
||||
let event = mouse.upcast::<Event>();
|
||||
event.fire(target);
|
||||
|
||||
|
@ -32,8 +32,13 @@ pub struct Attr {
|
||||
}
|
||||
|
||||
impl Attr {
|
||||
fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace,
|
||||
prefix: Option<Atom>, owner: Option<&Element>) -> Attr {
|
||||
fn new_inherited(local_name: Atom,
|
||||
value: AttrValue,
|
||||
name: Atom,
|
||||
namespace: Namespace,
|
||||
prefix: Option<Atom>,
|
||||
owner: Option<&Element>)
|
||||
-> Attr {
|
||||
Attr {
|
||||
reflector_: Reflector::new(),
|
||||
identifier: AttrIdentifier {
|
||||
@ -47,13 +52,22 @@ impl Attr {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(window: &Window, local_name: Atom, value: AttrValue,
|
||||
name: Atom, namespace: Namespace,
|
||||
prefix: Option<Atom>, owner: Option<&Element>) -> Root<Attr> {
|
||||
reflect_dom_object(
|
||||
box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
|
||||
GlobalRef::Window(window),
|
||||
AttrBinding::Wrap)
|
||||
pub fn new(window: &Window,
|
||||
local_name: Atom,
|
||||
value: AttrValue,
|
||||
name: Atom,
|
||||
namespace: Namespace,
|
||||
prefix: Option<Atom>,
|
||||
owner: Option<&Element>)
|
||||
-> Root<Attr> {
|
||||
reflect_dom_object(box Attr::new_inherited(local_name,
|
||||
value,
|
||||
name,
|
||||
namespace,
|
||||
prefix,
|
||||
owner),
|
||||
GlobalRef::Window(window),
|
||||
AttrBinding::Wrap)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -90,7 +104,9 @@ impl AttrMethods for Attr {
|
||||
match self.owner() {
|
||||
None => *self.value.borrow_mut() = AttrValue::String(value),
|
||||
Some(owner) => {
|
||||
let value = owner.parse_attribute(&self.identifier.namespace, self.local_name(), value);
|
||||
let value = owner.parse_attribute(&self.identifier.namespace,
|
||||
self.local_name(),
|
||||
value);
|
||||
self.set_value(value, owner.r());
|
||||
}
|
||||
}
|
||||
@ -127,7 +143,7 @@ impl AttrMethods for Attr {
|
||||
let Namespace(ref atom) = self.identifier.namespace;
|
||||
match &**atom {
|
||||
"" => None,
|
||||
url => Some(DOMString::from(url))
|
||||
url => Some(DOMString::from(url)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,8 +171,8 @@ impl Attr {
|
||||
owner.will_mutate_attr();
|
||||
mem::swap(&mut *self.value.borrow_mut(), &mut value);
|
||||
if self.identifier.namespace == ns!("") {
|
||||
vtable_for(owner.upcast()).attribute_mutated(
|
||||
self, AttributeMutation::Set(Some(&value)));
|
||||
vtable_for(owner.upcast())
|
||||
.attribute_mutated(self, AttributeMutation::Set(Some(&value)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,13 +195,14 @@ impl Attr {
|
||||
match (self.owner().r(), owner) {
|
||||
(None, Some(new)) => {
|
||||
// Already in the list of attributes of new owner.
|
||||
assert!(new.get_attribute(&ns, &self.identifier.local_name) == Some(Root::from_ref(self)))
|
||||
assert!(new.get_attribute(&ns, &self.identifier.local_name) ==
|
||||
Some(Root::from_ref(self)))
|
||||
}
|
||||
(Some(old), None) => {
|
||||
// Already gone from the list of attributes of old owner.
|
||||
assert!(old.get_attribute(&ns, &self.identifier.local_name).is_none())
|
||||
}
|
||||
(old, new) => assert!(old == new)
|
||||
(old, new) => assert!(old == new),
|
||||
}
|
||||
self.owner.set(owner);
|
||||
}
|
||||
|
@ -8,9 +8,9 @@ use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::global::global_root_from_object;
|
||||
use dom::bindings::reflector::Reflectable;
|
||||
use js::jsapi::GetGlobalForObjectCrossCompartment;
|
||||
use js::jsapi::JSAutoCompartment;
|
||||
use js::jsapi::{Heap, MutableHandleObject, RootedObject, RootedValue};
|
||||
use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject};
|
||||
use js::jsapi::{JSAutoCompartment};
|
||||
use js::jsapi::{JSCompartment, JS_EnterCompartment, JS_LeaveCompartment};
|
||||
use js::jsapi::{JS_BeginRequest, JS_EndRequest};
|
||||
use js::jsapi::{JS_GetProperty, JS_IsExceptionPending, JS_ReportPendingException};
|
||||
@ -28,13 +28,13 @@ pub enum ExceptionHandling {
|
||||
/// Report any exception and don't throw it to the caller code.
|
||||
Report,
|
||||
/// Throw any exception to the caller code.
|
||||
Rethrow
|
||||
Rethrow,
|
||||
}
|
||||
|
||||
/// A common base class for representing IDL callback function types.
|
||||
#[derive(JSTraceable, PartialEq)]
|
||||
pub struct CallbackFunction {
|
||||
object: CallbackObject
|
||||
object: CallbackObject,
|
||||
}
|
||||
|
||||
impl CallbackFunction {
|
||||
@ -42,8 +42,8 @@ impl CallbackFunction {
|
||||
pub fn new() -> CallbackFunction {
|
||||
CallbackFunction {
|
||||
object: CallbackObject {
|
||||
callback: Heap::default()
|
||||
}
|
||||
callback: Heap::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ impl CallbackFunction {
|
||||
/// A common base class for representing IDL callback interface types.
|
||||
#[derive(JSTraceable, PartialEq)]
|
||||
pub struct CallbackInterface {
|
||||
object: CallbackObject
|
||||
object: CallbackObject,
|
||||
}
|
||||
|
||||
/// A common base class for representing IDL callback function and
|
||||
@ -103,8 +103,8 @@ impl CallbackInterface {
|
||||
pub fn new() -> CallbackInterface {
|
||||
CallbackInterface {
|
||||
object: CallbackObject {
|
||||
callback: Heap::default()
|
||||
}
|
||||
callback: Heap::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,21 +116,18 @@ impl CallbackInterface {
|
||||
|
||||
/// Returns the property with the given `name`, if it is a callable object,
|
||||
/// or an error otherwise.
|
||||
pub fn get_callable_property(&self, cx: *mut JSContext, name: &str)
|
||||
-> Fallible<JSVal> {
|
||||
pub fn get_callable_property(&self, cx: *mut JSContext, name: &str) -> Fallible<JSVal> {
|
||||
let mut callable = RootedValue::new(cx, UndefinedValue());
|
||||
let obj = RootedObject::new(cx, self.callback());
|
||||
unsafe {
|
||||
let c_name = CString::new(name).unwrap();
|
||||
if !JS_GetProperty(cx, obj.handle(), c_name.as_ptr(),
|
||||
callable.handle_mut()) {
|
||||
if !JS_GetProperty(cx, obj.handle(), c_name.as_ptr(), callable.handle_mut()) {
|
||||
return Err(Error::JSFailed);
|
||||
}
|
||||
|
||||
if !callable.ptr.is_object() ||
|
||||
!IsCallable(callable.ptr.to_object()) {
|
||||
return Err(Error::Type(
|
||||
format!("The value of the {} property is not callable", name)));
|
||||
if !callable.ptr.is_object() || !IsCallable(callable.ptr.to_object()) {
|
||||
return Err(Error::Type(format!("The value of the {} property is not callable",
|
||||
name)));
|
||||
}
|
||||
}
|
||||
Ok(callable.ptr)
|
||||
@ -172,15 +169,17 @@ impl CallSetup {
|
||||
pub fn new<T: CallbackContainer>(callback: &T, handling: ExceptionHandling) -> CallSetup {
|
||||
let global = global_root_from_object(callback.callback());
|
||||
let cx = global.r().get_cx();
|
||||
unsafe { JS_BeginRequest(cx); }
|
||||
unsafe {
|
||||
JS_BeginRequest(cx);
|
||||
}
|
||||
|
||||
let exception_compartment = unsafe {
|
||||
GetGlobalForObjectCrossCompartment(callback.callback())
|
||||
};
|
||||
CallSetup {
|
||||
exception_compartment:
|
||||
RootedObject::new_with_addr(cx, exception_compartment,
|
||||
unsafe { return_address() }),
|
||||
exception_compartment: RootedObject::new_with_addr(cx,
|
||||
exception_compartment,
|
||||
unsafe { return_address() }),
|
||||
cx: cx,
|
||||
old_compartment: unsafe { JS_EnterCompartment(cx, callback.callback()) },
|
||||
handling: handling,
|
||||
@ -195,10 +194,11 @@ impl CallSetup {
|
||||
|
||||
impl Drop for CallSetup {
|
||||
fn drop(&mut self) {
|
||||
unsafe { JS_LeaveCompartment(self.cx, self.old_compartment); }
|
||||
let need_to_deal_with_exception =
|
||||
self.handling == ExceptionHandling::Report &&
|
||||
unsafe { JS_IsExceptionPending(self.cx) };
|
||||
unsafe {
|
||||
JS_LeaveCompartment(self.cx, self.old_compartment);
|
||||
}
|
||||
let need_to_deal_with_exception = self.handling == ExceptionHandling::Report &&
|
||||
unsafe { JS_IsExceptionPending(self.cx) };
|
||||
if need_to_deal_with_exception {
|
||||
unsafe {
|
||||
let old_global = RootedObject::new(self.cx, self.exception_compartment.ptr);
|
||||
@ -212,6 +212,8 @@ impl Drop for CallSetup {
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe { JS_EndRequest(self.cx); }
|
||||
unsafe {
|
||||
JS_EndRequest(self.cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
//! A shareable mutable container for the DOM.
|
||||
|
||||
use dom::bindings::trace::JSTraceable;
|
||||
use js::jsapi::{JSTracer};
|
||||
use js::jsapi::JSTracer;
|
||||
use std::cell::{BorrowState, Ref, RefCell, RefMut};
|
||||
use util::task_state;
|
||||
use util::task_state::SCRIPT;
|
||||
@ -40,7 +40,7 @@ impl<T> DOMRefCell<T> {
|
||||
pub unsafe fn borrow_for_gc_trace(&self) -> &T {
|
||||
// FIXME: IN_GC isn't reliable enough - doesn't catch minor GCs
|
||||
// https://github.com/servo/servo/issues/6389
|
||||
//debug_assert!(task_state::get().contains(SCRIPT | IN_GC));
|
||||
// debug_assert!(task_state::get().contains(SCRIPT | IN_GC));
|
||||
&*self.value.as_unsafe_cell().get()
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ use js::rust::ToString;
|
||||
use libc;
|
||||
use num::Float;
|
||||
use std::{ptr, slice};
|
||||
use util::str::{DOMString};
|
||||
use util::str::DOMString;
|
||||
pub use util::str::{StringificationBehavior, jsstring_to_str};
|
||||
|
||||
|
||||
@ -119,7 +119,10 @@ impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> {
|
||||
impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite<T> {
|
||||
type Config = ();
|
||||
|
||||
unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, option: ()) -> Result<Finite<T>, ()> {
|
||||
unsafe fn from_jsval(cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
option: ())
|
||||
-> Result<Finite<T>, ()> {
|
||||
let result = try!(FromJSValConvertible::from_jsval(cx, value, option));
|
||||
match Finite::new(result) {
|
||||
Some(v) => Ok(v),
|
||||
@ -140,18 +143,17 @@ pub fn jsid_to_str(cx: *mut JSContext, id: HandleId) -> DOMString {
|
||||
}
|
||||
}
|
||||
|
||||
//http://heycam.github.io/webidl/#es-USVString
|
||||
// http://heycam.github.io/webidl/#es-USVString
|
||||
impl ToJSValConvertible for USVString {
|
||||
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
|
||||
self.0.to_jsval(cx, rval);
|
||||
}
|
||||
}
|
||||
|
||||
//http://heycam.github.io/webidl/#es-USVString
|
||||
// http://heycam.github.io/webidl/#es-USVString
|
||||
impl FromJSValConvertible for USVString {
|
||||
type Config = ();
|
||||
unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ())
|
||||
-> Result<USVString, ()> {
|
||||
unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ()) -> Result<USVString, ()> {
|
||||
let jsstr = ToString(cx, value);
|
||||
if jsstr.is_null() {
|
||||
debug!("ToString failed");
|
||||
@ -170,10 +172,11 @@ impl FromJSValConvertible for USVString {
|
||||
}
|
||||
}
|
||||
|
||||
//http://heycam.github.io/webidl/#es-ByteString
|
||||
// http://heycam.github.io/webidl/#es-ByteString
|
||||
impl ToJSValConvertible for ByteString {
|
||||
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
|
||||
let jsstr = JS_NewStringCopyN(cx, self.as_ptr() as *const libc::c_char,
|
||||
let jsstr = JS_NewStringCopyN(cx,
|
||||
self.as_ptr() as *const libc::c_char,
|
||||
self.len() as libc::size_t);
|
||||
if jsstr.is_null() {
|
||||
panic!("JS_NewStringCopyN failed");
|
||||
@ -182,10 +185,13 @@ impl ToJSValConvertible for ByteString {
|
||||
}
|
||||
}
|
||||
|
||||
//http://heycam.github.io/webidl/#es-ByteString
|
||||
// http://heycam.github.io/webidl/#es-ByteString
|
||||
impl FromJSValConvertible for ByteString {
|
||||
type Config = ();
|
||||
unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _option: ()) -> Result<ByteString, ()> {
|
||||
unsafe fn from_jsval(cx: *mut JSContext,
|
||||
value: HandleValue,
|
||||
_option: ())
|
||||
-> Result<ByteString, ()> {
|
||||
let string = ToString(cx, value);
|
||||
if string.is_null() {
|
||||
debug!("ToString failed");
|
||||
@ -195,8 +201,7 @@ impl FromJSValConvertible for ByteString {
|
||||
let latin1 = JS_StringHasLatin1Chars(string);
|
||||
if latin1 {
|
||||
let mut length = 0;
|
||||
let chars = JS_GetLatin1StringCharsAndLength(cx, ptr::null(),
|
||||
string, &mut length);
|
||||
let chars = JS_GetLatin1StringCharsAndLength(cx, ptr::null(), string, &mut length);
|
||||
assert!(!chars.is_null());
|
||||
|
||||
let char_slice = slice::from_raw_parts(chars as *mut u8, length as usize);
|
||||
@ -293,9 +298,11 @@ pub unsafe fn get_dom_class(obj: *mut JSObject) -> Result<&'static DOMClass, ()>
|
||||
/// not an object for a DOM object of the given type (as defined by the
|
||||
/// proto_id and proto_depth).
|
||||
#[inline]
|
||||
pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject, proto_check: F)
|
||||
pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject,
|
||||
proto_check: F)
|
||||
-> Result<*const libc::c_void, ()>
|
||||
where F: Fn(&'static DOMClass) -> bool {
|
||||
where F: Fn(&'static DOMClass) -> bool
|
||||
{
|
||||
let dom_class = try!(get_dom_class(obj).or_else(|_| {
|
||||
if IsWrapper(obj) {
|
||||
debug!("found wrapper");
|
||||
|
@ -15,7 +15,7 @@ use dom::bindings::reflector::{Reflectable, Reflector};
|
||||
use dom::window::{self, ScriptHelpers};
|
||||
use dom::workerglobalscope::WorkerGlobalScope;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use js::jsapi::{GetGlobalForObjectCrossCompartment};
|
||||
use js::jsapi::GetGlobalForObjectCrossCompartment;
|
||||
use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
|
||||
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
||||
use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId};
|
||||
@ -140,7 +140,7 @@ impl<'a> GlobalRef<'a> {
|
||||
pub fn get_next_worker_id(&self) -> WorkerId {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.get_next_worker_id(),
|
||||
GlobalRef::Worker(ref worker) => worker.get_next_worker_id()
|
||||
GlobalRef::Worker(ref worker) => worker.get_next_worker_id(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +199,10 @@ impl<'a> GlobalRef<'a> {
|
||||
|
||||
/// Schedule the given `callback` to be invoked after at least `duration` milliseconds have
|
||||
/// passed.
|
||||
pub fn schedule_callback(&self, callback: Box<ScheduledCallback>, duration: MsDuration) -> TimerHandle {
|
||||
pub fn schedule_callback(&self,
|
||||
callback: Box<ScheduledCallback>,
|
||||
duration: MsDuration)
|
||||
-> TimerHandle {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.schedule_callback(callback, duration),
|
||||
GlobalRef::Worker(worker) => worker.schedule_callback(callback, duration),
|
||||
|
@ -15,20 +15,25 @@ use std::mem;
|
||||
/// or are derived from other interfaces.
|
||||
pub trait Castable: IDLInterface + Reflectable + Sized {
|
||||
/// Check whether a DOM object implements one of its deriving interfaces.
|
||||
fn is<T>(&self) -> bool where T: DerivedFrom<Self> {
|
||||
let class = unsafe {
|
||||
get_dom_class(self.reflector().get_jsobject().get()).unwrap()
|
||||
};
|
||||
fn is<T>(&self) -> bool
|
||||
where T: DerivedFrom<Self>
|
||||
{
|
||||
let class = unsafe { get_dom_class(self.reflector().get_jsobject().get()).unwrap() };
|
||||
T::derives(class)
|
||||
}
|
||||
|
||||
/// Cast a DOM object upwards to one of the interfaces it derives from.
|
||||
fn upcast<T>(&self) -> &T where T: Castable, Self: DerivedFrom<T> {
|
||||
fn upcast<T>(&self) -> &T
|
||||
where T: Castable,
|
||||
Self: DerivedFrom<T>
|
||||
{
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Cast a DOM object downwards to one of the interfaces it might implement.
|
||||
fn downcast<T>(&self) -> Option<&T> where T: DerivedFrom<Self> {
|
||||
fn downcast<T>(&self) -> Option<&T>
|
||||
where T: DerivedFrom<Self>
|
||||
{
|
||||
if self.is::<T>() {
|
||||
Some(unsafe { mem::transmute(self) })
|
||||
} else {
|
||||
|
@ -52,7 +52,7 @@ use util::task_state;
|
||||
/// This should only be used as a field in other DOM objects.
|
||||
#[must_root]
|
||||
pub struct JS<T> {
|
||||
ptr: NonZero<*const T>
|
||||
ptr: NonZero<*const T>,
|
||||
}
|
||||
|
||||
// JS<T> is similar to Rc<T>, in that it's not always clear how to avoid double-counting.
|
||||
@ -68,7 +68,7 @@ impl<T> JS<T> {
|
||||
pub unsafe fn to_layout(&self) -> LayoutJS<T> {
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
LayoutJS {
|
||||
ptr: self.ptr.clone()
|
||||
ptr: self.ptr.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,7 +80,7 @@ impl<T: Reflectable> JS<T> {
|
||||
pub fn from_rooted(root: &Root<T>) -> JS<T> {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
JS {
|
||||
ptr: unsafe { NonZero::new(&**root) }
|
||||
ptr: unsafe { NonZero::new(&**root) },
|
||||
}
|
||||
}
|
||||
/// Create a JS<T> from a &T
|
||||
@ -88,7 +88,7 @@ impl<T: Reflectable> JS<T> {
|
||||
pub fn from_ref(obj: &T) -> JS<T> {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
JS {
|
||||
ptr: unsafe { NonZero::new(&*obj) }
|
||||
ptr: unsafe { NonZero::new(&*obj) },
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,18 +114,23 @@ impl<T: Reflectable> JSTraceable for JS<T> {
|
||||
/// traits must be implemented on this.
|
||||
#[allow_unrooted_interior]
|
||||
pub struct LayoutJS<T> {
|
||||
ptr: NonZero<*const T>
|
||||
ptr: NonZero<*const T>,
|
||||
}
|
||||
|
||||
impl<T: Castable> LayoutJS<T> {
|
||||
/// Cast a DOM object root upwards to one of the interfaces it derives from.
|
||||
pub fn upcast<U>(&self) -> LayoutJS<U> where U: Castable, T: DerivedFrom<U> {
|
||||
pub fn upcast<U>(&self) -> LayoutJS<U>
|
||||
where U: Castable,
|
||||
T: DerivedFrom<U>
|
||||
{
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
unsafe { mem::transmute_copy(self) }
|
||||
}
|
||||
|
||||
/// Cast a DOM object downwards to one of the interfaces it might implement.
|
||||
pub fn downcast<U>(&self) -> Option<LayoutJS<U>> where U: DerivedFrom<T> {
|
||||
pub fn downcast<U>(&self) -> Option<LayoutJS<U>>
|
||||
where U: DerivedFrom<T>
|
||||
{
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
unsafe {
|
||||
if (*self.unsafe_get()).is::<U>() {
|
||||
@ -164,11 +169,15 @@ impl<T> PartialEq for LayoutJS<T> {
|
||||
impl<T> Eq for LayoutJS<T> {}
|
||||
|
||||
impl<T> Hash for JS<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) { self.ptr.hash(state) }
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.ptr.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Hash for LayoutJS<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) { self.ptr.hash(state) }
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.ptr.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl <T> Clone for JS<T> {
|
||||
@ -177,7 +186,7 @@ impl <T> Clone for JS<T> {
|
||||
fn clone(&self) -> JS<T> {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
JS {
|
||||
ptr: self.ptr.clone()
|
||||
ptr: self.ptr.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,7 +196,7 @@ impl <T> Clone for LayoutJS<T> {
|
||||
fn clone(&self) -> LayoutJS<T> {
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
LayoutJS {
|
||||
ptr: self.ptr.clone()
|
||||
ptr: self.ptr.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,12 +204,11 @@ impl <T> Clone for LayoutJS<T> {
|
||||
impl LayoutJS<Node> {
|
||||
/// Create a new JS-owned value wrapped from an address known to be a
|
||||
/// `Node` pointer.
|
||||
pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress)
|
||||
-> LayoutJS<Node> {
|
||||
pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> LayoutJS<Node> {
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
let TrustedNodeAddress(addr) = inner;
|
||||
LayoutJS {
|
||||
ptr: NonZero::new(addr as *const Node)
|
||||
ptr: NonZero::new(addr as *const Node),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -325,7 +333,7 @@ impl<T: Reflectable + PartialEq> PartialEq<T> for MutHeap<JS<T>> {
|
||||
#[must_root]
|
||||
#[derive(JSTraceable)]
|
||||
pub struct MutNullableHeap<T: HeapGCValue> {
|
||||
ptr: UnsafeCell<Option<T>>
|
||||
ptr: UnsafeCell<Option<T>>,
|
||||
}
|
||||
|
||||
impl<T: Reflectable> MutNullableHeap<JS<T>> {
|
||||
@ -333,7 +341,7 @@ impl<T: Reflectable> MutNullableHeap<JS<T>> {
|
||||
pub fn new(initial: Option<&T>) -> MutNullableHeap<JS<T>> {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
MutNullableHeap {
|
||||
ptr: UnsafeCell::new(initial.map(JS::from_ref))
|
||||
ptr: UnsafeCell::new(initial.map(JS::from_ref)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,7 +409,7 @@ impl<T: HeapGCValue> Default for MutNullableHeap<T> {
|
||||
fn default() -> MutNullableHeap<T> {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
MutNullableHeap {
|
||||
ptr: UnsafeCell::new(None)
|
||||
ptr: UnsafeCell::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -463,7 +471,9 @@ pub struct RootCollectionPtr(pub *const RootCollection);
|
||||
|
||||
impl Copy for RootCollectionPtr {}
|
||||
impl Clone for RootCollectionPtr {
|
||||
fn clone(&self) -> RootCollectionPtr { *self }
|
||||
fn clone(&self) -> RootCollectionPtr {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl RootCollection {
|
||||
@ -471,7 +481,7 @@ impl RootCollection {
|
||||
pub fn new() -> RootCollection {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
RootCollection {
|
||||
roots: UnsafeCell::new(vec!()),
|
||||
roots: UnsafeCell::new(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,7 +505,7 @@ impl RootCollection {
|
||||
Some(idx) => {
|
||||
roots.remove(idx);
|
||||
},
|
||||
None => panic!("Can't remove a root that was never rooted!")
|
||||
None => panic!("Can't remove a root that was never rooted!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -528,12 +538,17 @@ pub struct Root<T: Reflectable> {
|
||||
|
||||
impl<T: Castable> Root<T> {
|
||||
/// Cast a DOM object root upwards to one of the interfaces it derives from.
|
||||
pub fn upcast<U>(root: Root<T>) -> Root<U> where U: Castable, T: DerivedFrom<U> {
|
||||
pub fn upcast<U>(root: Root<T>) -> Root<U>
|
||||
where U: Castable,
|
||||
T: DerivedFrom<U>
|
||||
{
|
||||
unsafe { mem::transmute(root) }
|
||||
}
|
||||
|
||||
/// Cast a DOM object root downwards to one of the interfaces it might implement.
|
||||
pub fn downcast<U>(root: Root<T>) -> Option<Root<U>> where U: DerivedFrom<T> {
|
||||
pub fn downcast<U>(root: Root<T>) -> Option<Root<U>>
|
||||
where U: DerivedFrom<T>
|
||||
{
|
||||
if root.is::<U>() {
|
||||
Some(unsafe { mem::transmute(root) })
|
||||
} else {
|
||||
@ -546,8 +561,7 @@ impl<T: Reflectable> Root<T> {
|
||||
/// Create a new stack-bounded root for the provided JS-owned value.
|
||||
/// It cannot not outlive its associated `RootCollection`, and it gives
|
||||
/// out references which cannot outlive this new `Root`.
|
||||
pub fn new(unrooted: NonZero<*const T>)
|
||||
-> Root<T> {
|
||||
pub fn new(unrooted: NonZero<*const T>) -> Root<T> {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
STACK_ROOTS.with(|ref collection| {
|
||||
let RootCollectionPtr(collection) = collection.get().unwrap();
|
||||
@ -587,6 +601,8 @@ impl<T: Reflectable> PartialEq for Root<T> {
|
||||
|
||||
impl<T: Reflectable> Drop for Root<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { (*self.root_list).unroot(self); }
|
||||
unsafe {
|
||||
(*self.root_list).unroot(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ impl<T: Float> Finite<T> {
|
||||
/// Create a new `Finite<T: Float>`.
|
||||
#[inline]
|
||||
pub fn wrap(value: T) -> Finite<T> {
|
||||
assert!(value.is_finite(), "Finite<T> doesn't encapsulate unrestricted value.");
|
||||
assert!(value.is_finite(),
|
||||
"Finite<T> doesn't encapsulate unrestricted value.");
|
||||
Finite(value)
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ use js::glue::GetProxyExtra;
|
||||
use js::glue::InvokeGetOwnPropertyDescriptor;
|
||||
use js::glue::{GetProxyHandler, SetProxyExtra};
|
||||
use js::jsapi::GetObjectProto;
|
||||
use js::jsapi::JS_GetPropertyDescriptorById;
|
||||
use js::jsapi::{Handle, HandleId, HandleObject, MutableHandle, ObjectOpResult, RootedObject};
|
||||
use js::jsapi::{JSContext, JSObject, JSPropertyDescriptor};
|
||||
use js::jsapi::{JSErrNum, JS_StrictPropertyStub};
|
||||
use js::jsapi::{JS_DefinePropertyById6, JS_NewObjectWithGivenProto};
|
||||
use js::jsapi::{JS_GetPropertyDescriptorById};
|
||||
use js::jsval::ObjectValue;
|
||||
use js::{JSPROP_ENUMERATE, JSPROP_GETTER, JSPROP_READONLY};
|
||||
use libc;
|
||||
@ -28,11 +28,11 @@ static JSPROXYSLOT_EXPANDO: u32 = 0;
|
||||
/// with argument `id` and return the result, if it is not `undefined`.
|
||||
/// Otherwise, walk along the prototype chain to find a property with that
|
||||
/// name.
|
||||
pub unsafe extern fn get_property_descriptor(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
desc: MutableHandle<JSPropertyDescriptor>)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn get_property_descriptor(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
desc: MutableHandle<JSPropertyDescriptor>)
|
||||
-> bool {
|
||||
let handler = GetProxyHandler(proxy.get());
|
||||
if !InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) {
|
||||
return false;
|
||||
@ -51,11 +51,13 @@ pub unsafe extern fn get_property_descriptor(cx: *mut JSContext,
|
||||
}
|
||||
|
||||
/// Defines an expando on the given `proxy`.
|
||||
pub unsafe extern fn define_property(cx: *mut JSContext, proxy: HandleObject,
|
||||
id: HandleId, desc: Handle<JSPropertyDescriptor>,
|
||||
result: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
//FIXME: Workaround for https://github.com/mozilla/rust/issues/13385
|
||||
pub unsafe extern "C" fn define_property(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
desc: Handle<JSPropertyDescriptor>,
|
||||
result: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
// FIXME: Workaround for https://github.com/mozilla/rust/issues/13385
|
||||
let setter: *const libc::c_void = mem::transmute(desc.get().setter);
|
||||
let setter_stub: *const libc::c_void = mem::transmute(JS_StrictPropertyStub);
|
||||
if (desc.get().attrs & JSPROP_GETTER) != 0 && setter == setter_stub {
|
||||
@ -68,8 +70,11 @@ pub unsafe extern fn define_property(cx: *mut JSContext, proxy: HandleObject,
|
||||
}
|
||||
|
||||
/// Deletes an expando off the given `proxy`.
|
||||
pub unsafe extern fn delete(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
|
||||
bp: *mut ObjectOpResult) -> bool {
|
||||
pub unsafe extern "C" fn delete(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
bp: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
let expando = RootedObject::new(cx, get_expando_object(proxy));
|
||||
if expando.ptr.is_null() {
|
||||
(*bp).code_ = 0 /* OkCode */;
|
||||
@ -80,16 +85,19 @@ pub unsafe extern fn delete(cx: *mut JSContext, proxy: HandleObject, id: HandleI
|
||||
}
|
||||
|
||||
/// Controls whether the Extensible bit can be changed
|
||||
pub unsafe extern fn prevent_extensions(_cx: *mut JSContext,
|
||||
_proxy: HandleObject,
|
||||
result: *mut ObjectOpResult) -> bool {
|
||||
pub unsafe extern "C" fn prevent_extensions(_cx: *mut JSContext,
|
||||
_proxy: HandleObject,
|
||||
result: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
(*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as ::libc::uintptr_t;
|
||||
true
|
||||
}
|
||||
|
||||
/// Reports whether the object is Extensible
|
||||
pub unsafe extern fn is_extensible(_cx: *mut JSContext, _proxy: HandleObject,
|
||||
succeeded: *mut bool) -> bool {
|
||||
pub unsafe extern "C" fn is_extensible(_cx: *mut JSContext,
|
||||
_proxy: HandleObject,
|
||||
succeeded: *mut bool)
|
||||
-> bool {
|
||||
*succeeded = true;
|
||||
true
|
||||
}
|
||||
@ -109,8 +117,7 @@ pub fn get_expando_object(obj: HandleObject) -> *mut JSObject {
|
||||
|
||||
/// Get the expando object, or create it if it doesn't exist yet.
|
||||
/// Fails on JSAPI failure.
|
||||
pub fn ensure_expando_object(cx: *mut JSContext, obj: HandleObject)
|
||||
-> *mut JSObject {
|
||||
pub fn ensure_expando_object(cx: *mut JSContext, obj: HandleObject) -> *mut JSObject {
|
||||
unsafe {
|
||||
assert!(is_dom_proxy(obj.get()));
|
||||
let mut expando = get_expando_object(obj);
|
||||
@ -127,7 +134,8 @@ pub fn ensure_expando_object(cx: *mut JSContext, obj: HandleObject)
|
||||
/// Set the property descriptor's object to `obj` and set it to enumerable,
|
||||
/// and writable if `readonly` is true.
|
||||
pub fn fill_property_descriptor(desc: &mut JSPropertyDescriptor,
|
||||
obj: *mut JSObject, readonly: bool) {
|
||||
obj: *mut JSObject,
|
||||
readonly: bool) {
|
||||
desc.obj = obj;
|
||||
desc.attrs = if readonly { JSPROP_READONLY } else { 0 } | JSPROP_ENUMERATE;
|
||||
desc.getter = None;
|
||||
|
@ -138,7 +138,7 @@ impl<T: Reflectable> Drop for Trusted<T> {
|
||||
/// from being garbage collected due to outstanding references.
|
||||
pub struct LiveDOMReferences {
|
||||
// keyed on pointer to Rust DOM object
|
||||
table: RefCell<HashMap<*const libc::c_void, Arc<Mutex<usize>>>>
|
||||
table: RefCell<HashMap<*const libc::c_void, Arc<Mutex<usize>>>>,
|
||||
}
|
||||
|
||||
impl LiveDOMReferences {
|
||||
@ -197,7 +197,8 @@ impl LiveDOMReferences {
|
||||
}
|
||||
|
||||
/// A JSTraceDataOp for tracing reflectors held in LIVE_REFERENCES
|
||||
pub unsafe extern fn trace_refcounted_objects(tracer: *mut JSTracer, _data: *mut libc::c_void) {
|
||||
pub unsafe extern "C" fn trace_refcounted_objects(tracer: *mut JSTracer,
|
||||
_data: *mut libc::c_void) {
|
||||
LIVE_REFERENCES.with(|ref r| {
|
||||
let r = r.borrow();
|
||||
let live_references = r.as_ref().unwrap();
|
||||
|
@ -12,11 +12,10 @@ use std::ptr;
|
||||
|
||||
/// 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,
|
||||
wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>)
|
||||
-> Root<T> {
|
||||
pub fn reflect_dom_object<T: Reflectable>(obj: Box<T>,
|
||||
global: GlobalRef,
|
||||
wrap_fn: fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>)
|
||||
-> Root<T> {
|
||||
wrap_fn(global.get_cx(), global, obj)
|
||||
}
|
||||
|
||||
@ -65,7 +64,7 @@ impl Reflector {
|
||||
/// Create an uninitialized `Reflector`.
|
||||
pub fn new() -> Reflector {
|
||||
Reflector {
|
||||
object: UnsafeCell::new(ptr::null_mut())
|
||||
object: UnsafeCell::new(ptr::null_mut()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,12 +56,26 @@ impl ByteString {
|
||||
// http://tools.ietf.org/html/rfc2616#section-2.2
|
||||
match x {
|
||||
0...31 | 127 => false, // CTLs
|
||||
40 | 41 | 60 | 62 | 64 |
|
||||
44 | 59 | 58 | 92 | 34 |
|
||||
47 | 91 | 93 | 63 | 61 |
|
||||
123 | 125 | 32 => false, // separators
|
||||
40 |
|
||||
41 |
|
||||
60 |
|
||||
62 |
|
||||
64 |
|
||||
44 |
|
||||
59 |
|
||||
58 |
|
||||
92 |
|
||||
34 |
|
||||
47 |
|
||||
91 |
|
||||
93 |
|
||||
63 |
|
||||
61 |
|
||||
123 |
|
||||
125 |
|
||||
32 => false, // separators
|
||||
x if x > 127 => false, // non-CHARs
|
||||
_ => true
|
||||
_ => true,
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -75,7 +89,7 @@ impl ByteString {
|
||||
Other,
|
||||
CR,
|
||||
LF,
|
||||
SPHT // SP or HT
|
||||
SPHT, // SP or HT
|
||||
}
|
||||
let ByteString(ref vec) = *self;
|
||||
let mut prev = PreviousCharacter::Other; // The previous character
|
||||
|
@ -22,17 +22,22 @@ pub struct StructuredCloneData {
|
||||
|
||||
impl StructuredCloneData {
|
||||
/// Writes a structured clone. Returns a `DataClone` error if that fails.
|
||||
pub fn write(cx: *mut JSContext, message: HandleValue)
|
||||
-> Fallible<StructuredCloneData> {
|
||||
pub fn write(cx: *mut JSContext, message: HandleValue) -> Fallible<StructuredCloneData> {
|
||||
let mut data = ptr::null_mut();
|
||||
let mut nbytes = 0;
|
||||
let result = unsafe {
|
||||
JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes,
|
||||
ptr::null(), ptr::null_mut(),
|
||||
JS_WriteStructuredClone(cx,
|
||||
message,
|
||||
&mut data,
|
||||
&mut nbytes,
|
||||
ptr::null(),
|
||||
ptr::null_mut(),
|
||||
HandleValue::undefined())
|
||||
};
|
||||
if !result {
|
||||
unsafe { JS_ClearPendingException(cx); }
|
||||
unsafe {
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
return Err(Error::DataClone);
|
||||
}
|
||||
Ok(StructuredCloneData {
|
||||
@ -46,10 +51,13 @@ impl StructuredCloneData {
|
||||
/// Panics if `JS_ReadStructuredClone` fails.
|
||||
pub fn read(self, global: GlobalRef, rval: MutableHandleValue) {
|
||||
unsafe {
|
||||
assert!(JS_ReadStructuredClone(
|
||||
global.get_cx(), self.data, self.nbytes,
|
||||
JS_STRUCTURED_CLONE_VERSION, rval,
|
||||
ptr::null(), ptr::null_mut()));
|
||||
assert!(JS_ReadStructuredClone(global.get_cx(),
|
||||
self.data,
|
||||
self.nbytes,
|
||||
JS_STRUCTURED_CLONE_VERSION,
|
||||
rval,
|
||||
ptr::null(),
|
||||
ptr::null_mut()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,8 @@ pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>)
|
||||
(*tracer).debugPrintIndex_ = !0;
|
||||
(*tracer).debugPrintArg_ = name.as_ptr() as *const libc::c_void;
|
||||
debug!("tracing value {}", description);
|
||||
JS_CallValueTracer(tracer, val.ptr.get() as *mut _,
|
||||
JS_CallValueTracer(tracer,
|
||||
val.ptr.get() as *mut _,
|
||||
GCTraceKindToAscii(val.get().trace_kind()));
|
||||
}
|
||||
}
|
||||
@ -126,7 +127,8 @@ pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Ref
|
||||
(*tracer).debugPrintIndex_ = !0;
|
||||
(*tracer).debugPrintArg_ = name.as_ptr() as *const libc::c_void;
|
||||
debug!("tracing reflector {}", description);
|
||||
JS_CallUnbarrieredObjectTracer(tracer, reflector.rootable(),
|
||||
JS_CallUnbarrieredObjectTracer(tracer,
|
||||
reflector.rootable(),
|
||||
GCTraceKindToAscii(JSGCTraceKind::JSTRACE_OBJECT));
|
||||
}
|
||||
}
|
||||
@ -139,7 +141,8 @@ pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: &Heap<*mut JS
|
||||
(*tracer).debugPrintIndex_ = !0;
|
||||
(*tracer).debugPrintArg_ = name.as_ptr() as *const libc::c_void;
|
||||
debug!("tracing {}", description);
|
||||
JS_CallObjectTracer(tracer, obj.ptr.get() as *mut _,
|
||||
JS_CallObjectTracer(tracer,
|
||||
obj.ptr.get() as *mut _,
|
||||
GCTraceKindToAscii(JSGCTraceKind::JSTRACE_OBJECT));
|
||||
}
|
||||
}
|
||||
@ -354,12 +357,12 @@ impl<T> JSTraceable for IpcReceiver<T> where T: Deserialize + Serialize {
|
||||
/// Homemade trait object for JSTraceable things
|
||||
struct TraceableInfo {
|
||||
pub ptr: *const libc::c_void,
|
||||
pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer)
|
||||
pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer),
|
||||
}
|
||||
|
||||
/// Holds a set of JSTraceables that need to be rooted
|
||||
pub struct RootedTraceableSet {
|
||||
set: Vec<TraceableInfo>
|
||||
set: Vec<TraceableInfo>,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)] // FIXME
|
||||
@ -376,7 +379,7 @@ pub use self::dummy::ROOTED_TRACEABLES;
|
||||
impl RootedTraceableSet {
|
||||
fn new() -> RootedTraceableSet {
|
||||
RootedTraceableSet {
|
||||
set: vec!()
|
||||
set: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,7 +427,7 @@ impl RootedTraceableSet {
|
||||
/// If you know what you're doing, use this.
|
||||
#[derive(JSTraceable)]
|
||||
pub struct RootedTraceable<'a, T: 'a + JSTraceable> {
|
||||
ptr: &'a T
|
||||
ptr: &'a T,
|
||||
}
|
||||
|
||||
impl<'a, T: JSTraceable> RootedTraceable<'a, T> {
|
||||
@ -433,7 +436,9 @@ impl<'a, T: JSTraceable> RootedTraceable<'a, T> {
|
||||
unsafe {
|
||||
RootedTraceableSet::add(traceable);
|
||||
}
|
||||
RootedTraceable { ptr: traceable }
|
||||
RootedTraceable {
|
||||
ptr: traceable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,7 +456,7 @@ impl<'a, T: JSTraceable> Drop for RootedTraceable<'a, T> {
|
||||
#[derive(JSTraceable)]
|
||||
#[allow_unrooted_interior]
|
||||
pub struct RootedVec<T: JSTraceable> {
|
||||
v: Vec<T>
|
||||
v: Vec<T>,
|
||||
}
|
||||
|
||||
|
||||
@ -459,9 +464,7 @@ impl<T: JSTraceable> RootedVec<T> {
|
||||
/// Create a vector of items of type T that is rooted for
|
||||
/// the lifetime of this struct
|
||||
pub fn new() -> RootedVec<T> {
|
||||
let addr = unsafe {
|
||||
return_address() as *const libc::c_void
|
||||
};
|
||||
let addr = unsafe { return_address() as *const libc::c_void };
|
||||
|
||||
unsafe { RootedVec::new_with_destination_address(addr) }
|
||||
}
|
||||
@ -470,7 +473,9 @@ impl<T: JSTraceable> RootedVec<T> {
|
||||
/// for RootTraceableSet.
|
||||
pub unsafe fn new_with_destination_address(addr: *const libc::c_void) -> RootedVec<T> {
|
||||
RootedTraceableSet::add::<RootedVec<T>>(&*(addr as *const _));
|
||||
RootedVec::<T> { v: vec!() }
|
||||
RootedVec::<T> {
|
||||
v: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,7 +509,9 @@ impl<T: JSTraceable> DerefMut for RootedVec<T> {
|
||||
|
||||
impl<A: JSTraceable + Reflectable> FromIterator<Root<A>> for RootedVec<JS<A>> {
|
||||
#[allow(moved_no_move)]
|
||||
fn from_iter<T>(iterable: T) -> RootedVec<JS<A>> where T: IntoIterator<Item=Root<A>> {
|
||||
fn from_iter<T>(iterable: T) -> RootedVec<JS<A>>
|
||||
where T: IntoIterator<Item = Root<A>>
|
||||
{
|
||||
let mut vec = unsafe {
|
||||
RootedVec::new_with_destination_address(return_address() as *const libc::c_void)
|
||||
};
|
||||
|
@ -58,7 +58,7 @@ pub struct WindowProxyHandler(pub *const libc::c_void);
|
||||
|
||||
impl HeapSizeOf for WindowProxyHandler {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
//FIXME(#6907) this is a pointer to memory allocated by `new` in NewProxyHandler in rust-mozjs.
|
||||
// FIXME(#6907) this is a pointer to memory allocated by `new` in NewProxyHandler in rust-mozjs.
|
||||
0
|
||||
}
|
||||
}
|
||||
@ -116,7 +116,7 @@ pub struct ConstantSpec {
|
||||
/// name of the constant.
|
||||
pub name: &'static [u8],
|
||||
/// value of the constant.
|
||||
pub value: ConstantVal
|
||||
pub value: ConstantVal,
|
||||
}
|
||||
|
||||
impl ConstantSpec {
|
||||
@ -166,10 +166,12 @@ pub struct DOMJSClass {
|
||||
/// The actual JSClass.
|
||||
pub base: js::jsapi::Class,
|
||||
/// Associated data for DOM object reflectors.
|
||||
pub dom_class: DOMClass
|
||||
pub dom_class: DOMClass,
|
||||
}
|
||||
impl Clone for DOMJSClass {
|
||||
fn clone(&self) -> DOMJSClass { *self }
|
||||
fn clone(&self) -> DOMJSClass {
|
||||
*self
|
||||
}
|
||||
}
|
||||
unsafe impl Sync for DOMJSClass {}
|
||||
|
||||
@ -216,17 +218,17 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
|
||||
rval: MutableHandleObject) {
|
||||
assert!(rval.get().is_null());
|
||||
if let Some(proto_class) = proto_class {
|
||||
create_interface_prototype_object(cx, proto_proto,
|
||||
proto_class, members, rval);
|
||||
create_interface_prototype_object(cx, proto_proto, proto_class, members, rval);
|
||||
|
||||
if !rval.get().is_null() {
|
||||
let dom_class_ptr = match dom_class {
|
||||
Some(dom_class) => dom_class as *const DOMClass as *const libc::c_void,
|
||||
None => ptr::null() as *const libc::c_void,
|
||||
None => ptr::null() as *const libc::c_void,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
JS_SetReservedSlot(rval.get(), DOM_PROTO_INSTANCE_CLASS_SLOT,
|
||||
JS_SetReservedSlot(rval.get(),
|
||||
DOM_PROTO_INSTANCE_CLASS_SLOT,
|
||||
PrivateValue(dom_class_ptr));
|
||||
}
|
||||
}
|
||||
@ -234,22 +236,30 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
|
||||
|
||||
if let Some((native, name, nargs)) = constructor {
|
||||
let s = CString::new(name).unwrap();
|
||||
create_interface_object(cx, receiver,
|
||||
native, nargs, rval.handle(),
|
||||
members, s.as_ptr())
|
||||
create_interface_object(cx,
|
||||
receiver,
|
||||
native,
|
||||
nargs,
|
||||
rval.handle(),
|
||||
members,
|
||||
s.as_ptr())
|
||||
}
|
||||
|
||||
for ctor in named_constructors {
|
||||
let (cnative, cname, cnargs) = *ctor;
|
||||
|
||||
let cs = CString::new(cname).unwrap();
|
||||
let constructor = RootedObject::new(cx, create_constructor(cx, cnative, cnargs, cs.as_ptr()));
|
||||
let constructor = RootedObject::new(cx,
|
||||
create_constructor(cx, cnative, cnargs, cs.as_ptr()));
|
||||
assert!(!constructor.ptr.is_null());
|
||||
unsafe {
|
||||
assert!(JS_DefineProperty1(cx, constructor.handle(), b"prototype\0".as_ptr() as *const libc::c_char,
|
||||
assert!(JS_DefineProperty1(cx,
|
||||
constructor.handle(),
|
||||
b"prototype\0".as_ptr() as *const libc::c_char,
|
||||
rval.handle(),
|
||||
JSPROP_PERMANENT | JSPROP_READONLY,
|
||||
None, None));
|
||||
None,
|
||||
None));
|
||||
}
|
||||
define_constructor(cx, receiver, cs.as_ptr(), constructor.handle());
|
||||
}
|
||||
@ -259,10 +269,14 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
|
||||
fn create_constructor(cx: *mut JSContext,
|
||||
constructor_native: NonNullJSNative,
|
||||
ctor_nargs: u32,
|
||||
name: *const libc::c_char) -> *mut JSObject {
|
||||
name: *const libc::c_char)
|
||||
-> *mut JSObject {
|
||||
unsafe {
|
||||
let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs,
|
||||
JSFUN_CONSTRUCTOR, name);
|
||||
let fun = JS_NewFunction(cx,
|
||||
Some(constructor_native),
|
||||
ctor_nargs,
|
||||
JSFUN_CONSTRUCTOR,
|
||||
name);
|
||||
assert!(!fun.is_null());
|
||||
|
||||
let constructor = JS_GetFunctionObject(fun);
|
||||
@ -281,9 +295,7 @@ fn define_constructor(cx: *mut JSContext,
|
||||
assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined));
|
||||
|
||||
if !already_defined {
|
||||
assert!(JS_DefineProperty1(cx, receiver, name,
|
||||
constructor,
|
||||
0, None, None));
|
||||
assert!(JS_DefineProperty1(cx, receiver, name, constructor, 0, None, None));
|
||||
}
|
||||
|
||||
}
|
||||
@ -294,11 +306,16 @@ fn define_constructor(cx: *mut JSContext,
|
||||
fn create_interface_object(cx: *mut JSContext,
|
||||
receiver: HandleObject,
|
||||
constructor_native: NonNullJSNative,
|
||||
ctor_nargs: u32, proto: HandleObject,
|
||||
ctor_nargs: u32,
|
||||
proto: HandleObject,
|
||||
members: &'static NativeProperties,
|
||||
name: *const libc::c_char) {
|
||||
unsafe {
|
||||
let constructor = RootedObject::new(cx, create_constructor(cx, constructor_native, ctor_nargs, name));
|
||||
let constructor = RootedObject::new(cx,
|
||||
create_constructor(cx,
|
||||
constructor_native,
|
||||
ctor_nargs,
|
||||
name));
|
||||
assert!(!constructor.ptr.is_null());
|
||||
|
||||
if let Some(static_methods) = members.static_methods {
|
||||
@ -323,22 +340,25 @@ fn create_interface_object(cx: *mut JSContext,
|
||||
|
||||
/// Defines constants on `obj`.
|
||||
/// Fails on JSAPI failure.
|
||||
fn define_constants(cx: *mut JSContext, obj: HandleObject,
|
||||
constants: &'static [ConstantSpec]) {
|
||||
fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &'static [ConstantSpec]) {
|
||||
for spec in constants {
|
||||
let value = RootedValue::new(cx, spec.get_value());
|
||||
unsafe {
|
||||
assert!(JS_DefineProperty(cx, obj, spec.name.as_ptr() as *const libc::c_char,
|
||||
assert!(JS_DefineProperty(cx,
|
||||
obj,
|
||||
spec.name.as_ptr() as *const libc::c_char,
|
||||
value.handle(),
|
||||
JSPROP_ENUMERATE | JSPROP_READONLY |
|
||||
JSPROP_PERMANENT, None, None));
|
||||
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT,
|
||||
None,
|
||||
None));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the *interface prototype object*.
|
||||
/// Fails on JSAPI failure.
|
||||
fn create_interface_prototype_object(cx: *mut JSContext, global: HandleObject,
|
||||
fn create_interface_prototype_object(cx: *mut JSContext,
|
||||
global: HandleObject,
|
||||
proto_class: &'static JSClass,
|
||||
members: &'static NativeProperties,
|
||||
rval: MutableHandleObject) {
|
||||
@ -362,8 +382,10 @@ fn create_interface_prototype_object(cx: *mut JSContext, global: HandleObject,
|
||||
|
||||
/// A throwing constructor, for those interfaces that have neither
|
||||
/// `NoInterfaceObject` nor `Constructor`.
|
||||
pub unsafe extern fn throwing_constructor(cx: *mut JSContext, _argc: c_uint,
|
||||
_vp: *mut JSVal) -> bool {
|
||||
pub unsafe extern "C" fn throwing_constructor(cx: *mut JSContext,
|
||||
_argc: c_uint,
|
||||
_vp: *mut JSVal)
|
||||
-> bool {
|
||||
throw_type_error(cx, "Illegal constructor.");
|
||||
false
|
||||
}
|
||||
@ -389,29 +411,31 @@ pub fn initialize_global(global: *mut JSObject) {
|
||||
/// set to true and `*vp` to the value, otherwise `*found` is set to false.
|
||||
///
|
||||
/// Returns false on JSAPI failure.
|
||||
pub fn get_property_on_prototype(cx: *mut JSContext, proxy: HandleObject,
|
||||
id: HandleId, found: *mut bool, vp: MutableHandleValue)
|
||||
pub fn get_property_on_prototype(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
found: *mut bool,
|
||||
vp: MutableHandleValue)
|
||||
-> bool {
|
||||
unsafe {
|
||||
//let proto = GetObjectProto(proxy);
|
||||
let mut proto = RootedObject::new(cx, ptr::null_mut());
|
||||
if !JS_GetPrototype(cx, proxy, proto.handle_mut()) ||
|
||||
proto.ptr.is_null() {
|
||||
*found = false;
|
||||
return true;
|
||||
}
|
||||
let mut has_property = false;
|
||||
if !JS_HasPropertyById(cx, proto.handle(), id, &mut has_property) {
|
||||
return false;
|
||||
}
|
||||
*found = has_property;
|
||||
let no_output = vp.ptr.is_null();
|
||||
if !has_property || no_output {
|
||||
return true;
|
||||
}
|
||||
// let proto = GetObjectProto(proxy);
|
||||
let mut proto = RootedObject::new(cx, ptr::null_mut());
|
||||
if !JS_GetPrototype(cx, proxy, proto.handle_mut()) || proto.ptr.is_null() {
|
||||
*found = false;
|
||||
return true;
|
||||
}
|
||||
let mut has_property = false;
|
||||
if !JS_HasPropertyById(cx, proto.handle(), id, &mut has_property) {
|
||||
return false;
|
||||
}
|
||||
*found = has_property;
|
||||
let no_output = vp.ptr.is_null();
|
||||
if !has_property || no_output {
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_ForwardGetPropertyTo(cx, proto.handle(), id, proxy, vp)
|
||||
}
|
||||
JS_ForwardGetPropertyTo(cx, proto.handle(), id, proxy, vp)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an array index from the given `jsid`. Returns `None` if the given
|
||||
@ -485,17 +509,19 @@ pub fn get_dictionary_property(cx: *mut JSContext,
|
||||
property: &str,
|
||||
rval: MutableHandleValue)
|
||||
-> Result<bool, ()> {
|
||||
fn has_property(cx: *mut JSContext, object: HandleObject, property: &CString,
|
||||
found: &mut bool) -> bool {
|
||||
unsafe {
|
||||
JS_HasProperty(cx, object, property.as_ptr(), found)
|
||||
}
|
||||
fn has_property(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &CString,
|
||||
found: &mut bool)
|
||||
-> bool {
|
||||
unsafe { JS_HasProperty(cx, object, property.as_ptr(), found) }
|
||||
}
|
||||
fn get_property(cx: *mut JSContext, object: HandleObject, property: &CString,
|
||||
value: MutableHandleValue) -> bool {
|
||||
unsafe {
|
||||
JS_GetProperty(cx, object, property.as_ptr(), value)
|
||||
}
|
||||
fn get_property(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &CString,
|
||||
value: MutableHandleValue)
|
||||
-> bool {
|
||||
unsafe { JS_GetProperty(cx, object, property.as_ptr(), value) }
|
||||
}
|
||||
|
||||
let property = CString::new(property).unwrap();
|
||||
@ -525,7 +551,8 @@ pub fn get_dictionary_property(cx: *mut JSContext,
|
||||
pub fn set_dictionary_property(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
property: &str,
|
||||
value: HandleValue) -> Result<(), ()> {
|
||||
value: HandleValue)
|
||||
-> Result<(), ()> {
|
||||
if object.get().is_null() {
|
||||
return Err(());
|
||||
}
|
||||
@ -541,16 +568,17 @@ pub fn set_dictionary_property(cx: *mut JSContext,
|
||||
}
|
||||
|
||||
/// Returns whether `proxy` has a property `id` on its prototype.
|
||||
pub fn has_property_on_prototype(cx: *mut JSContext, proxy: HandleObject,
|
||||
id: HandleId) -> bool {
|
||||
// MOZ_ASSERT(js::IsProxy(proxy) && js::GetProxyHandler(proxy) == handler);
|
||||
pub fn has_property_on_prototype(cx: *mut JSContext, proxy: HandleObject, id: HandleId) -> bool {
|
||||
// MOZ_ASSERT(js::IsProxy(proxy) && js::GetProxyHandler(proxy) == handler);
|
||||
let mut found = false;
|
||||
!get_property_on_prototype(cx, proxy, id, &mut found,
|
||||
unsafe { MutableHandleValue::from_marked_location(ptr::null_mut()) }) || found
|
||||
!get_property_on_prototype(cx, proxy, id, &mut found, unsafe {
|
||||
MutableHandleValue::from_marked_location(ptr::null_mut())
|
||||
}) || found
|
||||
}
|
||||
|
||||
/// Create a DOM global object with the given class.
|
||||
pub fn create_dom_global(cx: *mut JSContext, class: *const JSClass,
|
||||
pub fn create_dom_global(cx: *mut JSContext,
|
||||
class: *const JSClass,
|
||||
private: *const libc::c_void,
|
||||
trace: JSTraceOp)
|
||||
-> *mut JSObject {
|
||||
@ -561,8 +589,11 @@ pub fn create_dom_global(cx: *mut JSContext, class: *const JSClass,
|
||||
|
||||
let obj =
|
||||
RootedObject::new(cx,
|
||||
JS_NewGlobalObject(cx, class, ptr::null_mut(),
|
||||
OnNewGlobalHookOption::DontFireOnNewGlobalHook, &options));
|
||||
JS_NewGlobalObject(cx,
|
||||
class,
|
||||
ptr::null_mut(),
|
||||
OnNewGlobalHookOption::DontFireOnNewGlobalHook,
|
||||
&options));
|
||||
if obj.ptr.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
@ -586,8 +617,7 @@ pub unsafe fn finalize_global(obj: *mut JSObject) {
|
||||
<*mut JSObject>::relocate(entry);
|
||||
}
|
||||
}
|
||||
let _: Box<ProtoOrIfaceArray> =
|
||||
Box::from_raw(protolist);
|
||||
let _: Box<ProtoOrIfaceArray> = Box::from_raw(protolist);
|
||||
}
|
||||
|
||||
/// Trace the resources held by reserved slots of a global object
|
||||
@ -595,23 +625,27 @@ pub unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) {
|
||||
let array = get_proto_or_iface_array(obj);
|
||||
for proto in (*array).iter() {
|
||||
if !proto.is_null() {
|
||||
trace_object(tracer, "prototype", &*(proto as *const *mut JSObject as *const Heap<*mut JSObject>));
|
||||
trace_object(tracer,
|
||||
"prototype",
|
||||
&*(proto as *const *mut JSObject as *const Heap<*mut JSObject>));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern fn wrap(cx: *mut JSContext,
|
||||
_existing: HandleObject,
|
||||
obj: HandleObject)
|
||||
-> *mut JSObject {
|
||||
unsafe extern "C" fn wrap(cx: *mut JSContext,
|
||||
_existing: HandleObject,
|
||||
obj: HandleObject)
|
||||
-> *mut JSObject {
|
||||
// FIXME terrible idea. need security wrappers
|
||||
// https://github.com/servo/servo/issues/2382
|
||||
WrapperNew(cx, obj, GetCrossCompartmentWrapper(), ptr::null(), false)
|
||||
}
|
||||
|
||||
unsafe extern fn pre_wrap(cx: *mut JSContext, _existing: HandleObject,
|
||||
obj: HandleObject, _object_passed_to_wrap: HandleObject)
|
||||
-> *mut JSObject {
|
||||
unsafe extern "C" fn pre_wrap(cx: *mut JSContext,
|
||||
_existing: HandleObject,
|
||||
obj: HandleObject,
|
||||
_object_passed_to_wrap: HandleObject)
|
||||
-> *mut JSObject {
|
||||
let _ac = JSAutoCompartment::new(cx, obj.get());
|
||||
JS_ObjectToOuterObject(cx, obj)
|
||||
}
|
||||
@ -623,7 +657,7 @@ pub static WRAP_CALLBACKS: JSWrapObjectCallbacks = JSWrapObjectCallbacks {
|
||||
};
|
||||
|
||||
/// Callback to outerize windows.
|
||||
pub unsafe extern fn outerize_global(_cx: *mut JSContext, obj: HandleObject) -> *mut JSObject {
|
||||
pub unsafe extern "C" fn outerize_global(_cx: *mut JSContext, obj: HandleObject) -> *mut JSObject {
|
||||
debug!("outerizing");
|
||||
let win = root_from_handleobject::<window::Window>(obj).unwrap();
|
||||
let context = win.browsing_context();
|
||||
@ -631,12 +665,17 @@ pub unsafe extern fn outerize_global(_cx: *mut JSContext, obj: HandleObject) ->
|
||||
}
|
||||
|
||||
/// Deletes the property `id` from `object`.
|
||||
pub unsafe fn delete_property_by_id(cx: *mut JSContext, object: HandleObject,
|
||||
id: HandleId, bp: *mut ObjectOpResult) -> bool {
|
||||
pub unsafe fn delete_property_by_id(cx: *mut JSContext,
|
||||
object: HandleObject,
|
||||
id: HandleId,
|
||||
bp: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
JS_DeletePropertyById1(cx, object, id, bp)
|
||||
}
|
||||
|
||||
unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal,
|
||||
unsafe fn generic_call(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal,
|
||||
is_lenient: bool,
|
||||
call: unsafe extern fn(*const JSJitInfo, *mut JSContext,
|
||||
HandleObject, *mut libc::c_void, u32,
|
||||
@ -677,31 +716,36 @@ unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal,
|
||||
}
|
||||
|
||||
/// Generic method of IDL interface.
|
||||
pub unsafe extern fn generic_method(cx: *mut JSContext,
|
||||
argc: libc::c_uint, vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_method(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
generic_call(cx, argc, vp, false, CallJitMethodOp)
|
||||
}
|
||||
|
||||
/// Generic getter of IDL interface.
|
||||
pub unsafe extern fn generic_getter(cx: *mut JSContext,
|
||||
argc: libc::c_uint, vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_getter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
generic_call(cx, argc, vp, false, CallJitGetterOp)
|
||||
}
|
||||
|
||||
/// Generic lenient getter of IDL interface.
|
||||
pub unsafe extern fn generic_lenient_getter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_lenient_getter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
generic_call(cx, argc, vp, true, CallJitGetterOp)
|
||||
}
|
||||
|
||||
unsafe extern fn call_setter(info: *const JSJitInfo, cx: *mut JSContext,
|
||||
handle: HandleObject, this: *mut libc::c_void,
|
||||
argc: u32, vp: *mut JSVal)
|
||||
-> bool {
|
||||
unsafe extern "C" fn call_setter(info: *const JSJitInfo,
|
||||
cx: *mut JSContext,
|
||||
handle: HandleObject,
|
||||
this: *mut libc::c_void,
|
||||
argc: u32,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
if !CallJitSetterOp(info, cx, handle, this, argc, vp) {
|
||||
return false;
|
||||
}
|
||||
@ -710,23 +754,25 @@ unsafe extern fn call_setter(info: *const JSJitInfo, cx: *mut JSContext,
|
||||
}
|
||||
|
||||
/// Generic setter of IDL interface.
|
||||
pub unsafe extern fn generic_setter(cx: *mut JSContext,
|
||||
argc: libc::c_uint, vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_setter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
generic_call(cx, argc, vp, false, call_setter)
|
||||
}
|
||||
|
||||
/// Generic lenient setter of IDL interface.
|
||||
pub unsafe extern fn generic_lenient_setter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
pub unsafe extern "C" fn generic_lenient_setter(cx: *mut JSContext,
|
||||
argc: libc::c_uint,
|
||||
vp: *mut JSVal)
|
||||
-> bool {
|
||||
generic_call(cx, argc, vp, true, call_setter)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi::Class,
|
||||
proto_id: u32,
|
||||
depth: u32) -> bool {
|
||||
depth: u32)
|
||||
-> bool {
|
||||
let domclass: *const DOMJSClass = clasp as *const _;
|
||||
let domclass = &*domclass;
|
||||
domclass.dom_class.interface_chain[depth as usize] as u32 == proto_id
|
||||
|
@ -50,8 +50,9 @@ pub trait WeakReferenceable: Reflectable + Sized {
|
||||
fn downgrade(&self) -> WeakRef<Self> {
|
||||
unsafe {
|
||||
let object = self.reflector().get_jsobject().get();
|
||||
let mut ptr =
|
||||
JS_GetReservedSlot(object, DOM_WEAK_SLOT).to_private() as *mut WeakBox<Self>;
|
||||
let mut ptr = JS_GetReservedSlot(object,
|
||||
DOM_WEAK_SLOT)
|
||||
.to_private() as *mut WeakBox<Self>;
|
||||
if ptr.is_null() {
|
||||
debug!("Creating new WeakBox holder for {:p}.", self);
|
||||
ptr = Box::into_raw(box WeakBox {
|
||||
@ -63,9 +64,13 @@ pub trait WeakReferenceable: Reflectable + Sized {
|
||||
let box_ = &*ptr;
|
||||
assert!(box_.value.get().is_some());
|
||||
let new_count = box_.count.get() + 1;
|
||||
debug!("Incrementing WeakBox refcount for {:p} to {}.", self, new_count);
|
||||
debug!("Incrementing WeakBox refcount for {:p} to {}.",
|
||||
self,
|
||||
new_count);
|
||||
box_.count.set(new_count);
|
||||
WeakRef { ptr: NonZero::new(ptr) }
|
||||
WeakRef {
|
||||
ptr: NonZero::new(ptr),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,7 +100,9 @@ impl<T: WeakReferenceable> Clone for WeakRef<T> {
|
||||
let box_ = &**self.ptr;
|
||||
let new_count = box_.count.get() + 1;
|
||||
box_.count.set(new_count);
|
||||
WeakRef { ptr: self.ptr }
|
||||
WeakRef {
|
||||
ptr: self.ptr,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,7 +150,9 @@ impl<T: WeakReferenceable> MutableWeakRef<T> {
|
||||
|
||||
/// Set the pointee of a mutable weak reference.
|
||||
pub fn set(&self, value: Option<&T>) {
|
||||
unsafe { *self.cell.get() = value.map(WeakRef::new); }
|
||||
unsafe {
|
||||
*self.cell.get() = value.map(WeakRef::new);
|
||||
}
|
||||
}
|
||||
|
||||
/// Root a mutable weak reference. Returns `None` if the object
|
||||
|
@ -19,13 +19,14 @@ pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult {
|
||||
// Step 2.
|
||||
Err(Error::Namespace)
|
||||
},
|
||||
XMLName::QName => Ok(())
|
||||
XMLName::QName => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Validate a namespace and qualified name and extract their parts.
|
||||
/// See https://dom.spec.whatwg.org/#validate-and-extract for details.
|
||||
pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str)
|
||||
pub fn validate_and_extract(namespace: Option<DOMString>,
|
||||
qualified_name: &str)
|
||||
-> Fallible<(Namespace, Option<Atom>, Atom)> {
|
||||
// Step 1.
|
||||
let namespace = namespace_from_domstring(namespace);
|
||||
@ -64,8 +65,7 @@ pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str)
|
||||
// Step 7.
|
||||
Err(Error::Namespace)
|
||||
},
|
||||
(ref ns, p) if ns != &ns!(XMLNS) &&
|
||||
(qualified_name == "xmlns" || p == Some("xmlns")) => {
|
||||
(ref ns, p) if ns != &ns!(XMLNS) && (qualified_name == "xmlns" || p == Some("xmlns")) => {
|
||||
// Step 8.
|
||||
Err(Error::Namespace)
|
||||
},
|
||||
@ -86,7 +86,7 @@ pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str)
|
||||
pub enum XMLName {
|
||||
QName,
|
||||
Name,
|
||||
InvalidXMLName
|
||||
InvalidXMLName,
|
||||
}
|
||||
|
||||
/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name
|
||||
@ -95,33 +95,34 @@ pub fn xml_name_type(name: &str) -> XMLName {
|
||||
fn is_valid_start(c: char) -> bool {
|
||||
match c {
|
||||
':' |
|
||||
'A' ... 'Z' |
|
||||
'A'...'Z' |
|
||||
'_' |
|
||||
'a' ... 'z' |
|
||||
'\u{C0}' ... '\u{D6}' |
|
||||
'\u{D8}' ... '\u{F6}' |
|
||||
'\u{F8}' ... '\u{2FF}' |
|
||||
'\u{370}' ... '\u{37D}' |
|
||||
'\u{37F}' ... '\u{1FFF}' |
|
||||
'\u{200C}' ... '\u{200D}' |
|
||||
'\u{2070}' ... '\u{218F}' |
|
||||
'\u{2C00}' ... '\u{2FEF}' |
|
||||
'\u{3001}' ... '\u{D7FF}' |
|
||||
'\u{F900}' ... '\u{FDCF}' |
|
||||
'\u{FDF0}' ... '\u{FFFD}' |
|
||||
'\u{10000}' ... '\u{EFFFF}' => true,
|
||||
'a'...'z' |
|
||||
'\u{C0}'...'\u{D6}' |
|
||||
'\u{D8}'...'\u{F6}' |
|
||||
'\u{F8}'...'\u{2FF}' |
|
||||
'\u{370}'...'\u{37D}' |
|
||||
'\u{37F}'...'\u{1FFF}' |
|
||||
'\u{200C}'...'\u{200D}' |
|
||||
'\u{2070}'...'\u{218F}' |
|
||||
'\u{2C00}'...'\u{2FEF}' |
|
||||
'\u{3001}'...'\u{D7FF}' |
|
||||
'\u{F900}'...'\u{FDCF}' |
|
||||
'\u{FDF0}'...'\u{FFFD}' |
|
||||
'\u{10000}'...'\u{EFFFF}' => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_valid_continuation(c: char) -> bool {
|
||||
is_valid_start(c) || match c {
|
||||
is_valid_start(c) ||
|
||||
match c {
|
||||
'-' |
|
||||
'.' |
|
||||
'0' ... '9' |
|
||||
'0'...'9' |
|
||||
'\u{B7}' |
|
||||
'\u{300}' ... '\u{36F}' |
|
||||
'\u{203F}' ... '\u{2040}' => true,
|
||||
'\u{300}'...'\u{36F}' |
|
||||
'\u{203F}'...'\u{2040}' => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -149,7 +150,7 @@ pub fn xml_name_type(name: &str) -> XMLName {
|
||||
if c == ':' {
|
||||
match seen_colon {
|
||||
true => non_qname_colons = true,
|
||||
false => seen_colon = true
|
||||
false => seen_colon = true,
|
||||
}
|
||||
}
|
||||
last = c
|
||||
@ -161,7 +162,7 @@ pub fn xml_name_type(name: &str) -> XMLName {
|
||||
|
||||
match non_qname_colons {
|
||||
false => XMLName::QName,
|
||||
true => XMLName::Name
|
||||
true => XMLName::Name,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use num::ToPrimitive;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::{Cell};
|
||||
use std::cell::Cell;
|
||||
use std::cmp::{max, min};
|
||||
use std::sync::mpsc::Sender;
|
||||
use util::str::DOMString;
|
||||
@ -23,29 +23,27 @@ pub struct Blob {
|
||||
bytes: Option<Vec<u8>>,
|
||||
typeString: String,
|
||||
global: GlobalField,
|
||||
isClosed_: Cell<bool>
|
||||
isClosed_: Cell<bool>,
|
||||
}
|
||||
|
||||
fn is_ascii_printable(string: &str) -> bool {
|
||||
// Step 5.1 in Sec 5.1 of File API spec
|
||||
// http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
|
||||
string.chars().all(|c| { c >= '\x20' && c <= '\x7E' })
|
||||
string.chars().all(|c| c >= '\x20' && c <= '\x7E')
|
||||
}
|
||||
|
||||
impl Blob {
|
||||
pub fn new_inherited(global: GlobalRef,
|
||||
bytes: Option<Vec<u8>>, typeString: &str) -> Blob {
|
||||
pub fn new_inherited(global: GlobalRef, bytes: Option<Vec<u8>>, typeString: &str) -> Blob {
|
||||
Blob {
|
||||
reflector_: Reflector::new(),
|
||||
bytes: bytes,
|
||||
typeString: typeString.to_owned(),
|
||||
global: GlobalField::from_rooted(&global),
|
||||
isClosed_: Cell::new(false)
|
||||
isClosed_: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef, bytes: Option<Vec<u8>>,
|
||||
typeString: &str) -> Root<Blob> {
|
||||
pub fn new(global: GlobalRef, bytes: Option<Vec<u8>>, typeString: &str) -> Root<Blob> {
|
||||
reflect_dom_object(box Blob::new_inherited(global, bytes, typeString),
|
||||
global,
|
||||
BlobBinding::Wrap)
|
||||
@ -57,9 +55,11 @@ impl Blob {
|
||||
}
|
||||
|
||||
// http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
|
||||
pub fn Constructor_(global: GlobalRef, blobParts: DOMString,
|
||||
blobPropertyBag: &BlobBinding::BlobPropertyBag) -> Fallible<Root<Blob>> {
|
||||
//TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView or Blob
|
||||
pub fn Constructor_(global: GlobalRef,
|
||||
blobParts: DOMString,
|
||||
blobPropertyBag: &BlobBinding::BlobPropertyBag)
|
||||
-> Fallible<Root<Blob>> {
|
||||
// TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView or Blob
|
||||
// FIXME(ajeffrey): convert directly from a DOMString to a Vec<u8>
|
||||
let bytes: Option<Vec<u8>> = Some(String::from(blobParts).into_bytes());
|
||||
let typeString = if is_ascii_printable(&blobPropertyBag.type_) {
|
||||
@ -85,7 +85,7 @@ impl BlobMethods for Blob {
|
||||
fn Size(&self) -> u64 {
|
||||
match self.bytes {
|
||||
None => 0,
|
||||
Some(ref bytes) => bytes.len() as u64
|
||||
Some(ref bytes) => bytes.len() as u64,
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,8 +95,11 @@ impl BlobMethods for Blob {
|
||||
}
|
||||
|
||||
// https://dev.w3.org/2006/webapi/FileAPI/#slice-method-algo
|
||||
fn Slice(&self, start: Option<i64>, end: Option<i64>,
|
||||
contentType: Option<DOMString>) -> Root<Blob> {
|
||||
fn Slice(&self,
|
||||
start: Option<i64>,
|
||||
end: Option<i64>,
|
||||
contentType: Option<DOMString>)
|
||||
-> Root<Blob> {
|
||||
let size: i64 = self.Size().to_i64().unwrap();
|
||||
let relativeStart: i64 = match start {
|
||||
None => 0,
|
||||
|
@ -35,7 +35,7 @@ impl BrowsingContext {
|
||||
pub fn new_inherited(document: &Document, frame_element: Option<&Element>) -> BrowsingContext {
|
||||
BrowsingContext {
|
||||
reflector: Reflector::new(),
|
||||
history: vec!(SessionHistoryEntry::new(document)),
|
||||
history: vec![SessionHistoryEntry::new(document)],
|
||||
active_index: 0,
|
||||
frame_element: frame_element.map(JS::from_ref),
|
||||
}
|
||||
@ -55,7 +55,12 @@ impl BrowsingContext {
|
||||
assert!(!parent.get().is_null());
|
||||
assert!(((*JS_GetClass(parent.get())).flags & JSCLASS_IS_GLOBAL) != 0);
|
||||
let _ac = JSAutoCompartment::new(cx, parent.get());
|
||||
let window_proxy = RootedObject::new(cx, WrapperNew(cx, parent, handler, ptr::null(), true));
|
||||
let window_proxy = RootedObject::new(cx,
|
||||
WrapperNew(cx,
|
||||
parent,
|
||||
handler,
|
||||
ptr::null(),
|
||||
true));
|
||||
assert!(!window_proxy.ptr.is_null());
|
||||
|
||||
let object = box BrowsingContext::new_inherited(document, frame_element);
|
||||
@ -95,20 +100,23 @@ impl BrowsingContext {
|
||||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
pub struct SessionHistoryEntry {
|
||||
document: JS<Document>,
|
||||
children: Vec<JS<BrowsingContext>>
|
||||
children: Vec<JS<BrowsingContext>>,
|
||||
}
|
||||
|
||||
impl SessionHistoryEntry {
|
||||
fn new(document: &Document) -> SessionHistoryEntry {
|
||||
SessionHistoryEntry {
|
||||
document: JS::from_ref(document),
|
||||
children: vec!()
|
||||
children: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn GetSubframeWindow(cx: *mut JSContext, proxy: HandleObject, id: HandleId) -> Option<Root<Window>> {
|
||||
unsafe fn GetSubframeWindow(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId)
|
||||
-> Option<Root<Window>> {
|
||||
let index = get_array_index_from_id(cx, id);
|
||||
if let Some(index) = index {
|
||||
let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
|
||||
@ -121,8 +129,11 @@ unsafe fn GetSubframeWindow(cx: *mut JSContext, proxy: HandleObject, id: HandleI
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern fn getOwnPropertyDescriptor(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
|
||||
desc: MutableHandle<JSPropertyDescriptor>) -> bool {
|
||||
unsafe extern "C" fn getOwnPropertyDescriptor(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
desc: MutableHandle<JSPropertyDescriptor>)
|
||||
-> bool {
|
||||
let window = GetSubframeWindow(cx, proxy, id);
|
||||
if let Some(window) = window {
|
||||
let mut val = RootedValue::new(cx, UndefinedValue());
|
||||
@ -149,18 +160,19 @@ unsafe extern fn getOwnPropertyDescriptor(cx: *mut JSContext, proxy: HandleObjec
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern fn defineProperty(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
desc: Handle<JSPropertyDescriptor>,
|
||||
res: *mut ObjectOpResult) -> bool {
|
||||
unsafe extern "C" fn defineProperty(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
desc: Handle<JSPropertyDescriptor>,
|
||||
res: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
if get_array_index_from_id(cx, id).is_some() {
|
||||
// Spec says to Reject whether this is a supported index or not,
|
||||
// since we have no indexed setter or indexed creator. That means
|
||||
// throwing in strict mode (FIXME: Bug 828137), doing nothing in
|
||||
// non-strict mode.
|
||||
(*res).code_ = JSErrNum::JSMSG_CANT_DEFINE_WINDOW_ELEMENT as ::libc::uintptr_t;
|
||||
return true;
|
||||
(*res).code_ = JSErrNum::JSMSG_CANT_DEFINE_WINDOW_ELEMENT as ::libc::uintptr_t;
|
||||
return true;
|
||||
}
|
||||
|
||||
let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
|
||||
@ -168,7 +180,11 @@ unsafe extern fn defineProperty(cx: *mut JSContext,
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern fn hasOwn(cx: *mut JSContext, proxy: HandleObject, id: HandleId, bp: *mut bool) -> bool {
|
||||
unsafe extern "C" fn hasOwn(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
bp: *mut bool)
|
||||
-> bool {
|
||||
let window = GetSubframeWindow(cx, proxy, id);
|
||||
if window.is_some() {
|
||||
*bp = true;
|
||||
@ -186,11 +202,12 @@ unsafe extern fn hasOwn(cx: *mut JSContext, proxy: HandleObject, id: HandleId, b
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern fn get(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
receiver: HandleObject,
|
||||
id: HandleId,
|
||||
vp: MutableHandleValue) -> bool {
|
||||
unsafe extern "C" fn get(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
receiver: HandleObject,
|
||||
id: HandleId,
|
||||
vp: MutableHandleValue)
|
||||
-> bool {
|
||||
let window = GetSubframeWindow(cx, proxy, id);
|
||||
if let Some(window) = window {
|
||||
window.to_jsval(cx, vp);
|
||||
@ -202,12 +219,13 @@ unsafe extern fn get(cx: *mut JSContext,
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern fn set(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
receiver: HandleObject,
|
||||
id: HandleId,
|
||||
vp: MutableHandleValue,
|
||||
res: *mut ObjectOpResult) -> bool {
|
||||
unsafe extern "C" fn set(cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
receiver: HandleObject,
|
||||
id: HandleId,
|
||||
vp: MutableHandleValue,
|
||||
res: *mut ObjectOpResult)
|
||||
-> bool {
|
||||
if get_array_index_from_id(cx, id).is_some() {
|
||||
// Reject (which means throw if and only if strict) the set.
|
||||
(*res).code_ = JSErrNum::JSMSG_READ_ONLY as ::libc::uintptr_t;
|
||||
@ -216,7 +234,12 @@ unsafe extern fn set(cx: *mut JSContext,
|
||||
|
||||
let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
|
||||
let receiver = RootedValue::new(cx, ObjectValue(&**receiver.ptr));
|
||||
JS_ForwardSetPropertyTo(cx, target.handle(), id, vp.to_handle(), receiver.handle(), res)
|
||||
JS_ForwardSetPropertyTo(cx,
|
||||
target.handle(),
|
||||
id,
|
||||
vp.to_handle(),
|
||||
receiver.handle(),
|
||||
res)
|
||||
}
|
||||
|
||||
static PROXY_HANDLER: ProxyTraps = ProxyTraps {
|
||||
|
@ -39,7 +39,8 @@ impl CanvasGradient {
|
||||
|
||||
pub fn new(global: GlobalRef, style: CanvasGradientStyle) -> Root<CanvasGradient> {
|
||||
reflect_dom_object(box CanvasGradient::new_inherited(style),
|
||||
global, CanvasGradientBinding::Wrap)
|
||||
global,
|
||||
CanvasGradientBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +53,7 @@ impl CanvasGradientMethods for CanvasGradient {
|
||||
|
||||
let color = match parse_color(&color) {
|
||||
Ok(color) => color,
|
||||
_ => return Err(Error::Syntax)
|
||||
_ => return Err(Error::Syntax),
|
||||
};
|
||||
|
||||
self.stops.borrow_mut().push(CanvasGradientStop {
|
||||
@ -71,17 +72,21 @@ impl<'a> ToFillOrStrokeStyle for &'a CanvasGradient {
|
||||
fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
|
||||
let gradient_stops = self.stops.borrow().clone();
|
||||
match self.style {
|
||||
CanvasGradientStyle::Linear(ref gradient) => {
|
||||
FillOrStrokeStyle::LinearGradient(
|
||||
LinearGradientStyle::new(gradient.x0, gradient.y0,
|
||||
gradient.x1, gradient.y1,
|
||||
gradient_stops))
|
||||
},
|
||||
CanvasGradientStyle::Linear(ref gradient) => {
|
||||
FillOrStrokeStyle::LinearGradient(LinearGradientStyle::new(gradient.x0,
|
||||
gradient.y0,
|
||||
gradient.x1,
|
||||
gradient.y1,
|
||||
gradient_stops))
|
||||
}
|
||||
CanvasGradientStyle::Radial(ref gradient) => {
|
||||
FillOrStrokeStyle::RadialGradient(
|
||||
RadialGradientStyle::new(gradient.x0, gradient.y0, gradient.r0,
|
||||
gradient.x1, gradient.y1, gradient.r1,
|
||||
gradient_stops))
|
||||
FillOrStrokeStyle::RadialGradient(RadialGradientStyle::new(gradient.x0,
|
||||
gradient.y0,
|
||||
gradient.r0,
|
||||
gradient.x1,
|
||||
gradient.y1,
|
||||
gradient.r1,
|
||||
gradient_stops))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,10 @@ pub struct CanvasPattern {
|
||||
}
|
||||
|
||||
impl CanvasPattern {
|
||||
fn new_inherited(surface_data: Vec<u8>, surface_size: Size2D<i32>, repeat: RepetitionStyle) -> CanvasPattern {
|
||||
fn new_inherited(surface_data: Vec<u8>,
|
||||
surface_size: Size2D<i32>,
|
||||
repeat: RepetitionStyle)
|
||||
-> CanvasPattern {
|
||||
let (x, y) = match repeat {
|
||||
RepetitionStyle::Repeat => (true, true),
|
||||
RepetitionStyle::RepeatX => (true, false),
|
||||
@ -43,13 +46,16 @@ impl CanvasPattern {
|
||||
repeat: RepetitionStyle)
|
||||
-> Root<CanvasPattern> {
|
||||
reflect_dom_object(box CanvasPattern::new_inherited(surface_data, surface_size, repeat),
|
||||
global, CanvasPatternBinding::Wrap)
|
||||
global,
|
||||
CanvasPatternBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToFillOrStrokeStyle for &'a CanvasPattern {
|
||||
fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
|
||||
FillOrStrokeStyle::Surface(
|
||||
SurfaceStyle::new(self.surface_data.clone(), self.surface_size, self.repeat_x, self.repeat_y))
|
||||
FillOrStrokeStyle::Surface(SurfaceStyle::new(self.surface_data.clone(),
|
||||
self.surface_size,
|
||||
self.repeat_x,
|
||||
self.repeat_y))
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,9 @@ impl CanvasContextState {
|
||||
}
|
||||
|
||||
impl CanvasRenderingContext2D {
|
||||
fn new_inherited(global: GlobalRef, canvas: &HTMLCanvasElement, size: Size2D<i32>)
|
||||
fn new_inherited(global: GlobalRef,
|
||||
canvas: &HTMLCanvasElement,
|
||||
size: Size2D<i32>)
|
||||
-> CanvasRenderingContext2D {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
let constellation_chan = global.constellation_chan();
|
||||
@ -130,10 +132,13 @@ impl CanvasRenderingContext2D {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef, canvas: &HTMLCanvasElement, size: Size2D<i32>)
|
||||
pub fn new(global: GlobalRef,
|
||||
canvas: &HTMLCanvasElement,
|
||||
size: Size2D<i32>)
|
||||
-> Root<CanvasRenderingContext2D> {
|
||||
reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, canvas, size),
|
||||
global, CanvasRenderingContext2DBinding::Wrap)
|
||||
global,
|
||||
CanvasRenderingContext2DBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn recreate(&self, size: Size2D<i32>) {
|
||||
@ -161,9 +166,16 @@ impl CanvasRenderingContext2D {
|
||||
// source rectangle = area of the original image to be copied
|
||||
// destination rectangle = area of the destination canvas where the source image is going to be drawn
|
||||
fn adjust_source_dest_rects(&self,
|
||||
image_size: Size2D<f64>,
|
||||
sx: f64, sy: f64, sw: f64, sh: f64,
|
||||
dx: f64, dy: f64, dw: f64, dh: f64) -> (Rect<f64>, Rect<f64>) {
|
||||
image_size: Size2D<f64>,
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
sw: f64,
|
||||
sh: f64,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: f64,
|
||||
dh: f64)
|
||||
-> (Rect<f64>, Rect<f64>) {
|
||||
let image_rect = Rect::new(Point2D::new(0f64, 0f64),
|
||||
Size2D::new(image_size.width as f64, image_size.height as f64));
|
||||
|
||||
@ -221,9 +233,17 @@ impl CanvasRenderingContext2D {
|
||||
// is copied on the rectangle (dx, dy, dh, dw) of the destination canvas
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
fn draw_image(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
sx: f64, sy: f64, sw: Option<f64>, sh: Option<f64>,
|
||||
dx: f64, dy: f64, dw: Option<f64>, dh: Option<f64>) -> Fallible<()> {
|
||||
fn draw_image(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
sw: Option<f64>,
|
||||
sh: Option<f64>,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: Option<f64>,
|
||||
dh: Option<f64>)
|
||||
-> Fallible<()> {
|
||||
match image {
|
||||
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(canvas) =>
|
||||
self.draw_html_canvas_element(canvas.r(),
|
||||
@ -264,12 +284,19 @@ impl CanvasRenderingContext2D {
|
||||
}
|
||||
|
||||
fn draw_html_canvas_element(&self,
|
||||
canvas: &HTMLCanvasElement,
|
||||
sx: f64, sy: f64, sw: Option<f64>, sh: Option<f64>,
|
||||
dx: f64, dy: f64, dw: Option<f64>, dh: Option<f64>) -> Fallible<()> {
|
||||
canvas: &HTMLCanvasElement,
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
sw: Option<f64>,
|
||||
sh: Option<f64>,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: Option<f64>,
|
||||
dh: Option<f64>)
|
||||
-> Fallible<()> {
|
||||
// 1. Check the usability of the image argument
|
||||
if !canvas.is_valid() {
|
||||
return Err(Error::InvalidState)
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
|
||||
let canvas_size = canvas.get_size();
|
||||
@ -280,18 +307,30 @@ impl CanvasRenderingContext2D {
|
||||
|
||||
let image_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
|
||||
// 2. Establish the source and destination rectangles
|
||||
let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size, sx, sy, sw, sh, dx, dy, dw, dh);
|
||||
let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size,
|
||||
sx,
|
||||
sy,
|
||||
sw,
|
||||
sh,
|
||||
dx,
|
||||
dy,
|
||||
dw,
|
||||
dh);
|
||||
|
||||
if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) {
|
||||
return Err(Error::IndexSize)
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
||||
|
||||
// If the source and target canvas are the same
|
||||
let msg = if &*self.canvas == canvas {
|
||||
CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled))
|
||||
} else { // Source and target canvases are different
|
||||
CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf(image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled))
|
||||
} else {
|
||||
// Source and target canvases are different
|
||||
let context = match canvas.get_or_init_2d_context() {
|
||||
Some(context) => context,
|
||||
None => return Err(Error::InvalidState),
|
||||
@ -302,11 +341,15 @@ impl CanvasRenderingContext2D {
|
||||
// Reads pixels from source image
|
||||
renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(source_rect.to_i32(),
|
||||
image_size,
|
||||
sender))).unwrap();
|
||||
sender)))
|
||||
.unwrap();
|
||||
let imagedata = receiver.recv().unwrap();
|
||||
// Writes pixels to destination canvas
|
||||
CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::DrawImage(imagedata, source_rect.size, dest_rect, source_rect, smoothing_enabled))
|
||||
CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage(imagedata,
|
||||
source_rect.size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled))
|
||||
};
|
||||
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
@ -317,13 +360,28 @@ impl CanvasRenderingContext2D {
|
||||
fn draw_image_data(&self,
|
||||
image_data: Vec<u8>,
|
||||
image_size: Size2D<f64>,
|
||||
sx: f64, sy: f64, sw: f64, sh: f64,
|
||||
dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> {
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
sw: f64,
|
||||
sh: f64,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: f64,
|
||||
dh: f64)
|
||||
-> Fallible<()> {
|
||||
// Establish the source and destination rectangles
|
||||
let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size, sx, sy, sw, sh, dx, dy, dw, dh);
|
||||
let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size,
|
||||
sx,
|
||||
sy,
|
||||
sw,
|
||||
sh,
|
||||
dx,
|
||||
dy,
|
||||
dw,
|
||||
dh);
|
||||
|
||||
if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) {
|
||||
return Err(Error::IndexSize)
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
||||
@ -338,9 +396,7 @@ impl CanvasRenderingContext2D {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fetch_image_data(&self,
|
||||
image_element: &HTMLImageElement)
|
||||
-> Option<(Vec<u8>, Size2D<i32>)> {
|
||||
fn fetch_image_data(&self, image_element: &HTMLImageElement) -> Option<(Vec<u8>, Size2D<i32>)> {
|
||||
let url = match image_element.get_url() {
|
||||
Some(url) => url,
|
||||
None => return None,
|
||||
@ -349,7 +405,7 @@ impl CanvasRenderingContext2D {
|
||||
let img = match self.request_image_from_cache(url) {
|
||||
ImageResponse::Loaded(img) => img,
|
||||
ImageResponse::PlaceholderLoaded(_) | ImageResponse::None => {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
@ -379,7 +435,8 @@ impl CanvasRenderingContext2D {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Rect::new(Point2D::new(x as f32, y as f32), Size2D::new(w as f32, h as f32)))
|
||||
Some(Rect::new(Point2D::new(x as f32, y as f32),
|
||||
Size2D::new(w as f32, h as f32)))
|
||||
}
|
||||
|
||||
pub fn get_renderer_id(&self) -> usize {
|
||||
@ -609,8 +666,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
fn DrawImage(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
dx: f64, dy: f64) -> Fallible<()> {
|
||||
fn DrawImage(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
dx: f64,
|
||||
dy: f64)
|
||||
-> Fallible<()> {
|
||||
if !(dx.is_finite() && dy.is_finite()) {
|
||||
return Ok(());
|
||||
}
|
||||
@ -619,10 +679,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
fn DrawImage_(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> {
|
||||
if !(dx.is_finite() && dy.is_finite() &&
|
||||
dw.is_finite() && dh.is_finite()) {
|
||||
fn DrawImage_(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: f64,
|
||||
dh: f64)
|
||||
-> Fallible<()> {
|
||||
if !(dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -630,15 +694,31 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
fn DrawImage__(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
sx: f64, sy: f64, sw: f64, sh: f64,
|
||||
dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> {
|
||||
fn DrawImage__(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
sw: f64,
|
||||
sh: f64,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: f64,
|
||||
dh: f64)
|
||||
-> Fallible<()> {
|
||||
if !(sx.is_finite() && sy.is_finite() && sw.is_finite() && sh.is_finite() &&
|
||||
dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.draw_image(image, sx, sy, Some(sw), Some(sh), dx, dy, Some(dw), Some(dh))
|
||||
self.draw_image(image,
|
||||
sx,
|
||||
sy,
|
||||
Some(sw),
|
||||
Some(sh),
|
||||
dx,
|
||||
dy,
|
||||
Some(dw),
|
||||
Some(dh))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto
|
||||
@ -647,9 +727,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
return;
|
||||
}
|
||||
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::MoveTo(
|
||||
Point2D::new(x as f32, y as f32)));
|
||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32)));
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
}
|
||||
|
||||
@ -659,9 +737,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
return;
|
||||
}
|
||||
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::LineTo(
|
||||
Point2D::new(x as f32, y as f32)));
|
||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32)));
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
}
|
||||
|
||||
@ -677,15 +753,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto
|
||||
fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
|
||||
if !(cpx.is_finite() && cpy.is_finite() &&
|
||||
x.is_finite() && y.is_finite()) {
|
||||
if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::QuadraticCurveTo(
|
||||
Point2D::new(cpx as f32, cpy as f32),
|
||||
Point2D::new(x as f32, y as f32)));
|
||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32,
|
||||
cpy as f32),
|
||||
Point2D::new(x as f32,
|
||||
y as f32)));
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
}
|
||||
|
||||
@ -696,17 +771,16 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
return;
|
||||
}
|
||||
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::BezierCurveTo(
|
||||
Point2D::new(cp1x as f32, cp1y as f32),
|
||||
Point2D::new(cp2x as f32, cp2y as f32),
|
||||
Point2D::new(x as f32, y as f32)));
|
||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::BezierCurveTo(Point2D::new(cp1x as f32,
|
||||
cp1y as f32),
|
||||
Point2D::new(cp2x as f32,
|
||||
cp2y as f32),
|
||||
Point2D::new(x as f32, y as f32)));
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-arc
|
||||
fn Arc(&self, x: f64, y: f64, r: f64,
|
||||
start: f64, end: f64, ccw: bool) -> Fallible<()> {
|
||||
fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> Fallible<()> {
|
||||
if !([x, y, r, start, end].iter().all(|x| x.is_finite())) {
|
||||
return Ok(());
|
||||
}
|
||||
@ -715,10 +789,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::Arc(
|
||||
Point2D::new(x as f32, y as f32), r as f32,
|
||||
start as f32, end as f32, ccw));
|
||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32),
|
||||
r as f32,
|
||||
start as f32,
|
||||
end as f32,
|
||||
ccw));
|
||||
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
Ok(())
|
||||
@ -733,11 +808,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::ArcTo(
|
||||
Point2D::new(cp1x as f32, cp1y as f32),
|
||||
Point2D::new(cp2x as f32, cp2y as f32),
|
||||
r as f32));
|
||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32),
|
||||
Point2D::new(cp2x as f32, cp2y as f32),
|
||||
r as f32));
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
@ -783,8 +856,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
}
|
||||
},
|
||||
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient) => {
|
||||
self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Gradient(
|
||||
JS::from_ref(gradient.r()));
|
||||
self.state.borrow_mut().stroke_style =
|
||||
CanvasFillOrStrokeStyle::Gradient(JS::from_ref(gradient.r()));
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style()));
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
@ -820,8 +893,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
}
|
||||
}
|
||||
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient) => {
|
||||
self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Gradient(
|
||||
JS::from_rooted(&gradient));
|
||||
self.state.borrow_mut().fill_style =
|
||||
CanvasFillOrStrokeStyle::Gradient(JS::from_rooted(&gradient));
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style()));
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
@ -836,7 +909,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
|
||||
fn CreateImageData(&self, sw: Finite<f64>, sh: Finite<f64>) -> Fallible<Root<ImageData>> {
|
||||
if *sw == 0.0 || *sh == 0.0 {
|
||||
return Err(Error::IndexSize)
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
let sw = cmp::max(1, sw.abs().to_u32().unwrap());
|
||||
@ -846,7 +919,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
|
||||
fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible<Root<ImageData>> {
|
||||
Ok(ImageData::new(self.global.root().r(), imagedata.Width(), imagedata.Height(), None))
|
||||
Ok(ImageData::new(self.global.root().r(),
|
||||
imagedata.Width(),
|
||||
imagedata.Height(),
|
||||
None))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata
|
||||
@ -854,14 +930,15 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
sx: Finite<f64>,
|
||||
sy: Finite<f64>,
|
||||
sw: Finite<f64>,
|
||||
sh: Finite<f64>) -> Fallible<Root<ImageData>> {
|
||||
sh: Finite<f64>)
|
||||
-> Fallible<Root<ImageData>> {
|
||||
let mut sx = *sx;
|
||||
let mut sy = *sy;
|
||||
let mut sw = *sw;
|
||||
let mut sh = *sh;
|
||||
|
||||
if sw == 0.0 || sh == 0.0 {
|
||||
return Err(Error::IndexSize)
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
if sw < 0.0 {
|
||||
@ -899,48 +976,81 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
|
||||
fn PutImageData(&self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>) {
|
||||
self.PutImageData_(imagedata, dx, dy, Finite::wrap(0f64), Finite::wrap(0f64),
|
||||
Finite::wrap(imagedata.Width() as f64), Finite::wrap(imagedata.Height() as f64))
|
||||
self.PutImageData_(imagedata,
|
||||
dx,
|
||||
dy,
|
||||
Finite::wrap(0f64),
|
||||
Finite::wrap(0f64),
|
||||
Finite::wrap(imagedata.Width() as f64),
|
||||
Finite::wrap(imagedata.Height() as f64))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
|
||||
fn PutImageData_(&self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>,
|
||||
dirtyX: Finite<f64>, dirtyY: Finite<f64>, dirtyWidth: Finite<f64>, dirtyHeight: Finite<f64>) {
|
||||
fn PutImageData_(&self,
|
||||
imagedata: &ImageData,
|
||||
dx: Finite<f64>,
|
||||
dy: Finite<f64>,
|
||||
dirtyX: Finite<f64>,
|
||||
dirtyY: Finite<f64>,
|
||||
dirtyWidth: Finite<f64>,
|
||||
dirtyHeight: Finite<f64>) {
|
||||
let data = imagedata.get_data_array(&self.global.root().r());
|
||||
let offset = Point2D::new(*dx, *dy);
|
||||
let image_data_size = Size2D::new(imagedata.Width() as f64,
|
||||
imagedata.Height() as f64);
|
||||
let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64);
|
||||
|
||||
let dirty_rect = Rect::new(Point2D::new(*dirtyX, *dirtyY),
|
||||
Size2D::new(*dirtyWidth, *dirtyHeight));
|
||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(data, offset, image_data_size, dirty_rect));
|
||||
let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(data,
|
||||
offset,
|
||||
image_data_size,
|
||||
dirty_rect));
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
self.mark_as_dirty();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient
|
||||
fn CreateLinearGradient(&self, x0: Finite<f64>, y0: Finite<f64>,
|
||||
x1: Finite<f64>, y1: Finite<f64>) -> Root<CanvasGradient> {
|
||||
fn CreateLinearGradient(&self,
|
||||
x0: Finite<f64>,
|
||||
y0: Finite<f64>,
|
||||
x1: Finite<f64>,
|
||||
y1: Finite<f64>)
|
||||
-> Root<CanvasGradient> {
|
||||
CanvasGradient::new(self.global.root().r(),
|
||||
CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new())))
|
||||
CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0,
|
||||
*y0,
|
||||
*x1,
|
||||
*y1,
|
||||
Vec::new())))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient
|
||||
fn CreateRadialGradient(&self, x0: Finite<f64>, y0: Finite<f64>, r0: Finite<f64>,
|
||||
x1: Finite<f64>, y1: Finite<f64>, r1: Finite<f64>)
|
||||
fn CreateRadialGradient(&self,
|
||||
x0: Finite<f64>,
|
||||
y0: Finite<f64>,
|
||||
r0: Finite<f64>,
|
||||
x1: Finite<f64>,
|
||||
y1: Finite<f64>,
|
||||
r1: Finite<f64>)
|
||||
-> Fallible<Root<CanvasGradient>> {
|
||||
if *r0 < 0. || *r1 < 0. {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
Ok(CanvasGradient::new(self.global.root().r(),
|
||||
CanvasGradientStyle::Radial(
|
||||
RadialGradientStyle::new(*x0, *y0, *r0, *x1, *y1, *r1, Vec::new()))))
|
||||
CanvasGradientStyle::Radial(RadialGradientStyle::new(*x0,
|
||||
*y0,
|
||||
*r0,
|
||||
*x1,
|
||||
*y1,
|
||||
*r1,
|
||||
Vec::new()))))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
|
||||
fn CreatePattern(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
repetition: DOMString) -> Fallible<Root<CanvasPattern>> {
|
||||
fn CreatePattern(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
repetition: DOMString)
|
||||
-> Fallible<Root<CanvasPattern>> {
|
||||
let (image_data, image_size) = match image {
|
||||
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
|
||||
// https://html.spec.whatwg.org/multipage/#img-error
|
||||
@ -967,14 +1077,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||
Some((data, size)) => (data, size),
|
||||
None => return Err(Error::InvalidState),
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(rep) = RepetitionStyle::from_str(&repetition) {
|
||||
return Ok(CanvasPattern::new(self.global.root().r(),
|
||||
image_data,
|
||||
image_size,
|
||||
rep));
|
||||
return Ok(CanvasPattern::new(self.global.root().r(), image_data, image_size, rep));
|
||||
}
|
||||
return Err(Error::Syntax);
|
||||
}
|
||||
@ -1121,8 +1228,11 @@ pub fn parse_color(string: &str) -> Result<RGBA, ()> {
|
||||
let mut parser = Parser::new(&string);
|
||||
match CSSColor::parse(&mut parser) {
|
||||
Ok(CSSColor::RGBA(rgba)) => {
|
||||
if parser.is_exhausted() { Ok(rgba) }
|
||||
else { Err(()) }
|
||||
if parser.is_exhausted() {
|
||||
Ok(rgba)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
@ -1135,18 +1245,23 @@ fn is_rect_valid(rect: Rect<f64>) -> bool {
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#serialisation-of-a-colour
|
||||
fn serialize<W>(color: &RGBA, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
fn serialize<W>(color: &RGBA, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write
|
||||
{
|
||||
let red = (color.red * 255.).round() as u8;
|
||||
let green = (color.green * 255.).round() as u8;
|
||||
let blue = (color.blue * 255.).round() as u8;
|
||||
|
||||
if color.alpha == 1f32 {
|
||||
write!(dest, "#{:x}{:x}{:x}{:x}{:x}{:x}",
|
||||
red >> 4, red & 0xF,
|
||||
green >> 4, green & 0xF,
|
||||
blue >> 4, blue & 0xF)
|
||||
write!(dest,
|
||||
"#{:x}{:x}{:x}{:x}{:x}{:x}",
|
||||
red >> 4,
|
||||
red & 0xF,
|
||||
green >> 4,
|
||||
green & 0xF,
|
||||
blue >> 4,
|
||||
blue & 0xF)
|
||||
} else {
|
||||
write!(dest, "rgba({}, {}, {}, {})",
|
||||
red, green, blue, color.alpha)
|
||||
write!(dest, "rgba({}, {}, {}, {})", red, green, blue, color.alpha)
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ impl CharacterDataMethods for CharacterData {
|
||||
let data_from_offset = match find_utf16_code_unit_offset(&data, offset) {
|
||||
Some(offset_bytes) => &data[offset_bytes..],
|
||||
// Step 2.
|
||||
None => return Err(Error::IndexSize)
|
||||
None => return Err(Error::IndexSize),
|
||||
};
|
||||
let substring = match find_utf16_code_unit_offset(data_from_offset, count) {
|
||||
// Steps 3.
|
||||
@ -90,7 +90,7 @@ impl CharacterDataMethods for CharacterData {
|
||||
let (prefix, data_from_offset) = match find_utf16_code_unit_offset(&data, offset) {
|
||||
Some(offset_bytes) => data.split_at(offset_bytes),
|
||||
// Step 2.
|
||||
None => return Err(Error::IndexSize)
|
||||
None => return Err(Error::IndexSize),
|
||||
};
|
||||
let suffix = match find_utf16_code_unit_offset(data_from_offset, count) {
|
||||
// Steps 3.
|
||||
@ -182,7 +182,7 @@ fn find_utf16_code_unit_offset(s: &str, offset: u32) -> Option<usize> {
|
||||
let mut code_units = 0;
|
||||
for (i, c) in s.char_indices() {
|
||||
if code_units == offset {
|
||||
return Some(i)
|
||||
return Some(i);
|
||||
}
|
||||
code_units += 1;
|
||||
if c > '\u{FFFF}' {
|
||||
|
@ -23,8 +23,7 @@ pub struct CloseEvent {
|
||||
}
|
||||
|
||||
impl CloseEvent {
|
||||
pub fn new_inherited(wasClean: bool, code: u16,
|
||||
reason: DOMString) -> CloseEvent {
|
||||
pub fn new_inherited(wasClean: bool, code: u16, reason: DOMString) -> CloseEvent {
|
||||
CloseEvent {
|
||||
event: Event::new_inherited(),
|
||||
wasClean: wasClean,
|
||||
@ -39,7 +38,8 @@ impl CloseEvent {
|
||||
cancelable: EventCancelable,
|
||||
wasClean: bool,
|
||||
code: u16,
|
||||
reason: DOMString) -> Root<CloseEvent> {
|
||||
reason: DOMString)
|
||||
-> Root<CloseEvent> {
|
||||
let event = box CloseEvent::new_inherited(wasClean, code, reason);
|
||||
let ev = reflect_dom_object(event, global, CloseEventBinding::Wrap);
|
||||
{
|
||||
@ -55,14 +55,23 @@ impl CloseEvent {
|
||||
type_: DOMString,
|
||||
init: &CloseEventBinding::CloseEventInit)
|
||||
-> Fallible<Root<CloseEvent>> {
|
||||
let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble };
|
||||
let bubbles = if init.parent.bubbles {
|
||||
EventBubbles::Bubbles
|
||||
} else {
|
||||
EventBubbles::DoesNotBubble
|
||||
};
|
||||
let cancelable = if init.parent.cancelable {
|
||||
EventCancelable::Cancelable
|
||||
} else {
|
||||
EventCancelable::NotCancelable
|
||||
};
|
||||
Ok(CloseEvent::new(global, type_, bubbles, cancelable, init.wasClean,
|
||||
init.code, init.reason.clone()))
|
||||
Ok(CloseEvent::new(global,
|
||||
type_,
|
||||
bubbles,
|
||||
cancelable,
|
||||
init.wasClean,
|
||||
init.code,
|
||||
init.reason.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,14 @@ pub struct Comment {
|
||||
impl Comment {
|
||||
fn new_inherited(text: DOMString, document: &Document) -> Comment {
|
||||
Comment {
|
||||
characterdata: CharacterData::new_inherited(text, document)
|
||||
characterdata: CharacterData::new_inherited(text, document),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(text: DOMString, document: &Document) -> Root<Comment> {
|
||||
Node::reflect_node(box Comment::new_inherited(text, document),
|
||||
document, CommentBinding::Wrap)
|
||||
document,
|
||||
CommentBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(global: GlobalRef, data: DOMString) -> Fallible<Root<Comment>> {
|
||||
|
@ -26,7 +26,9 @@ impl Console {
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef) -> Root<Console> {
|
||||
reflect_dom_object(box Console::new_inherited(global), global, ConsoleBinding::Wrap)
|
||||
reflect_dom_object(box Console::new_inherited(global),
|
||||
global,
|
||||
ConsoleBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,13 +84,13 @@ impl ConsoleMethods for Console {
|
||||
}
|
||||
|
||||
fn prepare_message(logLevel: LogLevel, message: DOMString) -> ConsoleMessage {
|
||||
//TODO: Sending fake values for filename, lineNumber and columnNumber in LogMessage; adjust later
|
||||
// TODO: Sending fake values for filename, lineNumber and columnNumber in LogMessage; adjust later
|
||||
ConsoleMessage {
|
||||
message: String::from(message),
|
||||
logLevel: logLevel,
|
||||
filename: "test".to_owned(),
|
||||
lineNumber: 1,
|
||||
columnNumber: 1
|
||||
columnNumber: 1,
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,7 +98,9 @@ fn propagate_console_msg(console: &&Console, console_message: ConsoleMessage) {
|
||||
let global = console.global.root();
|
||||
let pipelineId = global.r().pipeline();
|
||||
global.r().devtools_chan().as_ref().map(|chan| {
|
||||
chan.send(ScriptToDevtoolsControlMsg::ConsoleAPI(
|
||||
pipelineId, console_message.clone(), global.r().get_worker_id())).unwrap();
|
||||
chan.send(ScriptToDevtoolsControlMsg::ConsoleAPI(pipelineId,
|
||||
console_message.clone(),
|
||||
global.r().get_worker_id()))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
@ -77,8 +77,10 @@ use dom::htmlvideoelement::HTMLVideoElement;
|
||||
use string_cache::{Atom, QualName};
|
||||
use util::str::DOMString;
|
||||
|
||||
pub fn create_element(name: QualName, prefix: Option<Atom>,
|
||||
document: &Document, creator: ElementCreator)
|
||||
pub fn create_element(name: QualName,
|
||||
prefix: Option<Atom>,
|
||||
document: &Document,
|
||||
creator: ElementCreator)
|
||||
-> Root<Element> {
|
||||
// FIXME(ajeffrey): Convert directly from Atom to DOMString.
|
||||
|
||||
|
@ -39,12 +39,15 @@ impl Crypto {
|
||||
impl CryptoMethods for Crypto {
|
||||
#[allow(unsafe_code)]
|
||||
// https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#Crypto-method-getRandomValues
|
||||
fn GetRandomValues(&self, _cx: *mut JSContext, input: *mut JSObject)
|
||||
fn GetRandomValues(&self,
|
||||
_cx: *mut JSContext,
|
||||
input: *mut JSObject)
|
||||
-> Fallible<*mut JSObject> {
|
||||
let mut length = 0;
|
||||
let mut data = ptr::null_mut();
|
||||
if unsafe { JS_GetObjectAsArrayBufferView(input, &mut length, &mut data).is_null() } {
|
||||
return Err(Error::Type("Argument to Crypto.getRandomValues is not an ArrayBufferView".to_owned()));
|
||||
return Err(Error::Type("Argument to Crypto.getRandomValues is not an ArrayBufferView"
|
||||
.to_owned()));
|
||||
}
|
||||
if !is_integer_buffer(input) {
|
||||
return Err(Error::TypeMismatch);
|
||||
@ -73,6 +76,6 @@ fn is_integer_buffer(input: *mut JSObject) -> bool {
|
||||
Type::Int16 |
|
||||
Type::Uint32 |
|
||||
Type::Int32 => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ pub struct CSSStyleDeclaration {
|
||||
#[derive(PartialEq, HeapSizeOf)]
|
||||
pub enum CSSModificationAccess {
|
||||
ReadWrite,
|
||||
Readonly
|
||||
Readonly,
|
||||
}
|
||||
|
||||
macro_rules! css_properties(
|
||||
@ -48,12 +48,12 @@ macro_rules! css_properties(
|
||||
);
|
||||
);
|
||||
|
||||
fn serialize_shorthand(shorthand: Shorthand, declarations: &[Ref<PropertyDeclaration>])
|
||||
-> String {
|
||||
fn serialize_shorthand(shorthand: Shorthand, declarations: &[Ref<PropertyDeclaration>]) -> String {
|
||||
// https://drafts.csswg.org/css-variables/#variables-in-shorthands
|
||||
if let Some(css) = declarations[0].with_variables_from_shorthand(shorthand) {
|
||||
if declarations[1..].iter()
|
||||
.all(|d| d.with_variables_from_shorthand(shorthand) == Some(css)) {
|
||||
if declarations[1..]
|
||||
.iter()
|
||||
.all(|d| d.with_variables_from_shorthand(shorthand) == Some(css)) {
|
||||
css.to_owned()
|
||||
} else {
|
||||
String::new()
|
||||
@ -74,7 +74,8 @@ fn serialize_shorthand(shorthand: Shorthand, declarations: &[Ref<PropertyDeclara
|
||||
impl CSSStyleDeclaration {
|
||||
pub fn new_inherited(owner: &Element,
|
||||
pseudo: Option<PseudoElement>,
|
||||
modification_access: CSSModificationAccess) -> CSSStyleDeclaration {
|
||||
modification_access: CSSModificationAccess)
|
||||
-> CSSStyleDeclaration {
|
||||
CSSStyleDeclaration {
|
||||
reflector_: Reflector::new(),
|
||||
owner: JS::from_ref(owner),
|
||||
@ -83,10 +84,14 @@ impl CSSStyleDeclaration {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: &Window, owner: &Element,
|
||||
pub fn new(global: &Window,
|
||||
owner: &Element,
|
||||
pseudo: Option<PseudoElement>,
|
||||
modification_access: CSSModificationAccess) -> Root<CSSStyleDeclaration> {
|
||||
reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner, pseudo, modification_access),
|
||||
modification_access: CSSModificationAccess)
|
||||
-> Root<CSSStyleDeclaration> {
|
||||
reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner,
|
||||
pseudo,
|
||||
modification_access),
|
||||
GlobalRef::Window(global),
|
||||
CSSStyleDeclarationBinding::Wrap)
|
||||
}
|
||||
@ -109,7 +114,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||
let elem = self.owner.upcast::<Element>();
|
||||
let len = match *elem.style_attribute().borrow() {
|
||||
Some(ref declarations) => declarations.normal.len() + declarations.important.len(),
|
||||
None => 0
|
||||
None => 0,
|
||||
};
|
||||
len as u32
|
||||
}
|
||||
@ -150,7 +155,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||
// Step 2
|
||||
if let Some(shorthand) = Shorthand::from_name(&property) {
|
||||
// Step 2.1
|
||||
let mut list = vec!();
|
||||
let mut list = vec![];
|
||||
|
||||
// Step 2.2
|
||||
for longhand in shorthand.longhands() {
|
||||
@ -203,8 +208,11 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||
}
|
||||
|
||||
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty
|
||||
fn SetProperty(&self, mut property: DOMString, value: DOMString,
|
||||
priority: DOMString) -> ErrorResult {
|
||||
fn SetProperty(&self,
|
||||
mut property: DOMString,
|
||||
value: DOMString,
|
||||
priority: DOMString)
|
||||
-> ErrorResult {
|
||||
// Step 1
|
||||
if self.readonly {
|
||||
return Err(Error::NoModificationAllowed);
|
||||
@ -281,7 +289,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||
Some(shorthand) => {
|
||||
element.set_inline_style_property_priority(shorthand.longhands(), priority)
|
||||
}
|
||||
None => element.set_inline_style_property_priority(&[&*property], priority)
|
||||
None => element.set_inline_style_property_priority(&[&*property], priority),
|
||||
}
|
||||
|
||||
let document = document_from_node(element);
|
||||
@ -318,7 +326,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||
}
|
||||
}
|
||||
// Step 5
|
||||
None => elem.remove_inline_style_property(&property)
|
||||
None => elem.remove_inline_style_property(&property),
|
||||
}
|
||||
|
||||
// Step 6
|
||||
|
@ -40,7 +40,8 @@ impl CustomEvent {
|
||||
type_: DOMString,
|
||||
bubbles: bool,
|
||||
cancelable: bool,
|
||||
detail: HandleValue) -> Root<CustomEvent> {
|
||||
detail: HandleValue)
|
||||
-> Root<CustomEvent> {
|
||||
let ev = CustomEvent::new_uninitialized(global);
|
||||
ev.InitCustomEvent(global.get_cx(), type_, bubbles, cancelable, detail);
|
||||
ev
|
||||
@ -48,7 +49,8 @@ impl CustomEvent {
|
||||
#[allow(unsafe_code)]
|
||||
pub fn Constructor(global: GlobalRef,
|
||||
type_: DOMString,
|
||||
init: &CustomEventBinding::CustomEventInit) -> Fallible<Root<CustomEvent>>{
|
||||
init: &CustomEventBinding::CustomEventInit)
|
||||
-> Fallible<Root<CustomEvent>> {
|
||||
Ok(CustomEvent::new(global,
|
||||
type_,
|
||||
init.parent.bubbles,
|
||||
|
@ -113,7 +113,9 @@ struct AutoWorkerReset<'a> {
|
||||
}
|
||||
|
||||
impl<'a> AutoWorkerReset<'a> {
|
||||
fn new(workerscope: &'a DedicatedWorkerGlobalScope, worker: TrustedWorkerAddress) -> AutoWorkerReset<'a> {
|
||||
fn new(workerscope: &'a DedicatedWorkerGlobalScope,
|
||||
worker: TrustedWorkerAddress)
|
||||
-> AutoWorkerReset<'a> {
|
||||
AutoWorkerReset {
|
||||
workerscope: workerscope,
|
||||
old_worker: replace(&mut *workerscope.worker.borrow_mut(), Some(worker)),
|
||||
@ -165,8 +167,11 @@ impl DedicatedWorkerGlobalScope {
|
||||
-> DedicatedWorkerGlobalScope {
|
||||
|
||||
DedicatedWorkerGlobalScope {
|
||||
workerglobalscope: WorkerGlobalScope::new_inherited(
|
||||
init, worker_url, runtime, from_devtools_receiver, timer_event_chan),
|
||||
workerglobalscope: WorkerGlobalScope::new_inherited(init,
|
||||
worker_url,
|
||||
runtime,
|
||||
from_devtools_receiver,
|
||||
timer_event_chan),
|
||||
id: id,
|
||||
receiver: receiver,
|
||||
own_sender: own_sender,
|
||||
@ -187,9 +192,16 @@ impl DedicatedWorkerGlobalScope {
|
||||
timer_event_chan: IpcSender<TimerEvent>,
|
||||
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
|
||||
-> Root<DedicatedWorkerGlobalScope> {
|
||||
let scope = box DedicatedWorkerGlobalScope::new_inherited(
|
||||
init, worker_url, id, from_devtools_receiver, runtime.clone(), parent_sender,
|
||||
own_sender, receiver, timer_event_chan, timer_event_port);
|
||||
let scope = box DedicatedWorkerGlobalScope::new_inherited(init,
|
||||
worker_url,
|
||||
id,
|
||||
from_devtools_receiver,
|
||||
runtime.clone(),
|
||||
parent_sender,
|
||||
own_sender,
|
||||
receiver,
|
||||
timer_event_chan,
|
||||
timer_event_port);
|
||||
DedicatedWorkerGlobalScopeBinding::Wrap(runtime.cx(), scope)
|
||||
}
|
||||
|
||||
@ -315,7 +327,8 @@ impl DedicatedWorkerGlobalScope {
|
||||
let scope = self.upcast::<WorkerGlobalScope>();
|
||||
let target = self.upcast();
|
||||
let _ar = JSAutoRequest::new(scope.get_cx());
|
||||
let _ac = JSAutoCompartment::new(scope.get_cx(), scope.reflector().get_jsobject().get());
|
||||
let _ac = JSAutoCompartment::new(scope.get_cx(),
|
||||
scope.reflector().get_jsobject().get());
|
||||
let mut message = RootedValue::new(scope.get_cx(), UndefinedValue());
|
||||
data.read(GlobalRef::Worker(scope), message.handle_mut());
|
||||
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
|
||||
@ -375,8 +388,10 @@ impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
|
||||
fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
|
||||
let data = try!(StructuredCloneData::write(cx, message));
|
||||
let worker = self.worker.borrow().as_ref().unwrap().clone();
|
||||
self.parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||
box WorkerMessageHandler::new(worker, data))).unwrap();
|
||||
self.parent_sender
|
||||
.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||
box WorkerMessageHandler::new(worker, data)))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -35,14 +35,14 @@ use dom::documenttype::DocumentType;
|
||||
use dom::domimplementation::DOMImplementation;
|
||||
use dom::element::{Element, ElementCreator};
|
||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use dom::eventtarget::{EventTarget};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::htmlanchorelement::HTMLAnchorElement;
|
||||
use dom::htmlappletelement::HTMLAppletElement;
|
||||
use dom::htmlareaelement::HTMLAreaElement;
|
||||
use dom::htmlbaseelement::HTMLBaseElement;
|
||||
use dom::htmlbodyelement::HTMLBodyElement;
|
||||
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
|
||||
use dom::htmlelement::{HTMLElement};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::htmlembedelement::HTMLEmbedElement;
|
||||
use dom::htmlformelement::HTMLFormElement;
|
||||
use dom::htmlheadelement::HTMLHeadElement;
|
||||
@ -230,7 +230,7 @@ struct LinksFilter;
|
||||
impl CollectionFilter for LinksFilter {
|
||||
fn filter(&self, elem: &Element, _root: &Node) -> bool {
|
||||
(elem.is::<HTMLAnchorElement>() || elem.is::<HTMLAreaElement>()) &&
|
||||
elem.has_attribute(&atom!("href"))
|
||||
elem.has_attribute(&atom!("href"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,7 +330,8 @@ impl Document {
|
||||
|
||||
pub fn needs_reflow(&self) -> bool {
|
||||
self.GetDocumentElement().is_some() &&
|
||||
(self.upcast::<Node>().get_has_dirty_descendants() || !self.modified_elements.borrow().is_empty())
|
||||
(self.upcast::<Node>().get_has_dirty_descendants() ||
|
||||
!self.modified_elements.borrow().is_empty())
|
||||
}
|
||||
|
||||
/// Returns the first `base` element in the DOM that has an `href` attribute.
|
||||
@ -342,9 +343,9 @@ impl Document {
|
||||
/// https://github.com/w3c/web-platform-tests/issues/2122
|
||||
pub fn refresh_base_element(&self) {
|
||||
let base = self.upcast::<Node>()
|
||||
.traverse_preorder()
|
||||
.filter_map(Root::downcast::<HTMLBaseElement>)
|
||||
.find(|element| element.upcast::<Element>().has_attribute(&atom!("href")));
|
||||
.traverse_preorder()
|
||||
.filter_map(Root::downcast::<HTMLBaseElement>)
|
||||
.find(|element| element.upcast::<Element>().has_attribute(&atom!("href")));
|
||||
self.base_element.set(base.r());
|
||||
}
|
||||
|
||||
@ -377,7 +378,7 @@ impl Document {
|
||||
pub fn reflow_if_reflow_timer_expired(&self) {
|
||||
if let Some(reflow_timeout) = self.reflow_timeout.get() {
|
||||
if time::precise_time_ns() < reflow_timeout {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
self.reflow_timeout.set(None);
|
||||
@ -393,7 +394,7 @@ impl Document {
|
||||
pub fn set_reflow_timeout(&self, timeout: u64) {
|
||||
if let Some(existing_timeout) = self.reflow_timeout.get() {
|
||||
if existing_timeout < timeout {
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.reflow_timeout.set(Some(timeout))
|
||||
@ -405,10 +406,11 @@ impl Document {
|
||||
}
|
||||
|
||||
/// Remove any existing association between the provided id and any elements in this document.
|
||||
pub fn unregister_named_element(&self,
|
||||
to_unregister: &Element,
|
||||
id: Atom) {
|
||||
debug!("Removing named element from document {:p}: {:p} id={}", self, to_unregister, id);
|
||||
pub fn unregister_named_element(&self, to_unregister: &Element, id: Atom) {
|
||||
debug!("Removing named element from document {:p}: {:p} id={}",
|
||||
self,
|
||||
to_unregister,
|
||||
id);
|
||||
let mut id_map = self.id_map.borrow_mut();
|
||||
let is_empty = match id_map.get_mut(&id) {
|
||||
None => false,
|
||||
@ -426,17 +428,19 @@ impl Document {
|
||||
}
|
||||
|
||||
/// Associate an element present in this document with the provided id.
|
||||
pub fn register_named_element(&self,
|
||||
element: &Element,
|
||||
id: Atom) {
|
||||
debug!("Adding named element to document {:p}: {:p} id={}", self, element, id);
|
||||
pub fn register_named_element(&self, element: &Element, id: Atom) {
|
||||
debug!("Adding named element to document {:p}: {:p} id={}",
|
||||
self,
|
||||
element,
|
||||
id);
|
||||
assert!(element.upcast::<Node>().is_in_doc());
|
||||
assert!(!id.is_empty());
|
||||
|
||||
let mut id_map = self.id_map.borrow_mut();
|
||||
|
||||
let root = self.GetDocumentElement().expect(
|
||||
"The element is in the document, so there must be a document element.");
|
||||
let root = self.GetDocumentElement()
|
||||
.expect("The element is in the document, so there must be a document \
|
||||
element.");
|
||||
|
||||
match id_map.entry(id) {
|
||||
Vacant(entry) => {
|
||||
@ -470,9 +474,8 @@ impl Document {
|
||||
self.get_element_by_id(&Atom::from_slice(fragid)).or_else(|| {
|
||||
let check_anchor = |node: &HTMLAnchorElement| {
|
||||
let elem = node.upcast::<Element>();
|
||||
elem.get_attribute(&ns!(""), &atom!("name")).map_or(false, |attr| {
|
||||
&**attr.value() == fragid
|
||||
})
|
||||
elem.get_attribute(&ns!(""), &atom!("name"))
|
||||
.map_or(false, |attr| &**attr.value() == fragid)
|
||||
};
|
||||
let doc_node = self.upcast::<Node>();
|
||||
doc_node.traverse_preorder()
|
||||
@ -497,7 +500,7 @@ impl Document {
|
||||
assert!(self.GetDocumentElement().is_some());
|
||||
match self.window.layout().mouse_over(*point) {
|
||||
Ok(MouseOverResponse(node_address)) => node_address,
|
||||
Err(()) => vec!(),
|
||||
Err(()) => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,7 +549,7 @@ impl Document {
|
||||
/// Reassign the focus context to the element that last requested focus during this
|
||||
/// transaction, or none if no elements requested it.
|
||||
pub fn commit_focus_transaction(&self, focus_type: FocusType) {
|
||||
//TODO: dispatch blur, focus, focusout, and focusin events
|
||||
// TODO: dispatch blur, focus, focusout, and focusin events
|
||||
|
||||
if let Some(ref elem) = self.focused.get() {
|
||||
elem.set_focus_state(false);
|
||||
@ -579,7 +582,9 @@ impl Document {
|
||||
pub fn send_title_to_compositor(&self) {
|
||||
let window = self.window();
|
||||
let compositor = window.compositor();
|
||||
compositor.send(ScriptToCompositorMsg::SetTitle(window.pipeline(), Some(String::from(self.Title())))).unwrap();
|
||||
compositor.send(ScriptToCompositorMsg::SetTitle(window.pipeline(),
|
||||
Some(String::from(self.Title()))))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn dirty_all_nodes(&self) {
|
||||
@ -589,9 +594,11 @@ impl Document {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_mouse_event(&self, js_runtime: *mut JSRuntime,
|
||||
_button: MouseButton, point: Point2D<f32>,
|
||||
mouse_event_type: MouseEventType) {
|
||||
pub fn handle_mouse_event(&self,
|
||||
js_runtime: *mut JSRuntime,
|
||||
_button: MouseButton,
|
||||
point: Point2D<f32>,
|
||||
mouse_event_type: MouseEventType) {
|
||||
let mouse_event_type_string = match mouse_event_type {
|
||||
MouseEventType::Click => "click".to_owned(),
|
||||
MouseEventType::MouseUp => "mouseup".to_owned(),
|
||||
@ -620,7 +627,7 @@ impl Document {
|
||||
let node = el.upcast::<Node>();
|
||||
debug!("{} on {:?}", mouse_event_type_string, node.debug_str());
|
||||
// Prevent click event if form control element is disabled.
|
||||
if let MouseEventType::Click = mouse_event_type {
|
||||
if let MouseEventType::Click = mouse_event_type {
|
||||
if el.click_event_filter_by_disabled_state() {
|
||||
return;
|
||||
}
|
||||
@ -638,8 +645,14 @@ impl Document {
|
||||
EventCancelable::Cancelable,
|
||||
Some(&self.window),
|
||||
clickCount,
|
||||
x, y, x, y, // TODO: Get real screen coordinates?
|
||||
false, false, false, false,
|
||||
x,
|
||||
y,
|
||||
x,
|
||||
y, // TODO: Get real screen coordinates?
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0i16,
|
||||
None);
|
||||
let event = event.upcast::<Event>();
|
||||
@ -649,7 +662,7 @@ impl Document {
|
||||
// https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps
|
||||
match mouse_event_type {
|
||||
MouseEventType::Click => el.authentic_click_activation(event),
|
||||
_ => {
|
||||
_ => {
|
||||
let target = node.upcast();
|
||||
event.fire(target);
|
||||
},
|
||||
@ -663,10 +676,7 @@ impl Document {
|
||||
ReflowReason::MouseEvent);
|
||||
}
|
||||
|
||||
pub fn fire_mouse_event(&self,
|
||||
point: Point2D<f32>,
|
||||
target: &EventTarget,
|
||||
event_name: String) {
|
||||
pub fn fire_mouse_event(&self, point: Point2D<f32>, target: &EventTarget, event_name: String) {
|
||||
let x = point.x.to_i32().unwrap_or(0);
|
||||
let y = point.y.to_i32().unwrap_or(0);
|
||||
|
||||
@ -676,8 +686,14 @@ impl Document {
|
||||
EventCancelable::Cancelable,
|
||||
Some(&self.window),
|
||||
0i32,
|
||||
x, y, x, y,
|
||||
false, false, false, false,
|
||||
x,
|
||||
y,
|
||||
x,
|
||||
y,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0i16,
|
||||
None);
|
||||
let event = mouse_event.upcast::<Event>();
|
||||
@ -685,9 +701,9 @@ impl Document {
|
||||
}
|
||||
|
||||
pub fn handle_mouse_move_event(&self,
|
||||
js_runtime: *mut JSRuntime,
|
||||
point: Option<Point2D<f32>>,
|
||||
prev_mouse_over_targets: &mut RootedVec<JS<Element>>) {
|
||||
js_runtime: *mut JSRuntime,
|
||||
point: Option<Point2D<f32>>,
|
||||
prev_mouse_over_targets: &mut RootedVec<JS<Element>>) {
|
||||
// Build a list of elements that are currently under the mouse.
|
||||
let mouse_over_addresses = point.as_ref()
|
||||
.map(|point| self.get_nodes_under_mouse(point))
|
||||
@ -736,8 +752,8 @@ impl Document {
|
||||
|
||||
// Send mousemove event to topmost target
|
||||
if mouse_over_addresses.len() > 0 {
|
||||
let top_most_node =
|
||||
node::from_untrusted_node_address(js_runtime, mouse_over_addresses[0]);
|
||||
let top_most_node = node::from_untrusted_node_address(js_runtime,
|
||||
mouse_over_addresses[0]);
|
||||
|
||||
let target = top_most_node.upcast();
|
||||
if let Some(point) = point {
|
||||
@ -769,7 +785,7 @@ impl Document {
|
||||
|
||||
let node = match self.hit_test(&point) {
|
||||
Some(node_address) => node::from_untrusted_node_address(js_runtime, node_address),
|
||||
None => return false
|
||||
None => return false,
|
||||
};
|
||||
let el = match node.downcast::<Element>() {
|
||||
Some(el) => Root::from_ref(el),
|
||||
@ -777,7 +793,7 @@ impl Document {
|
||||
let parent = node.GetParentNode();
|
||||
match parent.and_then(Root::downcast::<Element>) {
|
||||
Some(parent) => parent,
|
||||
None => return false
|
||||
None => return false,
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -789,10 +805,15 @@ impl Document {
|
||||
let page_x = Finite::wrap(point.x as f64 + window.PageXOffset() as f64);
|
||||
let page_y = Finite::wrap(point.y as f64 + window.PageYOffset() as f64);
|
||||
|
||||
let touch = Touch::new(window, identifier, target.r(),
|
||||
client_x, client_y, // TODO: Get real screen coordinates?
|
||||
client_x, client_y,
|
||||
page_x, page_y);
|
||||
let touch = Touch::new(window,
|
||||
identifier,
|
||||
target.r(),
|
||||
client_x,
|
||||
client_y, // TODO: Get real screen coordinates?
|
||||
client_x,
|
||||
client_y,
|
||||
page_x,
|
||||
page_y);
|
||||
|
||||
match event_type {
|
||||
TouchEventType::Down => {
|
||||
@ -804,7 +825,7 @@ impl Document {
|
||||
let mut active_touch_points = self.active_touch_points.borrow_mut();
|
||||
match active_touch_points.iter_mut().find(|t| t.Identifier() == identifier) {
|
||||
Some(t) => *t = JS::from_rooted(&touch),
|
||||
None => warn!("Got a touchmove event for a non-active touch point")
|
||||
None => warn!("Got a touchmove event for a non-active touch point"),
|
||||
}
|
||||
}
|
||||
TouchEventType::Up |
|
||||
@ -812,8 +833,10 @@ impl Document {
|
||||
// Remove an existing touch point
|
||||
let mut active_touch_points = self.active_touch_points.borrow_mut();
|
||||
match active_touch_points.iter().position(|t| t.Identifier() == identifier) {
|
||||
Some(i) => { active_touch_points.swap_remove(i); }
|
||||
None => warn!("Got a touchend event for a non-active touch point")
|
||||
Some(i) => {
|
||||
active_touch_points.swap_remove(i);
|
||||
}
|
||||
None => warn!("Got a touchend event for a non-active touch point"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -825,8 +848,11 @@ impl Document {
|
||||
changed_touches.push(JS::from_rooted(&touch));
|
||||
|
||||
let mut target_touches = RootedVec::new();
|
||||
target_touches.extend(self.active_touch_points.borrow().iter().filter(
|
||||
|t| t.Target() == target).cloned());
|
||||
target_touches.extend(self.active_touch_points
|
||||
.borrow()
|
||||
.iter()
|
||||
.filter(|t| t.Target() == target)
|
||||
.cloned());
|
||||
|
||||
let event = TouchEvent::new(window,
|
||||
DOMString::from(event_name),
|
||||
@ -838,7 +864,10 @@ impl Document {
|
||||
&TouchList::new(window, changed_touches.r()),
|
||||
&TouchList::new(window, target_touches.r()),
|
||||
// FIXME: modifier keys
|
||||
false, false, false, false);
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false);
|
||||
let event = event.upcast::<Event>();
|
||||
let result = event.fire(target.r());
|
||||
|
||||
@ -850,10 +879,10 @@ impl Document {
|
||||
|
||||
/// The entry point for all key processing for web content
|
||||
pub fn dispatch_key_event(&self,
|
||||
key: Key,
|
||||
state: KeyState,
|
||||
modifiers: KeyModifiers,
|
||||
compositor: &mut IpcSender<ScriptToCompositorMsg>) {
|
||||
key: Key,
|
||||
state: KeyState,
|
||||
modifiers: KeyModifiers,
|
||||
compositor: &mut IpcSender<ScriptToCompositorMsg>) {
|
||||
let focused = self.get_focused_element();
|
||||
let body = self.GetBody();
|
||||
|
||||
@ -871,19 +900,31 @@ impl Document {
|
||||
let is_composing = false;
|
||||
let is_repeating = state == KeyState::Repeated;
|
||||
let ev_type = DOMString::from(match state {
|
||||
KeyState::Pressed | KeyState::Repeated => "keydown",
|
||||
KeyState::Released => "keyup",
|
||||
}.to_owned());
|
||||
KeyState::Pressed | KeyState::Repeated => "keydown",
|
||||
KeyState::Released => "keyup",
|
||||
}
|
||||
.to_owned());
|
||||
|
||||
let props = KeyboardEvent::key_properties(key, modifiers);
|
||||
|
||||
let keyevent = KeyboardEvent::new(&self.window, ev_type, true, true,
|
||||
Some(&self.window), 0, Some(key),
|
||||
let keyevent = KeyboardEvent::new(&self.window,
|
||||
ev_type,
|
||||
true,
|
||||
true,
|
||||
Some(&self.window),
|
||||
0,
|
||||
Some(key),
|
||||
DOMString::from(props.key_string),
|
||||
DOMString::from(props.code),
|
||||
props.location, is_repeating, is_composing,
|
||||
ctrl, alt, shift, meta,
|
||||
None, props.key_code);
|
||||
props.location,
|
||||
is_repeating,
|
||||
is_composing,
|
||||
ctrl,
|
||||
alt,
|
||||
shift,
|
||||
meta,
|
||||
None,
|
||||
props.key_code);
|
||||
let event = keyevent.upcast::<Event>();
|
||||
event.fire(target);
|
||||
let mut prevented = event.DefaultPrevented();
|
||||
@ -891,13 +932,24 @@ impl Document {
|
||||
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#keys-cancelable-keys
|
||||
if state != KeyState::Released && props.is_printable() && !prevented {
|
||||
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#keypress-event-order
|
||||
let event = KeyboardEvent::new(&self.window, DOMString::from("keypress"),
|
||||
true, true, Some(&self.window), 0, Some(key),
|
||||
let event = KeyboardEvent::new(&self.window,
|
||||
DOMString::from("keypress"),
|
||||
true,
|
||||
true,
|
||||
Some(&self.window),
|
||||
0,
|
||||
Some(key),
|
||||
DOMString::from(props.key_string),
|
||||
DOMString::from(props.code),
|
||||
props.location, is_repeating, is_composing,
|
||||
ctrl, alt, shift, meta,
|
||||
props.char_code, 0);
|
||||
props.location,
|
||||
is_repeating,
|
||||
is_composing,
|
||||
ctrl,
|
||||
alt,
|
||||
shift,
|
||||
meta,
|
||||
props.char_code,
|
||||
0);
|
||||
let ev = event.upcast::<Event>();
|
||||
ev.fire(target);
|
||||
prevented = ev.DefaultPrevented();
|
||||
@ -930,7 +982,7 @@ impl Document {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
@ -939,8 +991,9 @@ impl Document {
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#converting-nodes-into-a-node
|
||||
pub fn node_from_nodes_and_strings(&self, mut nodes: Vec<NodeOrString>)
|
||||
-> Fallible<Root<Node>> {
|
||||
pub fn node_from_nodes_and_strings(&self,
|
||||
mut nodes: Vec<NodeOrString>)
|
||||
-> Fallible<Root<Node>> {
|
||||
if nodes.len() == 1 {
|
||||
Ok(match nodes.pop().unwrap() {
|
||||
NodeOrString::eNode(node) => node,
|
||||
@ -970,7 +1023,7 @@ impl Document {
|
||||
Some(ref body) => {
|
||||
body.upcast::<Element>().get_string_attribute(local_name)
|
||||
},
|
||||
None => DOMString::new()
|
||||
None => DOMString::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1096,9 +1149,9 @@ impl Document {
|
||||
callback(*timing);
|
||||
}
|
||||
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::RequestAnimationFrame);
|
||||
self.window.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::RequestAnimationFrame);
|
||||
}
|
||||
|
||||
pub fn prepare_async_load(&self, load: LoadType) -> PendingAsyncLoad {
|
||||
@ -1137,7 +1190,8 @@ impl Document {
|
||||
// If we don't have a parser, and the reflow timer has been reset, explicitly
|
||||
// trigger a reflow.
|
||||
if let LoadType::Stylesheet(_) = load {
|
||||
self.window().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery,
|
||||
self.window().reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::StylesheetLoaded);
|
||||
}
|
||||
}
|
||||
@ -1159,8 +1213,7 @@ impl Document {
|
||||
Some(script) => script,
|
||||
};
|
||||
|
||||
if self.script_blocking_stylesheets_count.get() == 0 &&
|
||||
script.is_ready_to_be_executed() {
|
||||
if self.script_blocking_stylesheets_count.get() == 0 && script.is_ready_to_be_executed() {
|
||||
script.execute();
|
||||
self.pending_parsing_blocking_script.set(None);
|
||||
return ParserBlockedByScript::Unblocked;
|
||||
@ -1237,7 +1290,9 @@ impl Document {
|
||||
EventCancelable::NotCancelable);
|
||||
let doctarget = self.upcast::<EventTarget>();
|
||||
let _ = doctarget.DispatchEvent(event.r());
|
||||
self.window().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::DOMContentLoaded);
|
||||
self.window().reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::DOMContentLoaded);
|
||||
|
||||
update_with_current_time(&self.dom_content_loaded_event_end);
|
||||
}
|
||||
@ -1331,7 +1386,8 @@ impl Document {
|
||||
content_type: Option<DOMString>,
|
||||
last_modified: Option<String>,
|
||||
source: DocumentSource,
|
||||
doc_loader: DocumentLoader) -> Document {
|
||||
doc_loader: DocumentLoader)
|
||||
-> Document {
|
||||
let url = url.unwrap_or_else(|| Url::parse("about:blank").unwrap());
|
||||
|
||||
let (ready_state, domcontentloaded_dispatched) = if source == DocumentSource::FromParser {
|
||||
@ -1351,8 +1407,8 @@ impl Document {
|
||||
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
|
||||
IsHTMLDocument::HTMLDocument => "text/html",
|
||||
// https://dom.spec.whatwg.org/#concept-document-content-type
|
||||
IsHTMLDocument::NonHTMLDocument => "application/xml"
|
||||
})
|
||||
IsHTMLDocument::NonHTMLDocument => "application/xml",
|
||||
}),
|
||||
},
|
||||
last_modified: last_modified,
|
||||
url: url,
|
||||
@ -1381,9 +1437,9 @@ impl Document {
|
||||
current_script: Default::default(),
|
||||
pending_parsing_blocking_script: Default::default(),
|
||||
script_blocking_stylesheets_count: Cell::new(0u32),
|
||||
deferred_scripts: DOMRefCell::new(vec!()),
|
||||
asap_in_order_scripts_list: DOMRefCell::new(vec!()),
|
||||
asap_scripts_set: DOMRefCell::new(vec!()),
|
||||
deferred_scripts: DOMRefCell::new(vec![]),
|
||||
asap_in_order_scripts_list: DOMRefCell::new(vec![]),
|
||||
asap_scripts_set: DOMRefCell::new(vec![]),
|
||||
scripting_enabled: Cell::new(true),
|
||||
animation_frame_ident: Cell::new(0),
|
||||
animation_frame_list: DOMRefCell::new(HashMap::new()),
|
||||
@ -1408,9 +1464,13 @@ impl Document {
|
||||
let doc = win.Document();
|
||||
let doc = doc.r();
|
||||
let docloader = DocumentLoader::new(&*doc.loader());
|
||||
Ok(Document::new(win, None,
|
||||
IsHTMLDocument::NonHTMLDocument, None,
|
||||
None, DocumentSource::NotFromParser, docloader))
|
||||
Ok(Document::new(win,
|
||||
None,
|
||||
IsHTMLDocument::NonHTMLDocument,
|
||||
None,
|
||||
None,
|
||||
DocumentSource::NotFromParser,
|
||||
docloader))
|
||||
}
|
||||
|
||||
pub fn new(window: &Window,
|
||||
@ -1419,10 +1479,15 @@ impl Document {
|
||||
content_type: Option<DOMString>,
|
||||
last_modified: Option<String>,
|
||||
source: DocumentSource,
|
||||
doc_loader: DocumentLoader) -> Root<Document> {
|
||||
let document = reflect_dom_object(box Document::new_inherited(window, url, doctype,
|
||||
content_type, last_modified,
|
||||
source, doc_loader),
|
||||
doc_loader: DocumentLoader)
|
||||
-> Root<Document> {
|
||||
let document = reflect_dom_object(box Document::new_inherited(window,
|
||||
url,
|
||||
doctype,
|
||||
content_type,
|
||||
last_modified,
|
||||
source,
|
||||
doc_loader),
|
||||
GlobalRef::Window(window),
|
||||
DocumentBinding::Wrap);
|
||||
{
|
||||
@ -1435,7 +1500,8 @@ impl Document {
|
||||
fn create_node_list<F: Fn(&Node) -> bool>(&self, callback: F) -> Root<NodeList> {
|
||||
let doc = self.GetDocumentElement();
|
||||
let maybe_node = doc.r().map(Castable::upcast::<Node>);
|
||||
let iter = maybe_node.iter().flat_map(|node| node.traverse_preorder())
|
||||
let iter = maybe_node.iter()
|
||||
.flat_map(|node| node.traverse_preorder())
|
||||
.filter(|node| callback(node.r()));
|
||||
NodeList::new_simple_list(&self.window, iter)
|
||||
}
|
||||
@ -1477,9 +1543,13 @@ impl Document {
|
||||
} else {
|
||||
IsHTMLDocument::NonHTMLDocument
|
||||
};
|
||||
let new_doc = Document::new(
|
||||
self.window(), None, doctype, None, None,
|
||||
DocumentSource::NotFromParser, DocumentLoader::new(&self.loader()));
|
||||
let new_doc = Document::new(self.window(),
|
||||
None,
|
||||
doctype,
|
||||
None,
|
||||
None,
|
||||
DocumentSource::NotFromParser,
|
||||
DocumentLoader::new(&self.loader()));
|
||||
new_doc.appropriate_template_contents_owner_document.set(Some(&new_doc));
|
||||
new_doc
|
||||
})
|
||||
@ -1501,7 +1571,8 @@ impl Document {
|
||||
let mut map = self.modified_elements.borrow_mut();
|
||||
let mut snapshot = map.entry(JS::from_ref(el)).or_insert(ElementSnapshot::new());
|
||||
if snapshot.attrs.is_none() {
|
||||
let attrs = el.attrs().iter()
|
||||
let attrs = el.attrs()
|
||||
.iter()
|
||||
.map(|attr| (attr.identifier().clone(), attr.value().clone()))
|
||||
.collect();
|
||||
snapshot.attrs = Some(attrs);
|
||||
@ -1521,7 +1592,7 @@ impl Element {
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) |
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement))
|
||||
if self.get_disabled_state() => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1546,7 +1617,7 @@ impl DocumentMethods for Document {
|
||||
None => match self.GetBody() { // Step 5.
|
||||
Some(body) => Some(Root::upcast(body)),
|
||||
None => self.GetDocumentElement(),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -1565,7 +1636,7 @@ impl DocumentMethods for Document {
|
||||
false //TODO Step 4.
|
||||
}
|
||||
}
|
||||
None => false
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1578,7 +1649,7 @@ impl DocumentMethods for Document {
|
||||
fn CompatMode(&self) -> DOMString {
|
||||
DOMString::from(match self.quirks_mode.get() {
|
||||
LimitedQuirks | NoQuirks => "CSS1Compat",
|
||||
Quirks => "BackCompat"
|
||||
Quirks => "BackCompat",
|
||||
})
|
||||
}
|
||||
|
||||
@ -1616,7 +1687,10 @@ impl DocumentMethods for Document {
|
||||
let mut tag_copy = tag_name;
|
||||
tag_copy.make_ascii_lowercase();
|
||||
let ascii_lower_tag = Atom::from_slice(&tag_copy);
|
||||
let result = HTMLCollection::by_atomic_tag_name(&self.window, self.upcast(), tag_atom, ascii_lower_tag);
|
||||
let result = HTMLCollection::by_atomic_tag_name(&self.window,
|
||||
self.upcast(),
|
||||
tag_atom,
|
||||
ascii_lower_tag);
|
||||
entry.insert(JS::from_rooted(&result));
|
||||
result
|
||||
}
|
||||
@ -1624,7 +1698,9 @@ impl DocumentMethods for Document {
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens
|
||||
fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>, tag_name: DOMString)
|
||||
fn GetElementsByTagNameNS(&self,
|
||||
maybe_ns: Option<DOMString>,
|
||||
tag_name: DOMString)
|
||||
-> Root<HTMLCollection> {
|
||||
let ns = namespace_from_domstring(maybe_ns);
|
||||
let local = Atom::from_slice(&tag_name);
|
||||
@ -1641,11 +1717,15 @@ impl DocumentMethods for Document {
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname
|
||||
fn GetElementsByClassName(&self, classes: DOMString) -> Root<HTMLCollection> {
|
||||
let class_atoms: Vec<Atom> = split_html_space_chars(&classes).map(Atom::from_slice).collect();
|
||||
match self.classes_map.borrow_mut().entry(class_atoms.clone()) {
|
||||
let class_atoms: Vec<Atom> = split_html_space_chars(&classes)
|
||||
.map(Atom::from_slice)
|
||||
.collect();
|
||||
match self.classes_map.borrow_mut().entry(class_atoms.clone()) {
|
||||
Occupied(entry) => Root::from_ref(entry.get()),
|
||||
Vacant(entry) => {
|
||||
let result = HTMLCollection::by_atomic_class_name(&self.window, self.upcast(), class_atoms);
|
||||
let result = HTMLCollection::by_atomic_class_name(&self.window,
|
||||
self.upcast(),
|
||||
class_atoms);
|
||||
entry.insert(JS::from_rooted(&result));
|
||||
result
|
||||
}
|
||||
@ -1673,9 +1753,10 @@ impl DocumentMethods for Document {
|
||||
// https://dom.spec.whatwg.org/#dom-document-createelementns
|
||||
fn CreateElementNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
qualified_name: DOMString) -> Fallible<Root<Element>> {
|
||||
let (namespace, prefix, local_name) =
|
||||
try!(validate_and_extract(namespace, &qualified_name));
|
||||
qualified_name: DOMString)
|
||||
-> Fallible<Root<Element>> {
|
||||
let (namespace, prefix, local_name) = try!(validate_and_extract(namespace,
|
||||
&qualified_name));
|
||||
let name = QualName::new(namespace, local_name);
|
||||
Ok(Element::create(name, prefix, self, ElementCreator::ScriptCreated))
|
||||
}
|
||||
@ -1696,14 +1777,21 @@ impl DocumentMethods for Document {
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-createattributens
|
||||
fn CreateAttributeNS(&self, namespace: Option<DOMString>, qualified_name: DOMString)
|
||||
fn CreateAttributeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
qualified_name: DOMString)
|
||||
-> Fallible<Root<Attr>> {
|
||||
let (namespace, prefix, local_name) =
|
||||
try!(validate_and_extract(namespace, &qualified_name));
|
||||
let (namespace, prefix, local_name) = try!(validate_and_extract(namespace,
|
||||
&qualified_name));
|
||||
let value = AttrValue::String(DOMString::new());
|
||||
let qualified_name = Atom::from_slice(&qualified_name);
|
||||
Ok(Attr::new(&self.window, local_name, value, qualified_name,
|
||||
namespace, prefix, None))
|
||||
Ok(Attr::new(&self.window,
|
||||
local_name,
|
||||
value,
|
||||
qualified_name,
|
||||
namespace,
|
||||
prefix,
|
||||
None))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-createdocumentfragment
|
||||
@ -1722,8 +1810,10 @@ impl DocumentMethods for Document {
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-createprocessinginstruction
|
||||
fn CreateProcessingInstruction(&self, target: DOMString, data: DOMString) ->
|
||||
Fallible<Root<ProcessingInstruction>> {
|
||||
fn CreateProcessingInstruction(&self,
|
||||
target: DOMString,
|
||||
data: DOMString)
|
||||
-> Fallible<Root<ProcessingInstruction>> {
|
||||
// Step 1.
|
||||
if xml_name_type(&target) == InvalidXMLName {
|
||||
return Err(Error::InvalidCharacter);
|
||||
@ -1748,7 +1838,7 @@ impl DocumentMethods for Document {
|
||||
// Step 2.
|
||||
let clone_children = match deep {
|
||||
true => CloneChildrenFlag::CloneChildren,
|
||||
false => CloneChildrenFlag::DoNotCloneChildren
|
||||
false => CloneChildrenFlag::DoNotCloneChildren,
|
||||
};
|
||||
|
||||
Ok(Node::clone(node, Some(self), clone_children))
|
||||
@ -1811,8 +1901,11 @@ impl DocumentMethods for Document {
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-createnodeiteratorroot-whattoshow-filter
|
||||
fn CreateNodeIterator(&self, root: &Node, whatToShow: u32, filter: Option<Rc<NodeFilter>>)
|
||||
-> Root<NodeIterator> {
|
||||
fn CreateNodeIterator(&self,
|
||||
root: &Node,
|
||||
whatToShow: u32,
|
||||
filter: Option<Rc<NodeFilter>>)
|
||||
-> Root<NodeIterator> {
|
||||
NodeIterator::new(self, root, whatToShow, filter)
|
||||
}
|
||||
|
||||
@ -1828,11 +1921,22 @@ impl DocumentMethods for Document {
|
||||
-> Root<Touch> {
|
||||
let clientX = Finite::wrap(*pageX - window.PageXOffset() as f64);
|
||||
let clientY = Finite::wrap(*pageY - window.PageYOffset() as f64);
|
||||
Touch::new(window, identifier, target, screenX, screenY, clientX, clientY, pageX, pageY)
|
||||
Touch::new(window,
|
||||
identifier,
|
||||
target,
|
||||
screenX,
|
||||
screenY,
|
||||
clientX,
|
||||
clientY,
|
||||
pageX,
|
||||
pageY)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-createtreewalker
|
||||
fn CreateTreeWalker(&self, root: &Node, whatToShow: u32, filter: Option<Rc<NodeFilter>>)
|
||||
fn CreateTreeWalker(&self,
|
||||
root: &Node,
|
||||
whatToShow: u32,
|
||||
filter: Option<Rc<NodeFilter>>)
|
||||
-> Root<TreeWalker> {
|
||||
TreeWalker::new(self, root, whatToShow, filter)
|
||||
}
|
||||
@ -1842,10 +1946,12 @@ impl DocumentMethods for Document {
|
||||
let title = self.GetDocumentElement().and_then(|root| {
|
||||
if root.namespace() == &ns!(SVG) && root.local_name() == &atom!("svg") {
|
||||
// Step 1.
|
||||
root.upcast::<Node>().child_elements().find(|node| {
|
||||
node.namespace() == &ns!(SVG) &&
|
||||
node.local_name() == &atom!("title")
|
||||
}).map(Root::upcast::<Node>)
|
||||
root.upcast::<Node>()
|
||||
.child_elements()
|
||||
.find(|node| {
|
||||
node.namespace() == &ns!(SVG) && node.local_name() == &atom!("title")
|
||||
})
|
||||
.map(Root::upcast::<Node>)
|
||||
} else {
|
||||
// Step 2.
|
||||
root.upcast::<Node>()
|
||||
@ -1871,23 +1977,19 @@ impl DocumentMethods for Document {
|
||||
None => return,
|
||||
};
|
||||
|
||||
let elem = if root.namespace() == &ns!(SVG) &&
|
||||
root.local_name() == &atom!("svg") {
|
||||
let elem = if root.namespace() == &ns!(SVG) && root.local_name() == &atom!("svg") {
|
||||
let elem = root.upcast::<Node>().child_elements().find(|node| {
|
||||
node.namespace() == &ns!(SVG) &&
|
||||
node.local_name() == &atom!("title")
|
||||
node.namespace() == &ns!(SVG) && node.local_name() == &atom!("title")
|
||||
});
|
||||
match elem {
|
||||
Some(elem) => Root::upcast::<Node>(elem),
|
||||
None => {
|
||||
let name = QualName::new(ns!(SVG), atom!("title"));
|
||||
let elem = Element::create(name, None, self,
|
||||
ElementCreator::ScriptCreated);
|
||||
let elem = Element::create(name, None, self, ElementCreator::ScriptCreated);
|
||||
let parent = root.upcast::<Node>();
|
||||
let child = elem.upcast::<Node>();
|
||||
parent
|
||||
.InsertBefore(child, parent.GetFirstChild().r())
|
||||
.unwrap()
|
||||
parent.InsertBefore(child, parent.GetFirstChild().r())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
} else if root.namespace() == &ns!(HTML) {
|
||||
@ -1900,7 +2002,9 @@ impl DocumentMethods for Document {
|
||||
match self.GetHead() {
|
||||
Some(head) => {
|
||||
let name = QualName::new(ns!(HTML), atom!("title"));
|
||||
let elem = Element::create(name, None, self,
|
||||
let elem = Element::create(name,
|
||||
None,
|
||||
self,
|
||||
ElementCreator::ScriptCreated);
|
||||
head.upcast::<Node>()
|
||||
.AppendChild(elem.upcast())
|
||||
@ -1911,7 +2015,7 @@ impl DocumentMethods for Document {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return
|
||||
return;
|
||||
};
|
||||
|
||||
elem.SetTextContent(Some(title));
|
||||
@ -1919,9 +2023,8 @@ impl DocumentMethods for Document {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-document-head
|
||||
fn GetHead(&self) -> Option<Root<HTMLHeadElement>> {
|
||||
self.get_html_element().and_then(|root| {
|
||||
root.upcast::<Node>().children().filter_map(Root::downcast).next()
|
||||
})
|
||||
self.get_html_element()
|
||||
.and_then(|root| root.upcast::<Node>().children().filter_map(Root::downcast).next())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-document-currentscript
|
||||
@ -1955,7 +2058,7 @@ impl DocumentMethods for Document {
|
||||
match node.type_id() {
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement)) |
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFrameSetElement)) => {}
|
||||
_ => return Err(Error::HierarchyRequest)
|
||||
_ => return Err(Error::HierarchyRequest),
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
@ -1993,9 +2096,8 @@ impl DocumentMethods for Document {
|
||||
if element.namespace() != &ns!(HTML) {
|
||||
return false;
|
||||
}
|
||||
element.get_attribute(&ns!(""), &atom!("name")).map_or(false, |attr| {
|
||||
&**attr.value() == &*name
|
||||
})
|
||||
element.get_attribute(&ns!(""), &atom!("name"))
|
||||
.map_or(false, |attr| &**attr.value() == &*name)
|
||||
})
|
||||
}
|
||||
|
||||
@ -2120,7 +2222,7 @@ impl DocumentMethods for Document {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-document-cookie
|
||||
fn GetCookie(&self) -> Fallible<DOMString> {
|
||||
//TODO: return empty string for cookie-averse Document
|
||||
// TODO: return empty string for cookie-averse Document
|
||||
let url = self.url();
|
||||
if !is_scheme_host_port_tuple(&url) {
|
||||
return Err(Error::Security);
|
||||
@ -2133,12 +2235,14 @@ impl DocumentMethods for Document {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-document-cookie
|
||||
fn SetCookie(&self, cookie: DOMString) -> ErrorResult {
|
||||
//TODO: ignore for cookie-averse Document
|
||||
// TODO: ignore for cookie-averse Document
|
||||
let url = self.url();
|
||||
if !is_scheme_host_port_tuple(url) {
|
||||
return Err(Error::Security);
|
||||
}
|
||||
let _ = self.window.resource_task().send(SetCookiesForUrl((*url).clone(), String::from(cookie), NonHTTP));
|
||||
let _ = self.window
|
||||
.resource_task()
|
||||
.send(SetCookiesForUrl((*url).clone(), String::from(cookie), NonHTTP));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -2153,8 +2257,7 @@ impl DocumentMethods for Document {
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-tree-accessors:dom-document-nameditem-filter
|
||||
fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString, found: &mut bool)
|
||||
-> *mut JSObject {
|
||||
fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString, found: &mut bool) -> *mut JSObject {
|
||||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
struct NamedElementFilter {
|
||||
name: Atom,
|
||||
@ -2215,15 +2318,15 @@ impl DocumentMethods for Document {
|
||||
let root = self.upcast::<Node>();
|
||||
{
|
||||
// Step 1.
|
||||
let mut elements = root.traverse_preorder().filter(|node| {
|
||||
filter_by_name(&name, node.r())
|
||||
}).peekable();
|
||||
let mut elements = root.traverse_preorder()
|
||||
.filter(|node| filter_by_name(&name, node.r()))
|
||||
.peekable();
|
||||
if let Some(first) = elements.next() {
|
||||
if elements.is_empty() {
|
||||
*found = true;
|
||||
// TODO: Step 2.
|
||||
// Step 3.
|
||||
return first.reflector().get_jsobject().get()
|
||||
return first.reflector().get_jsobject().get();
|
||||
}
|
||||
} else {
|
||||
*found = false;
|
||||
@ -2232,7 +2335,9 @@ impl DocumentMethods for Document {
|
||||
}
|
||||
// Step 4.
|
||||
*found = true;
|
||||
let filter = NamedElementFilter { name: name };
|
||||
let filter = NamedElementFilter {
|
||||
name: name,
|
||||
};
|
||||
let collection = HTMLCollection::create(self.window(), root, box filter);
|
||||
collection.reflector().get_jsobject().get()
|
||||
}
|
||||
@ -2277,13 +2382,13 @@ fn update_with_current_time(marker: &Cell<u64>) {
|
||||
}
|
||||
|
||||
pub struct DocumentProgressHandler {
|
||||
addr: Trusted<Document>
|
||||
addr: Trusted<Document>,
|
||||
}
|
||||
|
||||
impl DocumentProgressHandler {
|
||||
pub fn new(addr: Trusted<Document>) -> DocumentProgressHandler {
|
||||
DocumentProgressHandler {
|
||||
addr: addr
|
||||
addr: addr,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2295,7 +2400,8 @@ impl DocumentProgressHandler {
|
||||
fn dispatch_load(&self) {
|
||||
let document = self.addr.root();
|
||||
let window = document.window();
|
||||
let event = Event::new(GlobalRef::Window(window), DOMString::from("load"),
|
||||
let event = Event::new(GlobalRef::Window(window),
|
||||
DOMString::from("load"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable);
|
||||
let wintarget = window.upcast::<EventTarget>();
|
||||
@ -2307,7 +2413,8 @@ impl DocumentProgressHandler {
|
||||
|
||||
if let Some(frame_element) = browsing_context.frame_element() {
|
||||
let frame_window = window_from_node(frame_element);
|
||||
let event = Event::new(GlobalRef::Window(frame_window.r()), DOMString::from("load"),
|
||||
let event = Event::new(GlobalRef::Window(frame_window.r()),
|
||||
DOMString::from("load"),
|
||||
EventBubbles::DoesNotBubble,
|
||||
EventCancelable::NotCancelable);
|
||||
event.fire(frame_element.upcast());
|
||||
|
@ -34,7 +34,8 @@ impl DocumentFragment {
|
||||
|
||||
pub fn new(document: &Document) -> Root<DocumentFragment> {
|
||||
Node::reflect_node(box DocumentFragment::new_inherited(document),
|
||||
document, DocumentFragmentBinding::Wrap)
|
||||
document,
|
||||
DocumentFragmentBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(global: GlobalRef) -> Fallible<Root<DocumentFragment>> {
|
||||
|
@ -24,10 +24,10 @@ pub struct DocumentType {
|
||||
|
||||
impl DocumentType {
|
||||
fn new_inherited(name: DOMString,
|
||||
public_id: Option<DOMString>,
|
||||
system_id: Option<DOMString>,
|
||||
document: &Document)
|
||||
-> DocumentType {
|
||||
public_id: Option<DOMString>,
|
||||
system_id: Option<DOMString>,
|
||||
document: &Document)
|
||||
-> DocumentType {
|
||||
DocumentType {
|
||||
node: Node::new_inherited(document),
|
||||
name: name,
|
||||
@ -41,10 +41,7 @@ impl DocumentType {
|
||||
system_id: Option<DOMString>,
|
||||
document: &Document)
|
||||
-> Root<DocumentType> {
|
||||
let documenttype = DocumentType::new_inherited(name,
|
||||
public_id,
|
||||
system_id,
|
||||
document);
|
||||
let documenttype = DocumentType::new_inherited(name, public_id, system_id, document);
|
||||
Node::reflect_node(box documenttype, document, DocumentTypeBinding::Wrap)
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ pub enum DOMErrorName {
|
||||
TimeoutError = DOMExceptionConstants::TIMEOUT_ERR,
|
||||
InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR,
|
||||
DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR,
|
||||
EncodingError
|
||||
EncodingError,
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
@ -53,7 +53,9 @@ impl DOMException {
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef, code: DOMErrorName) -> Root<DOMException> {
|
||||
reflect_dom_object(box DOMException::new_inherited(code), global, DOMExceptionBinding::Wrap)
|
||||
reflect_dom_object(box DOMException::new_inherited(code),
|
||||
global,
|
||||
DOMExceptionBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +65,7 @@ impl DOMExceptionMethods for DOMException {
|
||||
match self.code {
|
||||
// https://heycam.github.io/webidl/#dfn-throw
|
||||
DOMErrorName::EncodingError => 0,
|
||||
code => code as u16
|
||||
code => code as u16,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,28 +50,39 @@ impl DOMImplementation {
|
||||
// https://dom.spec.whatwg.org/#domimplementation
|
||||
impl DOMImplementationMethods for DOMImplementation {
|
||||
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
|
||||
fn CreateDocumentType(&self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString)
|
||||
fn CreateDocumentType(&self,
|
||||
qualified_name: DOMString,
|
||||
pubid: DOMString,
|
||||
sysid: DOMString)
|
||||
-> Fallible<Root<DocumentType>> {
|
||||
try!(validate_qualified_name(&qualified_name));
|
||||
Ok(DocumentType::new(qualified_name, Some(pubid), Some(sysid), &self.document))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocument
|
||||
fn CreateDocument(&self, namespace: Option<DOMString>, qname: DOMString,
|
||||
maybe_doctype: Option<&DocumentType>) -> Fallible<Root<Document>> {
|
||||
fn CreateDocument(&self,
|
||||
namespace: Option<DOMString>,
|
||||
qname: DOMString,
|
||||
maybe_doctype: Option<&DocumentType>)
|
||||
-> Fallible<Root<Document>> {
|
||||
let win = self.document.window();
|
||||
let loader = DocumentLoader::new(&self.document.loader());
|
||||
|
||||
// Step 1.
|
||||
let doc = Document::new(win, None, IsHTMLDocument::NonHTMLDocument,
|
||||
None, None, DocumentSource::NotFromParser, loader);
|
||||
let doc = Document::new(win,
|
||||
None,
|
||||
IsHTMLDocument::NonHTMLDocument,
|
||||
None,
|
||||
None,
|
||||
DocumentSource::NotFromParser,
|
||||
loader);
|
||||
// Step 2-3.
|
||||
let maybe_elem = if qname.is_empty() {
|
||||
None
|
||||
} else {
|
||||
match doc.CreateElementNS(namespace, qname) {
|
||||
Err(error) => return Err(error),
|
||||
Ok(elem) => Some(elem)
|
||||
Ok(elem) => Some(elem),
|
||||
}
|
||||
};
|
||||
|
||||
@ -102,8 +113,13 @@ impl DOMImplementationMethods for DOMImplementation {
|
||||
let loader = DocumentLoader::new(&self.document.loader());
|
||||
|
||||
// Step 1-2.
|
||||
let doc = Document::new(win, None, IsHTMLDocument::HTMLDocument, None, None,
|
||||
DocumentSource::NotFromParser, loader);
|
||||
let doc = Document::new(win,
|
||||
None,
|
||||
IsHTMLDocument::HTMLDocument,
|
||||
None,
|
||||
None,
|
||||
DocumentSource::NotFromParser,
|
||||
loader);
|
||||
|
||||
{
|
||||
// Step 3.
|
||||
@ -115,14 +131,16 @@ impl DOMImplementationMethods for DOMImplementation {
|
||||
{
|
||||
// Step 4.
|
||||
let doc_node = doc.upcast::<Node>();
|
||||
let doc_html = Root::upcast::<Node>(
|
||||
HTMLHtmlElement::new(DOMString::from("html"), None, doc.r()));
|
||||
let doc_html = Root::upcast::<Node>(HTMLHtmlElement::new(DOMString::from("html"),
|
||||
None,
|
||||
doc.r()));
|
||||
doc_node.AppendChild(&doc_html).expect("Appending failed");
|
||||
|
||||
{
|
||||
// Step 5.
|
||||
let doc_head = Root::upcast::<Node>(
|
||||
HTMLHeadElement::new(DOMString::from("head"), None, doc.r()));
|
||||
let doc_head = Root::upcast::<Node>(HTMLHeadElement::new(DOMString::from("head"),
|
||||
None,
|
||||
doc.r()));
|
||||
doc_html.AppendChild(&doc_head).unwrap();
|
||||
|
||||
// Step 6.
|
||||
@ -130,8 +148,10 @@ impl DOMImplementationMethods for DOMImplementation {
|
||||
None => (),
|
||||
Some(title_str) => {
|
||||
// Step 6.1.
|
||||
let doc_title = Root::upcast::<Node>(
|
||||
HTMLTitleElement::new(DOMString::from("title"), None, doc.r()));
|
||||
let doc_title =
|
||||
Root::upcast::<Node>(HTMLTitleElement::new(DOMString::from("title"),
|
||||
None,
|
||||
doc.r()));
|
||||
doc_head.AppendChild(&doc_title).unwrap();
|
||||
|
||||
// Step 6.2.
|
||||
|
@ -22,7 +22,7 @@ use util::str::DOMString;
|
||||
#[dom_struct]
|
||||
pub struct DOMParser {
|
||||
reflector_: Reflector,
|
||||
window: JS<Window>, //XXXjdm Document instead?
|
||||
window: JS<Window>, // XXXjdm Document instead?
|
||||
}
|
||||
|
||||
impl DOMParser {
|
||||
@ -34,7 +34,8 @@ impl DOMParser {
|
||||
}
|
||||
|
||||
pub fn new(window: &Window) -> Root<DOMParser> {
|
||||
reflect_dom_object(box DOMParser::new_inherited(window), GlobalRef::Window(window),
|
||||
reflect_dom_object(box DOMParser::new_inherited(window),
|
||||
GlobalRef::Window(window),
|
||||
DOMParserBinding::Wrap)
|
||||
}
|
||||
|
||||
@ -50,13 +51,15 @@ impl DOMParserMethods for DOMParser {
|
||||
ty: DOMParserBinding::SupportedType)
|
||||
-> Fallible<Root<Document>> {
|
||||
let url = self.window.get_url();
|
||||
let content_type = DOMString::from(DOMParserBinding::SupportedTypeValues::strings[ty as usize]);
|
||||
let content_type =
|
||||
DOMString::from(DOMParserBinding::SupportedTypeValues::strings[ty as usize]);
|
||||
let doc = self.window.Document();
|
||||
let doc = doc.r();
|
||||
let loader = DocumentLoader::new(&*doc.loader());
|
||||
match ty {
|
||||
Text_html => {
|
||||
let document = Document::new(&self.window, Some(url.clone()),
|
||||
let document = Document::new(&self.window,
|
||||
Some(url.clone()),
|
||||
IsHTMLDocument::HTMLDocument,
|
||||
Some(content_type),
|
||||
None,
|
||||
@ -67,8 +70,9 @@ impl DOMParserMethods for DOMParser {
|
||||
Ok(document)
|
||||
}
|
||||
Text_xml => {
|
||||
//FIXME: this should probably be FromParser when we actually parse the string (#3756).
|
||||
let document = Document::new(&self.window, Some(url.clone()),
|
||||
// FIXME: this should probably be FromParser when we actually parse the string (#3756).
|
||||
let document = Document::new(&self.window,
|
||||
Some(url.clone()),
|
||||
IsHTMLDocument::NonHTMLDocument,
|
||||
Some(content_type),
|
||||
None,
|
||||
|
@ -13,7 +13,7 @@ use dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods};
|
||||
// http://dev.w3.org/fxtf/geometry/Overview.html#dompoint
|
||||
#[dom_struct]
|
||||
pub struct DOMPoint {
|
||||
point: DOMPointReadOnly
|
||||
point: DOMPointReadOnly,
|
||||
}
|
||||
|
||||
impl DOMPoint {
|
||||
@ -28,7 +28,11 @@ impl DOMPoint {
|
||||
}
|
||||
|
||||
pub fn Constructor(global: GlobalRef,
|
||||
x: f64, y: f64, z: f64, w: f64) -> Fallible<Root<DOMPoint>> {
|
||||
x: f64,
|
||||
y: f64,
|
||||
z: f64,
|
||||
w: f64)
|
||||
-> Fallible<Root<DOMPoint>> {
|
||||
Ok(DOMPoint::new(global, x, y, z, w))
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +31,17 @@ impl DOMPointReadOnly {
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef, x: f64, y: f64, z: f64, w: f64) -> Root<DOMPointReadOnly> {
|
||||
reflect_dom_object(box DOMPointReadOnly::new_inherited(x, y, z, w), global, Wrap)
|
||||
reflect_dom_object(box DOMPointReadOnly::new_inherited(x, y, z, w),
|
||||
global,
|
||||
Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(global: GlobalRef,
|
||||
x: f64, y: f64, z: f64, w: f64) -> Fallible<Root<DOMPointReadOnly>> {
|
||||
x: f64,
|
||||
y: f64,
|
||||
z: f64,
|
||||
w: f64)
|
||||
-> Fallible<Root<DOMPointReadOnly>> {
|
||||
Ok(DOMPointReadOnly::new(global, x, y, z, w))
|
||||
}
|
||||
}
|
||||
|
@ -24,11 +24,17 @@ impl DOMRect {
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef, x: f64, y: f64, width: f64, height: f64) -> Root<DOMRect> {
|
||||
reflect_dom_object(box DOMRect::new_inherited(x, y, width, height), global, DOMRectBinding::Wrap)
|
||||
reflect_dom_object(box DOMRect::new_inherited(x, y, width, height),
|
||||
global,
|
||||
DOMRectBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(global: GlobalRef,
|
||||
x: f64, y: f64, width: f64, height: f64) -> Fallible<Root<DOMRect>> {
|
||||
x: f64,
|
||||
y: f64,
|
||||
width: f64,
|
||||
height: f64)
|
||||
-> Fallible<Root<DOMRect>> {
|
||||
Ok(DOMRect::new(global, x, y, width, height))
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ pub struct DOMRectList {
|
||||
|
||||
impl DOMRectList {
|
||||
fn new_inherited<T>(rects: T) -> DOMRectList
|
||||
where T: Iterator<Item=Root<DOMRect>> {
|
||||
where T: Iterator<Item = Root<DOMRect>>
|
||||
{
|
||||
DOMRectList {
|
||||
reflector_: Reflector::new(),
|
||||
rects: rects.map(|r| JS::from_rooted(&r)).collect(),
|
||||
@ -26,9 +27,11 @@ impl DOMRectList {
|
||||
}
|
||||
|
||||
pub fn new<T>(window: &Window, rects: T) -> Root<DOMRectList>
|
||||
where T: Iterator<Item=Root<DOMRect>> {
|
||||
where T: Iterator<Item = Root<DOMRect>>
|
||||
{
|
||||
reflect_dom_object(box DOMRectList::new_inherited(rects),
|
||||
GlobalRef::Window(window), DOMRectListBinding::Wrap)
|
||||
GlobalRef::Window(window),
|
||||
DOMRectListBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,12 +29,23 @@ impl DOMRectReadOnly {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef, x: f64, y: f64, width: f64, height: f64) -> Root<DOMRectReadOnly> {
|
||||
reflect_dom_object(box DOMRectReadOnly::new_inherited(x, y, width, height), global, Wrap)
|
||||
pub fn new(global: GlobalRef,
|
||||
x: f64,
|
||||
y: f64,
|
||||
width: f64,
|
||||
height: f64)
|
||||
-> Root<DOMRectReadOnly> {
|
||||
reflect_dom_object(box DOMRectReadOnly::new_inherited(x, y, width, height),
|
||||
global,
|
||||
Wrap)
|
||||
}
|
||||
|
||||
pub fn Constructor(global: GlobalRef,
|
||||
x: f64, y: f64, width: f64, height: f64) -> Fallible<Root<DOMRectReadOnly>> {
|
||||
x: f64,
|
||||
y: f64,
|
||||
width: f64,
|
||||
height: f64)
|
||||
-> Fallible<Root<DOMRectReadOnly>> {
|
||||
Ok(DOMRectReadOnly::new(global, x, y, width, height))
|
||||
}
|
||||
|
||||
@ -79,24 +90,40 @@ impl DOMRectReadOnlyMethods for DOMRectReadOnly {
|
||||
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-top
|
||||
fn Top(&self) -> f64 {
|
||||
let height = self.height.get();
|
||||
if height >= 0f64 { self.y.get() } else { self.y.get() + height }
|
||||
if height >= 0f64 {
|
||||
self.y.get()
|
||||
} else {
|
||||
self.y.get() + height
|
||||
}
|
||||
}
|
||||
|
||||
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-right
|
||||
fn Right(&self) -> f64 {
|
||||
let width = self.width.get();
|
||||
if width < 0f64 { self.x.get() } else { self.x.get() + width }
|
||||
if width < 0f64 {
|
||||
self.x.get()
|
||||
} else {
|
||||
self.x.get() + width
|
||||
}
|
||||
}
|
||||
|
||||
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-bottom
|
||||
fn Bottom(&self) -> f64 {
|
||||
let height = self.height.get();
|
||||
if height < 0f64 { self.y.get() } else { self.y.get() + height }
|
||||
if height < 0f64 {
|
||||
self.y.get()
|
||||
} else {
|
||||
self.y.get() + height
|
||||
}
|
||||
}
|
||||
|
||||
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-left
|
||||
fn Left(&self) -> f64 {
|
||||
let width = self.width.get();
|
||||
if width >= 0f64 { self.x.get() } else { self.x.get() + width }
|
||||
if width >= 0f64 {
|
||||
self.x.get()
|
||||
} else {
|
||||
self.x.get() + width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ impl DOMStringMap {
|
||||
pub fn new(element: &HTMLElement) -> Root<DOMStringMap> {
|
||||
let window = window_from_node(element);
|
||||
reflect_dom_object(box DOMStringMap::new_inherited(element),
|
||||
GlobalRef::Window(window.r()), DOMStringMapBinding::Wrap)
|
||||
GlobalRef::Window(window.r()),
|
||||
DOMStringMapBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ impl DOMTokenList {
|
||||
match token {
|
||||
"" => Err(Error::Syntax),
|
||||
slice if slice.find(HTML_SPACE_CHARACTERS).is_some() => Err(Error::InvalidCharacter),
|
||||
slice => Ok(Atom::from_slice(slice))
|
||||
slice => Ok(Atom::from_slice(slice)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,9 +99,7 @@ impl DOMTokenListMethods for DOMTokenList {
|
||||
let mut atoms = self.element.get_tokenlist_attribute(&self.local_name);
|
||||
for token in &tokens {
|
||||
let token = try!(self.check_token_exceptions(&token));
|
||||
atoms.iter().position(|atom| *atom == token).map(|index| {
|
||||
atoms.remove(index)
|
||||
});
|
||||
atoms.iter().position(|atom| *atom == token).map(|index| atoms.remove(index));
|
||||
}
|
||||
self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms);
|
||||
Ok(())
|
||||
@ -127,7 +125,7 @@ impl DOMTokenListMethods for DOMTokenList {
|
||||
self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms);
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ impl Element {
|
||||
local_name: Atom::from_slice(&local_name),
|
||||
namespace: namespace,
|
||||
prefix: prefix,
|
||||
attrs: DOMRefCell::new(vec!()),
|
||||
attrs: DOMRefCell::new(vec![]),
|
||||
id_attribute: DOMRefCell::new(None),
|
||||
style_attribute: DOMRefCell::new(None),
|
||||
attr_list: Default::default(),
|
||||
@ -249,9 +249,8 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||
#[allow(unsafe_code)]
|
||||
#[inline]
|
||||
unsafe fn get_classes_for_layout(&self) -> Option<&'static [Atom]> {
|
||||
get_attr_for_layout(&*self.unsafe_get(), &ns!(""), &atom!("class")).map(|attr| {
|
||||
attr.value_tokens_forever().unwrap()
|
||||
})
|
||||
get_attr_for_layout(&*self.unsafe_get(), &ns!(""), &atom!("class"))
|
||||
.map(|attr| attr.value_tokens_forever().unwrap())
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
@ -259,8 +258,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||
where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
|
||||
{
|
||||
#[inline]
|
||||
fn from_declaration(rule: PropertyDeclaration)
|
||||
-> DeclarationBlock<Vec<PropertyDeclaration>> {
|
||||
fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock<Vec<PropertyDeclaration>> {
|
||||
DeclarationBlock::from_declarations(Arc::new(vec![rule]))
|
||||
}
|
||||
|
||||
@ -373,15 +371,14 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||
s => Some(s as i32),
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(size) = size {
|
||||
let value = specified::Length::ServoCharacterWidth(
|
||||
specified::CharacterWidth(size));
|
||||
let value = specified::Length::ServoCharacterWidth(specified::CharacterWidth(size));
|
||||
hints.push(from_declaration(
|
||||
PropertyDeclaration::Width(DeclaredValue::Value(
|
||||
specified::LengthOrPercentageOrAuto::Length(value)))));
|
||||
@ -521,7 +518,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn html_element_in_html_document_for_layout(&self) -> bool {
|
||||
if (*self.unsafe_get()).namespace != ns!(HTML) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
self.upcast::<Node>().owner_doc_for_layout().is_html_document_for_layout()
|
||||
}
|
||||
@ -692,9 +689,9 @@ impl Element {
|
||||
}
|
||||
|
||||
let (important, normal) = if style_priority == StylePriority::Important {
|
||||
(vec!(property_decl), vec!())
|
||||
(vec![property_decl], vec![])
|
||||
} else {
|
||||
(vec!(), vec!(property_decl))
|
||||
(vec![], vec![property_decl])
|
||||
};
|
||||
|
||||
*inline_declarations = Some(PropertyDeclarationBlock {
|
||||
@ -703,7 +700,9 @@ impl Element {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_inline_style_property_priority(&self, properties: &[&str], style_priority: StylePriority) {
|
||||
pub fn set_inline_style_property_priority(&self,
|
||||
properties: &[&str],
|
||||
style_priority: StylePriority) {
|
||||
let mut inline_declarations = self.style_attribute().borrow_mut();
|
||||
if let &mut Some(ref mut declarations) = &mut *inline_declarations {
|
||||
let (from, to) = if style_priority == StylePriority::Important {
|
||||
@ -729,7 +728,9 @@ impl Element {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_inline_style_declaration(&self, property: &Atom) -> Option<Ref<PropertyDeclaration>> {
|
||||
pub fn get_inline_style_declaration(&self,
|
||||
property: &Atom)
|
||||
-> Option<Ref<PropertyDeclaration>> {
|
||||
Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| {
|
||||
inline_declarations.as_ref().and_then(|declarations| {
|
||||
declarations.normal
|
||||
@ -740,7 +741,8 @@ impl Element {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_important_inline_style_declaration(&self, property: &Atom)
|
||||
pub fn get_important_inline_style_declaration(&self,
|
||||
property: &Atom)
|
||||
-> Option<Ref<PropertyDeclaration>> {
|
||||
Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| {
|
||||
inline_declarations.as_ref().and_then(|declarations| {
|
||||
@ -753,10 +755,11 @@ impl Element {
|
||||
|
||||
pub fn serialize(&self, traversal_scope: TraversalScope) -> Fallible<DOMString> {
|
||||
let mut writer = vec![];
|
||||
match serialize(&mut writer, &self.upcast::<Node>(),
|
||||
match serialize(&mut writer,
|
||||
&self.upcast::<Node>(),
|
||||
SerializeOpts {
|
||||
traversal_scope: traversal_scope,
|
||||
.. Default::default()
|
||||
..Default::default()
|
||||
}) {
|
||||
// FIXME(ajeffrey): Directly convert UTF8 to DOMString
|
||||
Ok(()) => Ok(DOMString::from(String::from_utf8(writer).unwrap())),
|
||||
@ -766,7 +769,10 @@ impl Element {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#root-element
|
||||
pub fn get_root_element(&self) -> Root<Element> {
|
||||
self.upcast::<Node>().inclusive_ancestors().filter_map(Root::downcast).last()
|
||||
self.upcast::<Node>()
|
||||
.inclusive_ancestors()
|
||||
.filter_map(Root::downcast)
|
||||
.last()
|
||||
.expect("We know inclusive_ancestors will return `self` which is an element")
|
||||
}
|
||||
|
||||
@ -816,7 +822,7 @@ impl Element {
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
|
||||
true
|
||||
}
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -834,7 +840,7 @@ impl Element {
|
||||
// an optgroup element that has a disabled attribute
|
||||
// a menuitem element that has a disabled attribute
|
||||
// a fieldset element that is a disabled fieldset
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -850,7 +856,13 @@ impl Element {
|
||||
self.will_mutate_attr();
|
||||
let window = window_from_node(self);
|
||||
let in_empty_ns = namespace == ns!("");
|
||||
let attr = Attr::new(&window, local_name, value, name, namespace, prefix, Some(self));
|
||||
let attr = Attr::new(&window,
|
||||
local_name,
|
||||
value,
|
||||
name,
|
||||
namespace,
|
||||
prefix,
|
||||
Some(self));
|
||||
self.attrs.borrow_mut().push(JS::from_rooted(&attr));
|
||||
if in_empty_ns {
|
||||
vtable_for(self.upcast()).attribute_mutated(&attr, AttributeMutation::Set(None));
|
||||
@ -858,9 +870,11 @@ impl Element {
|
||||
}
|
||||
|
||||
pub fn get_attribute(&self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
|
||||
self.attrs.borrow().iter().find(|attr| {
|
||||
attr.local_name() == local_name && attr.namespace() == namespace
|
||||
}).map(|js| Root::from_ref(&**js))
|
||||
self.attrs
|
||||
.borrow()
|
||||
.iter()
|
||||
.find(|attr| attr.local_name() == local_name && attr.namespace() == namespace)
|
||||
.map(|js| Root::from_ref(&**js))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
|
||||
@ -874,8 +888,10 @@ impl Element {
|
||||
value: DOMString,
|
||||
prefix: Option<Atom>) {
|
||||
// Don't set if the attribute already exists, so we can handle add_attrs_if_missing
|
||||
if self.attrs.borrow().iter()
|
||||
.any(|a| *a.local_name() == qname.local && *a.namespace() == qname.ns) {
|
||||
if self.attrs
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|a| *a.local_name() == qname.local && *a.namespace() == qname.ns) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -894,9 +910,12 @@ impl Element {
|
||||
assert!(&**name == name.to_ascii_lowercase());
|
||||
assert!(!name.contains(":"));
|
||||
|
||||
self.set_first_matching_attribute(
|
||||
name.clone(), value, name.clone(), ns!(""), None,
|
||||
|attr| attr.local_name() == name);
|
||||
self.set_first_matching_attribute(name.clone(),
|
||||
value,
|
||||
name.clone(),
|
||||
ns!(""),
|
||||
None,
|
||||
|attr| attr.local_name() == name);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#attr-data-*
|
||||
@ -910,9 +929,14 @@ impl Element {
|
||||
// Steps 2-5.
|
||||
let name = Atom::from_slice(&name);
|
||||
let value = self.parse_attribute(&ns!(""), &name, value);
|
||||
self.set_first_matching_attribute(
|
||||
name.clone(), value, name.clone(), ns!(""), None,
|
||||
|attr| *attr.name() == name && *attr.namespace() == ns!(""));
|
||||
self.set_first_matching_attribute(name.clone(),
|
||||
value,
|
||||
name.clone(),
|
||||
ns!(""),
|
||||
None,
|
||||
|attr| {
|
||||
*attr.name() == name && *attr.namespace() == ns!("")
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -923,10 +947,13 @@ impl Element {
|
||||
namespace: Namespace,
|
||||
prefix: Option<Atom>,
|
||||
find: F)
|
||||
where F: Fn(&Attr)
|
||||
-> bool {
|
||||
let attr = self.attrs.borrow().iter()
|
||||
.find(|attr| find(&attr)).map(|js| Root::from_ref(&**js));
|
||||
where F: Fn(&Attr) -> bool
|
||||
{
|
||||
let attr = self.attrs
|
||||
.borrow()
|
||||
.iter()
|
||||
.find(|attr| find(&attr))
|
||||
.map(|js| Root::from_ref(&**js));
|
||||
if let Some(attr) = attr {
|
||||
attr.set_value(value, self);
|
||||
} else {
|
||||
@ -934,8 +961,11 @@ impl Element {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn parse_attribute(&self, namespace: &Namespace, local_name: &Atom,
|
||||
value: DOMString) -> AttrValue {
|
||||
pub fn parse_attribute(&self,
|
||||
namespace: &Namespace,
|
||||
local_name: &Atom,
|
||||
value: DOMString)
|
||||
-> AttrValue {
|
||||
if *namespace == ns!("") {
|
||||
vtable_for(self.upcast()).parse_plain_attribute(local_name, value)
|
||||
} else {
|
||||
@ -943,8 +973,7 @@ impl Element {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_attribute(&self, namespace: &Namespace, local_name: &Atom)
|
||||
-> Option<Root<Attr>> {
|
||||
pub fn remove_attribute(&self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
|
||||
self.remove_first_matching_attribute(|attr| {
|
||||
attr.namespace() == namespace && attr.local_name() == local_name
|
||||
})
|
||||
@ -973,13 +1002,15 @@ impl Element {
|
||||
|
||||
pub fn has_class(&self, name: &Atom) -> bool {
|
||||
let quirks_mode = document_from_node(self).quirks_mode();
|
||||
let is_equal = |lhs: &Atom, rhs: &Atom| match quirks_mode {
|
||||
NoQuirks | LimitedQuirks => lhs == rhs,
|
||||
Quirks => lhs.eq_ignore_ascii_case(&rhs)
|
||||
let is_equal = |lhs: &Atom, rhs: &Atom| {
|
||||
match quirks_mode {
|
||||
NoQuirks | LimitedQuirks => lhs == rhs,
|
||||
Quirks => lhs.eq_ignore_ascii_case(&rhs),
|
||||
}
|
||||
};
|
||||
self.get_attribute(&ns!(""), &atom!("class")).map(|attr| {
|
||||
attr.value().as_tokens().iter().any(|atom| is_equal(name, atom))
|
||||
}).unwrap_or(false)
|
||||
self.get_attribute(&ns!(""), &atom!("class"))
|
||||
.map(|attr| attr.value().as_tokens().iter().any(|atom| is_equal(name, atom)))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn set_atomic_attribute(&self, local_name: &Atom, value: DOMString) {
|
||||
@ -990,13 +1021,16 @@ impl Element {
|
||||
|
||||
pub fn has_attribute(&self, local_name: &Atom) -> bool {
|
||||
assert!(local_name.bytes().all(|b| b.to_ascii_lowercase() == b));
|
||||
self.attrs.borrow().iter().any(|attr| {
|
||||
attr.local_name() == local_name && attr.namespace() == &ns!("")
|
||||
})
|
||||
self.attrs
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|attr| attr.local_name() == local_name && attr.namespace() == &ns!(""))
|
||||
}
|
||||
|
||||
pub fn set_bool_attribute(&self, local_name: &Atom, value: bool) {
|
||||
if self.has_attribute(local_name) == value { return; }
|
||||
if self.has_attribute(local_name) == value {
|
||||
return;
|
||||
}
|
||||
if value {
|
||||
self.set_string_attribute(local_name, DOMString::new());
|
||||
} else {
|
||||
@ -1016,7 +1050,7 @@ impl Element {
|
||||
// XXXManishearth this doesn't handle `javascript:` urls properly
|
||||
match UrlParser::new().base_url(&base).parse(&url) {
|
||||
Ok(parsed) => DOMString::from(parsed.serialize()),
|
||||
Err(_) => DOMString::from("")
|
||||
Err(_) => DOMString::from(""),
|
||||
}
|
||||
}
|
||||
pub fn set_url_attribute(&self, local_name: &Atom, value: DOMString) {
|
||||
@ -1026,7 +1060,7 @@ impl Element {
|
||||
pub fn get_string_attribute(&self, local_name: &Atom) -> DOMString {
|
||||
match self.get_attribute(&ns!(""), local_name) {
|
||||
Some(x) => x.Value(),
|
||||
None => DOMString::new()
|
||||
None => DOMString::new(),
|
||||
}
|
||||
}
|
||||
pub fn set_string_attribute(&self, local_name: &Atom, value: DOMString) {
|
||||
@ -1054,16 +1088,13 @@ impl Element {
|
||||
}
|
||||
|
||||
pub fn get_uint_attribute(&self, local_name: &Atom, default: u32) -> u32 {
|
||||
assert!(local_name.chars().all(|ch| {
|
||||
!ch.is_ascii() || ch.to_ascii_lowercase() == ch
|
||||
}));
|
||||
assert!(local_name.chars().all(|ch| !ch.is_ascii() || ch.to_ascii_lowercase() == ch));
|
||||
let attribute = self.get_attribute(&ns!(""), local_name);
|
||||
match attribute {
|
||||
Some(ref attribute) => {
|
||||
match *attribute.value() {
|
||||
AttrValue::UInt(_, value) => value,
|
||||
_ => panic!("Expected an AttrValue::UInt: \
|
||||
implement parse_plain_attribute"),
|
||||
_ => panic!("Expected an AttrValue::UInt: implement parse_plain_attribute"),
|
||||
}
|
||||
}
|
||||
None => default,
|
||||
@ -1072,7 +1103,8 @@ impl Element {
|
||||
pub fn set_uint_attribute(&self, local_name: &Atom, value: u32) {
|
||||
assert!(&**local_name == local_name.to_ascii_lowercase());
|
||||
// FIXME(ajeffrey): Directly convert u32 to DOMString
|
||||
self.set_attribute(local_name, AttrValue::UInt(DOMString::from(value.to_string()), value));
|
||||
self.set_attribute(local_name,
|
||||
AttrValue::UInt(DOMString::from(value.to_string()), value));
|
||||
}
|
||||
|
||||
pub fn will_mutate_attr(&self) {
|
||||
@ -1146,15 +1178,16 @@ impl ElementMethods for Element {
|
||||
// https://dom.spec.whatwg.org/#dom-element-getattribute
|
||||
fn GetAttribute(&self, name: DOMString) -> Option<DOMString> {
|
||||
self.GetAttributeNode(name)
|
||||
.map(|s| s.Value())
|
||||
.map(|s| s.Value())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-getattributens
|
||||
fn GetAttributeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
local_name: DOMString) -> Option<DOMString> {
|
||||
local_name: DOMString)
|
||||
-> Option<DOMString> {
|
||||
self.GetAttributeNodeNS(namespace, local_name)
|
||||
.map(|attr| attr.Value())
|
||||
.map(|attr| attr.Value())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-getattributenode
|
||||
@ -1164,16 +1197,15 @@ impl ElementMethods for Element {
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-getattributenodens
|
||||
fn GetAttributeNodeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
local_name: DOMString) -> Option<Root<Attr>> {
|
||||
namespace: Option<DOMString>,
|
||||
local_name: DOMString)
|
||||
-> Option<Root<Attr>> {
|
||||
let namespace = &namespace_from_domstring(namespace);
|
||||
self.get_attribute(namespace, &Atom::from_slice(&local_name))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-setattribute
|
||||
fn SetAttribute(&self,
|
||||
name: DOMString,
|
||||
value: DOMString) -> ErrorResult {
|
||||
fn SetAttribute(&self, name: DOMString, value: DOMString) -> ErrorResult {
|
||||
// Step 1.
|
||||
if xml_name_type(&name) == InvalidXMLName {
|
||||
return Err(Error::InvalidCharacter);
|
||||
@ -1212,9 +1244,7 @@ impl ElementMethods for Element {
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-removeattributens
|
||||
fn RemoveAttributeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
local_name: DOMString) {
|
||||
fn RemoveAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) {
|
||||
let namespace = namespace_from_domstring(namespace);
|
||||
let local_name = Atom::from_slice(&local_name);
|
||||
self.remove_attribute(&namespace, &local_name);
|
||||
@ -1226,9 +1256,7 @@ impl ElementMethods for Element {
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-hasattributens
|
||||
fn HasAttributeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
local_name: DOMString) -> bool {
|
||||
fn HasAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> bool {
|
||||
self.GetAttributeNS(namespace, local_name).is_some()
|
||||
}
|
||||
|
||||
@ -1239,8 +1267,10 @@ impl ElementMethods for Element {
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens
|
||||
fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>,
|
||||
localname: DOMString) -> Root<HTMLCollection> {
|
||||
fn GetElementsByTagNameNS(&self,
|
||||
maybe_ns: Option<DOMString>,
|
||||
localname: DOMString)
|
||||
-> Root<HTMLCollection> {
|
||||
let window = window_from_node(self);
|
||||
HTMLCollection::by_tag_name_ns(window.r(), self.upcast(), localname, maybe_ns)
|
||||
}
|
||||
@ -1298,7 +1328,7 @@ impl ElementMethods for Element {
|
||||
|
||||
/// https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML
|
||||
fn GetInnerHTML(&self) -> Fallible<DOMString> {
|
||||
//XXX TODO: XML case
|
||||
// XXX TODO: XML case
|
||||
self.serialize(ChildrenOnly)
|
||||
}
|
||||
|
||||
@ -1548,7 +1578,9 @@ impl VirtualMethods for Element {
|
||||
s.bind_to_tree(tree_in_doc);
|
||||
}
|
||||
|
||||
if !tree_in_doc { return; }
|
||||
if !tree_in_doc {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(ref value) = *self.id_attribute.borrow() {
|
||||
let doc = document_from_node(self);
|
||||
@ -1561,7 +1593,9 @@ impl VirtualMethods for Element {
|
||||
s.unbind_from_tree(tree_in_doc);
|
||||
}
|
||||
|
||||
if !tree_in_doc { return; }
|
||||
if !tree_in_doc {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(ref value) = *self.id_attribute.borrow() {
|
||||
let doc = document_from_node(self);
|
||||
@ -1729,9 +1763,9 @@ impl Element {
|
||||
};
|
||||
element.and_then(|elem| {
|
||||
if elem.is_instance_activatable() {
|
||||
Some(elem)
|
||||
Some(elem)
|
||||
} else {
|
||||
None
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1753,7 +1787,7 @@ impl Element {
|
||||
for node in node.ancestors() {
|
||||
if let Some(node) = node.downcast::<Element>() {
|
||||
if node.as_maybe_activatable().is_some() {
|
||||
return Some(Root::from_ref(node))
|
||||
return Some(Root::from_ref(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1795,10 +1829,14 @@ impl Element {
|
||||
}
|
||||
}
|
||||
// Step 6
|
||||
None => { event.fire(target); }
|
||||
None => {
|
||||
event.fire(target);
|
||||
}
|
||||
},
|
||||
// Step 6
|
||||
None => { event.fire(target); }
|
||||
None => {
|
||||
event.fire(target);
|
||||
}
|
||||
}
|
||||
// Step 7
|
||||
self.set_click_in_progress(false);
|
||||
@ -1811,7 +1849,7 @@ impl Element {
|
||||
pub fn set_state(&self, which: ElementState, value: bool) {
|
||||
let mut state = self.state.get();
|
||||
if state.contains(which) == value {
|
||||
return
|
||||
return;
|
||||
}
|
||||
let node = self.upcast::<Node>();
|
||||
node.owner_doc().element_state_will_change(self);
|
||||
@ -1866,25 +1904,32 @@ impl Element {
|
||||
impl Element {
|
||||
pub fn check_ancestors_disabled_state_for_form_control(&self) {
|
||||
let node = self.upcast::<Node>();
|
||||
if self.get_disabled_state() { return; }
|
||||
if self.get_disabled_state() {
|
||||
return;
|
||||
}
|
||||
for ancestor in node.ancestors() {
|
||||
let ancestor = ancestor;
|
||||
let ancestor = ancestor.r();
|
||||
if !ancestor.is::<HTMLFieldSetElement>() { continue; }
|
||||
if !ancestor.downcast::<Element>().unwrap().get_disabled_state() { continue; }
|
||||
if !ancestor.is::<HTMLFieldSetElement>() {
|
||||
continue;
|
||||
}
|
||||
if !ancestor.downcast::<Element>().unwrap().get_disabled_state() {
|
||||
continue;
|
||||
}
|
||||
if ancestor.is_parent_of(node) {
|
||||
self.set_disabled_state(true);
|
||||
self.set_enabled_state(false);
|
||||
return;
|
||||
}
|
||||
match ancestor.children()
|
||||
.find(|child| child.is::<HTMLLegendElement>())
|
||||
{
|
||||
.find(|child| child.is::<HTMLLegendElement>()) {
|
||||
Some(ref legend) => {
|
||||
// XXXabinader: should we save previous ancestor to avoid this iteration?
|
||||
if node.ancestors().any(|ancestor| ancestor == *legend) { continue; }
|
||||
if node.ancestors().any(|ancestor| ancestor == *legend) {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
None => ()
|
||||
None => (),
|
||||
}
|
||||
self.set_disabled_state(true);
|
||||
self.set_enabled_state(false);
|
||||
@ -1893,10 +1938,13 @@ impl Element {
|
||||
}
|
||||
|
||||
pub fn check_parent_disabled_state_for_option(&self) {
|
||||
if self.get_disabled_state() { return; }
|
||||
if self.get_disabled_state() {
|
||||
return;
|
||||
}
|
||||
let node = self.upcast::<Node>();
|
||||
if let Some(ref parent) = node.GetParentNode() {
|
||||
if parent.is::<HTMLOptGroupElement>() && parent.downcast::<Element>().unwrap().get_disabled_state() {
|
||||
if parent.is::<HTMLOptGroupElement>() &&
|
||||
parent.downcast::<Element>().unwrap().get_disabled_state() {
|
||||
self.set_disabled_state(true);
|
||||
self.set_enabled_state(false);
|
||||
}
|
||||
@ -1918,7 +1966,7 @@ pub enum AttributeMutation<'a> {
|
||||
|
||||
/// The attribute is removed.
|
||||
/// https://dom.spec.whatwg.org/#attribute-is-removed
|
||||
Removed
|
||||
Removed,
|
||||
}
|
||||
|
||||
impl<'a> AttributeMutation<'a> {
|
||||
|
Loading…
Reference in New Issue
Block a user