Format script component

This commit is contained in:
chansuke 2018-09-18 23:24:15 +09:00 committed by Josh Matthews
parent 2ca7a13473
commit c37a345dc9
357 changed files with 25485 additions and 18076 deletions

View file

@ -35,7 +35,7 @@ pub enum BodyType {
FormData,
Json,
Text,
ArrayBuffer
ArrayBuffer,
}
pub enum FetchedData {
@ -44,7 +44,7 @@ pub enum FetchedData {
BlobData(DomRoot<Blob>),
FormData(DomRoot<FormData>),
ArrayBuffer(RootedTraceableBox<Heap<*mut JSObject>>),
JSException(RootedTraceableBox<Heap<JSVal>>)
JSException(RootedTraceableBox<Heap<JSVal>>),
}
// https://fetch.spec.whatwg.org/#concept-body-consume-body
@ -72,19 +72,19 @@ pub fn consume_body<T: BodyOperations + DomObject>(object: &T, body_type: BodyTy
// https://fetch.spec.whatwg.org/#concept-body-consume-body
#[allow(unrooted_must_root)]
pub fn consume_body_with_promise<T: BodyOperations + DomObject>(object: &T,
pub fn consume_body_with_promise<T: BodyOperations + DomObject>(
object: &T,
body_type: BodyType,
promise: &Promise) {
promise: &Promise,
) {
// Step 5
let body = match object.take_body() {
Some(body) => body,
None => return,
};
let pkg_data_results = run_package_data_algorithm(object,
body,
body_type,
object.get_mime_type());
let pkg_data_results =
run_package_data_algorithm(object, body, body_type, object.get_mime_type());
match pkg_data_results {
Ok(results) => {
@ -103,11 +103,12 @@ pub fn consume_body_with_promise<T: BodyOperations + DomObject>(object: &T,
// https://fetch.spec.whatwg.org/#concept-body-package-data
#[allow(unsafe_code)]
fn run_package_data_algorithm<T: BodyOperations + DomObject>(object: &T,
fn run_package_data_algorithm<T: BodyOperations + DomObject>(
object: &T,
bytes: Vec<u8>,
body_type: BodyType,
mime_type: Ref<Vec<u8>>)
-> Fallible<FetchedData> {
mime_type: Ref<Vec<u8>>,
) -> Fallible<FetchedData> {
let global = object.global();
let cx = global.get_cx();
let mime = &*mime_type;
@ -116,40 +117,45 @@ fn run_package_data_algorithm<T: BodyOperations + DomObject>(object: &T,
BodyType::Json => run_json_data_algorithm(cx, bytes),
BodyType::Blob => run_blob_data_algorithm(&global, bytes, mime),
BodyType::FormData => run_form_data_algorithm(&global, bytes, mime),
BodyType::ArrayBuffer => unsafe {
run_array_buffer_data_algorithm(cx, bytes)
}
BodyType::ArrayBuffer => unsafe { run_array_buffer_data_algorithm(cx, bytes) },
}
}
fn run_text_data_algorithm(bytes: Vec<u8>) -> Fallible<FetchedData> {
Ok(FetchedData::Text(String::from_utf8_lossy(&bytes).into_owned()))
Ok(FetchedData::Text(
String::from_utf8_lossy(&bytes).into_owned(),
))
}
#[allow(unsafe_code)]
fn run_json_data_algorithm(cx: *mut JSContext,
bytes: Vec<u8>) -> Fallible<FetchedData> {
fn run_json_data_algorithm(cx: *mut JSContext, bytes: Vec<u8>) -> Fallible<FetchedData> {
let json_text = String::from_utf8_lossy(&bytes);
let json_text: Vec<u16> = json_text.encode_utf16().collect();
rooted!(in(cx) let mut rval = UndefinedValue());
unsafe {
if !JS_ParseJSON(cx,
if !JS_ParseJSON(
cx,
json_text.as_ptr(),
json_text.len() as u32,
rval.handle_mut()) {
rval.handle_mut(),
) {
rooted!(in(cx) let mut exception = UndefinedValue());
assert!(JS_GetPendingException(cx, exception.handle_mut()));
JS_ClearPendingException(cx);
return Ok(FetchedData::JSException(RootedTraceableBox::from_box(Heap::boxed(exception.get()))));
return Ok(FetchedData::JSException(RootedTraceableBox::from_box(
Heap::boxed(exception.get()),
)));
}
let rooted_heap = RootedTraceableBox::from_box(Heap::boxed(rval.get()));
Ok(FetchedData::Json(rooted_heap))
}
}
fn run_blob_data_algorithm(root: &GlobalScope,
fn run_blob_data_algorithm(
root: &GlobalScope,
bytes: Vec<u8>,
mime: &[u8]) -> Fallible<FetchedData> {
mime: &[u8],
) -> Fallible<FetchedData> {
let mime_string = if let Ok(s) = String::from_utf8(mime.to_vec()) {
s
} else {
@ -159,14 +165,19 @@ fn run_blob_data_algorithm(root: &GlobalScope,
Ok(FetchedData::BlobData(blob))
}
fn run_form_data_algorithm(root: &GlobalScope, bytes: Vec<u8>, mime: &[u8]) -> Fallible<FetchedData> {
fn run_form_data_algorithm(
root: &GlobalScope,
bytes: Vec<u8>,
mime: &[u8],
) -> Fallible<FetchedData> {
let mime_str = if let Ok(s) = str::from_utf8(mime) {
s
} else {
""
};
let mime: Mime = mime_str.parse().map_err(
|_| Error::Type("Inappropriate MIME-type for Body".to_string()))?;
let mime: Mime = mime_str
.parse()
.map_err(|_| Error::Type("Inappropriate MIME-type for Body".to_string()))?;
match mime {
// TODO
// ... Parser for Mime(TopLevel::Multipart, SubLevel::FormData, _)
@ -184,9 +195,13 @@ fn run_form_data_algorithm(root: &GlobalScope, bytes: Vec<u8>, mime: &[u8]) -> F
}
#[allow(unsafe_code)]
unsafe fn run_array_buffer_data_algorithm(cx: *mut JSContext, bytes: Vec<u8>) -> Fallible<FetchedData> {
unsafe fn run_array_buffer_data_algorithm(
cx: *mut JSContext,
bytes: Vec<u8>,
) -> Fallible<FetchedData> {
rooted!(in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
let arraybuffer = ArrayBuffer::create(cx, CreateWith::Slice(&bytes), array_buffer_ptr.handle_mut());
let arraybuffer =
ArrayBuffer::create(cx, CreateWith::Slice(&bytes), array_buffer_ptr.handle_mut());
if arraybuffer.is_err() {
return Err(Error::JSFailed);
}

View file

@ -31,22 +31,34 @@ fn main() {
build.generator("Ninja");
// because we're using ninja, we need to explicitly set these
// to VC++, otherwise it'll try to use cc
build.define("CMAKE_C_COMPILER", "cl.exe")
build
.define("CMAKE_C_COMPILER", "cl.exe")
.define("CMAKE_CXX_COMPILER", "cl.exe");
// We have to explicitly specify the full path to link.exe,
// for reasons that I don't understand. If we just give
// link.exe, it tries to use script-*/out/link.exe, which of
// course does not exist.
let link = std::process::Command::new("where").arg("link.exe").output().unwrap();
let link_path: Vec<&str> = std::str::from_utf8(&link.stdout).unwrap().split("\r\n").collect();
let link = std::process::Command::new("where")
.arg("link.exe")
.output()
.unwrap();
let link_path: Vec<&str> = std::str::from_utf8(&link.stdout)
.unwrap()
.split("\r\n")
.collect();
build.define("CMAKE_LINKER", link_path[0]);
}
build.build();
println!("Binding generation completed in {}s", start.elapsed().as_secs());
println!(
"Binding generation completed in {}s",
start.elapsed().as_secs()
);
let json = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("build").join("InterfaceObjectMapData.json");
let json = PathBuf::from(env::var_os("OUT_DIR").unwrap())
.join("build")
.join("InterfaceObjectMapData.json");
let json: Value = serde_json::from_reader(File::open(&json).unwrap()).unwrap();
let mut map = phf_codegen::Map::new();
for (key, value) in json.as_object().unwrap() {
@ -54,7 +66,10 @@ fn main() {
}
let phf = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("InterfaceObjectMapPhf.rs");
let mut phf = File::create(&phf).unwrap();
write!(&mut phf, "pub static MAP: phf::Map<&'static [u8], unsafe fn(*mut JSContext, HandleObject)> = ").unwrap();
write!(
&mut phf,
"pub static MAP: phf::Map<&'static [u8], unsafe fn(*mut JSContext, HandleObject)> = "
).unwrap();
map.build(&mut phf).unwrap();
write!(&mut phf, ";\n").unwrap();
}

View file

@ -32,7 +32,6 @@ use std::str;
use style::properties::longhands::{margin_bottom, margin_left, margin_right, margin_top};
use uuid::Uuid;
#[allow(unsafe_code)]
pub fn handle_evaluate_js(global: &GlobalScope, eval: String, reply: IpcSender<EvaluateJSReply>) {
// global.get_cx() returns a valid `JSContext` pointer, so this is safe.
@ -48,8 +47,11 @@ pub fn handle_evaluate_js(global: &GlobalScope, eval: String, reply: IpcSender<E
} else if rval.is_boolean() {
EvaluateJSReply::BooleanValue(rval.to_boolean())
} else if rval.is_double() || rval.is_int32() {
EvaluateJSReply::NumberValue(
match FromJSValConvertible::from_jsval(cx, rval.handle(), ()) {
EvaluateJSReply::NumberValue(match FromJSValConvertible::from_jsval(
cx,
rval.handle(),
(),
) {
Ok(ConversionResult::Success(v)) => v,
_ => unreachable!(),
})
@ -73,65 +75,84 @@ pub fn handle_evaluate_js(global: &GlobalScope, eval: String, reply: IpcSender<E
reply.send(result).unwrap();
}
pub fn handle_get_root_node(documents: &Documents, pipeline: PipelineId, reply: IpcSender<Option<NodeInfo>>) {
let info = documents.find_document(pipeline)
pub fn handle_get_root_node(
documents: &Documents,
pipeline: PipelineId,
reply: IpcSender<Option<NodeInfo>>,
) {
let info = documents
.find_document(pipeline)
.map(|document| document.upcast::<Node>().summarize());
reply.send(info).unwrap();
}
pub fn handle_get_document_element(documents: &Documents,
pub fn handle_get_document_element(
documents: &Documents,
pipeline: PipelineId,
reply: IpcSender<Option<NodeInfo>>) {
let info = documents.find_document(pipeline)
reply: IpcSender<Option<NodeInfo>>,
) {
let info = documents
.find_document(pipeline)
.and_then(|document| document.GetDocumentElement())
.map(|element| element.upcast::<Node>().summarize());
reply.send(info).unwrap();
}
fn find_node_by_unique_id(documents: &Documents,
fn find_node_by_unique_id(
documents: &Documents,
pipeline: PipelineId,
node_id: &str)
-> Option<DomRoot<Node>> {
documents.find_document(pipeline).and_then(|document|
document.upcast::<Node>().traverse_preorder().find(|candidate| candidate.unique_id() == node_id)
)
node_id: &str,
) -> Option<DomRoot<Node>> {
documents.find_document(pipeline).and_then(|document| {
document
.upcast::<Node>()
.traverse_preorder()
.find(|candidate| candidate.unique_id() == node_id)
})
}
pub fn handle_get_children(documents: &Documents,
pub fn handle_get_children(
documents: &Documents,
pipeline: PipelineId,
node_id: String,
reply: IpcSender<Option<Vec<NodeInfo>>>) {
reply: IpcSender<Option<Vec<NodeInfo>>>,
) {
match find_node_by_unique_id(documents, pipeline, &*node_id) {
None => return reply.send(None).unwrap(),
Some(parent) => {
let children = parent.children()
.map(|child| child.summarize())
.collect();
let children = parent.children().map(|child| child.summarize()).collect();
reply.send(Some(children)).unwrap();
}
},
};
}
pub fn handle_get_layout(documents: &Documents,
pub fn handle_get_layout(
documents: &Documents,
pipeline: PipelineId,
node_id: String,
reply: IpcSender<Option<ComputedNodeLayout>>) {
reply: IpcSender<Option<ComputedNodeLayout>>,
) {
let node = match find_node_by_unique_id(documents, pipeline, &*node_id) {
None => return reply.send(None).unwrap(),
Some(found_node) => found_node
Some(found_node) => found_node,
};
let elem = node.downcast::<Element>().expect("should be getting layout of element");
let elem = node
.downcast::<Element>()
.expect("should be getting layout of element");
let rect = elem.GetBoundingClientRect();
let width = rect.Width() as f32;
let height = rect.Height() as f32;
let window = window_from_node(&*node);
let elem = node.downcast::<Element>().expect("should be getting layout of element");
let elem = node
.downcast::<Element>()
.expect("should be getting layout of element");
let computed_style = window.GetComputedStyle(elem, None);
reply.send(Some(ComputedNodeLayout {
reply
.send(Some(ComputedNodeLayout {
display: String::from(computed_style.Display()),
position: String::from(computed_style.Position()),
zIndex: String::from(computed_style.ZIndex()),
@ -165,9 +186,11 @@ fn determine_auto_margins(window: &Window, node: &Node) -> AutoMargins {
}
}
pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
pub fn handle_get_cached_messages(
_pipeline_id: PipelineId,
message_types: CachedConsoleMessageTypes,
reply: IpcSender<Vec<CachedConsoleMessage>>) {
reply: IpcSender<Vec<CachedConsoleMessage>>,
) {
// TODO: check the messageTypes against a global Cache for console messages and page exceptions
let mut messages = Vec::new();
if message_types.contains(CachedConsoleMessageTypes::PAGE_ERROR) {
@ -207,22 +230,33 @@ pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
reply.send(messages).unwrap();
}
pub fn handle_modify_attribute(documents: &Documents,
pub fn handle_modify_attribute(
documents: &Documents,
pipeline: PipelineId,
node_id: String,
modifications: Vec<Modification>) {
modifications: Vec<Modification>,
) {
let node = match find_node_by_unique_id(documents, pipeline, &*node_id) {
None => return warn!("node id {} for pipeline id {} is not found", &node_id, &pipeline),
Some(found_node) => found_node
None => {
return warn!(
"node id {} for pipeline id {} is not found",
&node_id, &pipeline
)
},
Some(found_node) => found_node,
};
let elem = node.downcast::<Element>().expect("should be getting layout of element");
let elem = node
.downcast::<Element>()
.expect("should be getting layout of element");
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)),
}
@ -233,34 +267,35 @@ pub fn handle_wants_live_notifications(global: &GlobalScope, send_notifications:
global.set_devtools_wants_updates(send_notifications);
}
pub fn handle_set_timeline_markers(documents: &Documents,
pub fn handle_set_timeline_markers(
documents: &Documents,
pipeline: PipelineId,
marker_types: Vec<TimelineMarkerType>,
reply: IpcSender<Option<TimelineMarker>>) {
reply: IpcSender<Option<TimelineMarker>>,
) {
match documents.find_window(pipeline) {
None => reply.send(None).unwrap(),
Some(window) => window.set_devtools_timeline_markers(marker_types, reply),
}
}
pub fn handle_drop_timeline_markers(documents: &Documents,
pub fn handle_drop_timeline_markers(
documents: &Documents,
pipeline: PipelineId,
marker_types: Vec<TimelineMarkerType>) {
marker_types: Vec<TimelineMarkerType>,
) {
if let Some(window) = documents.find_window(pipeline) {
window.drop_devtools_timeline_markers(marker_types);
}
}
pub fn handle_request_animation_frame(documents: &Documents,
id: PipelineId,
actor_name: String) {
pub fn handle_request_animation_frame(documents: &Documents, id: PipelineId, actor_name: String) {
if let Some(doc) = documents.find_document(id) {
doc.request_animation_frame(AnimationFrameCallback::DevtoolsFramerateTick { actor_name });
}
}
pub fn handle_reload(documents: &Documents,
id: PipelineId) {
pub fn handle_reload(documents: &Documents, id: PipelineId) {
if let Some(win) = documents.find_window(id) {
win.Location().reload_without_origin_check();
}

View file

@ -96,8 +96,10 @@ impl DocumentLoader {
DocumentLoader::new_with_threads(existing.resource_threads.clone(), None)
}
pub fn new_with_threads(resource_threads: ResourceThreads,
initial_load: Option<ServoUrl>) -> DocumentLoader {
pub fn new_with_threads(
resource_threads: ResourceThreads,
initial_load: Option<ServoUrl>,
) -> DocumentLoader {
debug!("Initial blocking load {:?}.", initial_load);
let initial_loads = initial_load.into_iter().map(LoadType::PageSource).collect();
@ -105,7 +107,7 @@ impl DocumentLoader {
resource_threads: resource_threads,
blocking_loads: initial_loads,
events_inhibited: false,
cancellers: Vec::new()
cancellers: Vec::new(),
}
}
@ -118,35 +120,55 @@ impl DocumentLoader {
/// Add a load to the list of blocking loads.
fn add_blocking_load(&mut self, load: LoadType) {
debug!("Adding blocking load {:?} ({}).", load, self.blocking_loads.len());
debug!(
"Adding blocking load {:?} ({}).",
load,
self.blocking_loads.len()
);
self.blocking_loads.push(load);
}
/// Initiate a new fetch.
pub fn fetch_async(&mut self,
pub fn fetch_async(
&mut self,
load: LoadType,
request: RequestInit,
fetch_target: IpcSender<FetchResponseMsg>) {
fetch_target: IpcSender<FetchResponseMsg>,
) {
self.add_blocking_load(load);
self.fetch_async_background(request, fetch_target);
}
/// Initiate a new fetch that does not block the document load event.
pub fn fetch_async_background(&mut self,
pub fn fetch_async_background(
&mut self,
request: RequestInit,
fetch_target: IpcSender<FetchResponseMsg>) {
fetch_target: IpcSender<FetchResponseMsg>,
) {
let mut canceller = FetchCanceller::new();
let cancel_receiver = canceller.initialize();
self.cancellers.push(canceller);
self.resource_threads.sender().send(
CoreResourceMsg::Fetch(request, FetchChannels::ResponseMsg(fetch_target, Some(cancel_receiver)))).unwrap();
self.resource_threads
.sender()
.send(CoreResourceMsg::Fetch(
request,
FetchChannels::ResponseMsg(fetch_target, Some(cancel_receiver)),
)).unwrap();
}
/// Mark an in-progress network request complete.
pub fn finish_load(&mut self, load: &LoadType) {
debug!("Removing blocking load {:?} ({}).", load, self.blocking_loads.len());
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == *load);
self.blocking_loads.remove(idx.unwrap_or_else(|| panic!("unknown completed load {:?}", load)));
debug!(
"Removing blocking load {:?} ({}).",
load,
self.blocking_loads.len()
);
let idx = self
.blocking_loads
.iter()
.position(|unfinished| *unfinished == *load);
self.blocking_loads
.remove(idx.unwrap_or_else(|| panic!("unknown completed load {:?}", load)));
}
pub fn is_blocked(&self) -> bool {
@ -157,7 +179,7 @@ impl DocumentLoader {
pub fn is_only_blocked_by_iframes(&self) -> bool {
self.blocking_loads.iter().all(|load| match *load {
LoadType::Subframe(_) => true,
_ => false
_ => false,
})
}

View file

@ -12,7 +12,7 @@ pub enum WorkerScriptMsg {
/// Common variants associated with the script messages
Common(CommonScriptMsg),
/// Message sent through Worker.postMessage
DOMMessage(StructuredCloneData)
DOMMessage(StructuredCloneData),
}
pub struct SimpleWorkerErrorHandler<T: DomObject> {
@ -21,8 +21,6 @@ pub struct SimpleWorkerErrorHandler<T: DomObject> {
impl<T: DomObject> SimpleWorkerErrorHandler<T> {
pub fn new(addr: Trusted<T>) -> SimpleWorkerErrorHandler<T> {
SimpleWorkerErrorHandler {
addr: addr
}
SimpleWorkerErrorHandler { addr: addr }
}
}

View file

@ -25,7 +25,10 @@ pub struct SendableWorkerScriptChan {
impl ScriptChan for SendableWorkerScriptChan {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let msg = DedicatedWorkerScriptMsg::CommonWorker(self.worker.clone(), WorkerScriptMsg::Common(msg));
let msg = DedicatedWorkerScriptMsg::CommonWorker(
self.worker.clone(),
WorkerScriptMsg::Common(msg),
);
self.sender.send(msg).map_err(|_| ())
}
@ -48,10 +51,11 @@ pub struct WorkerThreadWorkerChan {
impl ScriptChan for WorkerThreadWorkerChan {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let msg = DedicatedWorkerScriptMsg::CommonWorker(self.worker.clone(), WorkerScriptMsg::Common(msg));
self.sender
.send(msg)
.map_err(|_| ())
let msg = DedicatedWorkerScriptMsg::CommonWorker(
self.worker.clone(),
WorkerScriptMsg::Common(msg),
);
self.sender.send(msg).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
@ -67,7 +71,7 @@ impl ScriptPort for Receiver<DedicatedWorkerScriptMsg> {
let common_msg = match self.recv() {
Some(DedicatedWorkerScriptMsg::CommonWorker(_worker, common_msg)) => common_msg,
None => return Err(()),
Some(DedicatedWorkerScriptMsg::WakeUp) => panic!("unexpected worker event message!")
Some(DedicatedWorkerScriptMsg::WakeUp) => panic!("unexpected worker event message!"),
};
match common_msg {
WorkerScriptMsg::Common(script_msg) => Ok(script_msg),
@ -90,14 +94,17 @@ pub trait WorkerEventLoopMethods {
}
// https://html.spec.whatwg.org/multipage/#worker-event-loop
pub fn run_worker_event_loop<T, TimerMsg, WorkerMsg, Event>(worker_scope: &T,
worker: Option<&TrustedWorkerAddress>)
where
pub fn run_worker_event_loop<T, TimerMsg, WorkerMsg, Event>(
worker_scope: &T,
worker: Option<&TrustedWorkerAddress>,
) where
TimerMsg: Send,
WorkerMsg: QueuedTaskConversion + Send,
T: WorkerEventLoopMethods<TimerMsg = TimerMsg, WorkerMsg = WorkerMsg, Event = Event>
+ DerivedFrom<WorkerGlobalScope> + DerivedFrom<GlobalScope>
+ DomObject {
+ DerivedFrom<WorkerGlobalScope>
+ DerivedFrom<GlobalScope>
+ DomObject,
{
let scope = worker_scope.upcast::<WorkerGlobalScope>();
let timer_event_port = worker_scope.timer_event_port();
let devtools_port = match scope.from_devtools_sender() {
@ -140,8 +147,10 @@ where
// Step 6
let _ar = match worker {
Some(worker) => worker_scope.handle_worker_post_event(worker),
None => None
None => None,
};
worker_scope.upcast::<GlobalScope>().perform_a_microtask_checkpoint();
worker_scope
.upcast::<GlobalScope>()
.perform_a_microtask_checkpoint();
}
}

View file

@ -56,12 +56,14 @@ pub enum ActivationSource {
}
// https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps
pub fn synthetic_click_activation(element: &Element,
pub fn synthetic_click_activation(
element: &Element,
ctrl_key: bool,
shift_key: bool,
alt_key: bool,
meta_key: bool,
source: ActivationSource) {
source: ActivationSource,
) {
// Step 1
if element.click_in_progress() {
return;
@ -78,7 +80,8 @@ pub fn synthetic_click_activation(element: &Element,
// https://html.spec.whatwg.org/multipage/#fire-a-synthetic-mouse-event
let win = window_from_node(element);
let target = element.upcast::<EventTarget>();
let mouse = MouseEvent::new(&win,
let mouse = MouseEvent::new(
&win,
DOMString::from("click"),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable,
@ -94,7 +97,8 @@ pub fn synthetic_click_activation(element: &Element,
meta_key,
0,
None,
None);
None,
);
let event = mouse.upcast::<Event>();
if source == ActivationSource::FromClick {
event.set_trusted(false);

View file

@ -36,13 +36,14 @@ pub struct Attr {
}
impl Attr {
fn new_inherited(local_name: LocalName,
fn new_inherited(
local_name: LocalName,
value: AttrValue,
name: LocalName,
namespace: Namespace,
prefix: Option<Prefix>,
owner: Option<&Element>)
-> Attr {
owner: Option<&Element>,
) -> Attr {
Attr {
reflector_: Reflector::new(),
identifier: AttrIdentifier {
@ -56,25 +57,21 @@ impl Attr {
}
}
pub fn new(window: &Window,
pub fn new(
window: &Window,
local_name: LocalName,
value: AttrValue,
name: LocalName,
namespace: Namespace,
prefix: Option<Prefix>,
owner: Option<&Element>)
-> DomRoot<Attr> {
owner: Option<&Element>,
) -> DomRoot<Attr> {
reflect_dom_object(
Box::new(Attr::new_inherited(
local_name,
value,
name,
namespace,
prefix,
owner
local_name, value, name, namespace, prefix, owner,
)),
window,
AttrBinding::Wrap
AttrBinding::Wrap,
)
}
@ -110,9 +107,7 @@ impl AttrMethods for Attr {
// https://dom.spec.whatwg.org/#dom-attr-value
fn SetValue(&self, value: DOMString) {
if let Some(owner) = self.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);
} else {
*self.value.borrow_mut() = AttrValue::String(value.into());
@ -175,7 +170,6 @@ impl AttrMethods for Attr {
}
}
impl Attr {
pub fn set_value(&self, mut value: AttrValue, owner: &Element) {
let name = self.local_name().clone();
@ -191,7 +185,12 @@ impl Attr {
MutationObserver::queue_a_mutation_record(owner.upcast::<Node>(), mutation);
if owner.get_custom_element_definition().is_some() {
let reaction = CallbackReaction::AttributeChanged(name, Some(old_value), Some(new_value), namespace);
let reaction = CallbackReaction::AttributeChanged(
name,
Some(old_value),
Some(new_value),
namespace,
);
ScriptThread::enqueue_callback_reaction(owner, reaction, None);
}
@ -229,7 +228,7 @@ impl Attr {
(Some(old), None) => {
// Already gone from the list of attributes of old owner.
assert!(old.get_attribute(&ns, &self.identifier.local_name).r() != Some(self))
}
},
(Some(old), Some(new)) => assert_eq!(&*old, new),
_ => {},
}

View file

@ -98,7 +98,11 @@ impl AudioBufferSourceNode {
options: &AudioBufferSourceOptions,
) -> Fallible<DomRoot<AudioBufferSourceNode>> {
let node = AudioBufferSourceNode::new_inherited(window, context, options)?;
Ok(reflect_dom_object(Box::new(node), window, AudioBufferSourceNodeBinding::Wrap))
Ok(reflect_dom_object(
Box::new(node),
window,
AudioBufferSourceNodeBinding::Wrap,
))
}
pub fn Constructor(

View file

@ -36,9 +36,8 @@ impl AudioContext {
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
fn new_inherited(options: &AudioContextOptions) -> AudioContext {
// Steps 1-3.
let context = BaseAudioContext::new_inherited(
BaseAudioContextOptions::AudioContext(options.into()),
);
let context =
BaseAudioContext::new_inherited(BaseAudioContextOptions::AudioContext(options.into()));
// Step 4.1.
let latency_hint = options.latencyHint;

View file

@ -22,8 +22,8 @@ impl AudioDestinationNode {
context: &BaseAudioContext,
options: &AudioNodeOptions,
) -> AudioDestinationNode {
let node_options = options.unwrap_or(2, ChannelCountMode::Max,
ChannelInterpretation::Speakers);
let node_options =
options.unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);
AudioDestinationNode {
node: AudioNode::new_inherited_for_id(
context.destination_node(),

View file

@ -28,10 +28,7 @@ pub struct AudioListener {
}
impl AudioListener {
fn new_inherited(
window: &Window,
context: &BaseAudioContext,
) -> AudioListener {
fn new_inherited(window: &Window, context: &BaseAudioContext) -> AudioListener {
let node = context.listener();
let position_x = AudioParam::new(
@ -139,10 +136,7 @@ impl AudioListener {
}
#[allow(unrooted_must_root)]
pub fn new(
window: &Window,
context: &BaseAudioContext,
) -> DomRoot<AudioListener> {
pub fn new(window: &Window, context: &BaseAudioContext) -> DomRoot<AudioListener> {
let node = AudioListener::new_inherited(window, context);
reflect_dom_object(Box::new(node), window, AudioListenerBinding::Wrap)
}

View file

@ -36,7 +36,6 @@ pub struct AudioNode {
channel_interpretation: Cell<ChannelInterpretation>,
}
impl AudioNode {
pub fn new_inherited(
node_type: AudioNodeInit,
@ -54,7 +53,13 @@ impl AudioNode {
interpretation: options.interpretation.into(),
};
let node_id = context.audio_context_impl().create_node(node_type, ch);
Ok(AudioNode::new_inherited_for_id(node_id, context, options, number_of_inputs, number_of_outputs))
Ok(AudioNode::new_inherited_for_id(
node_id,
context,
options,
number_of_inputs,
number_of_outputs,
))
}
pub fn new_inherited_for_id(
@ -177,8 +182,7 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect_____(&self, param: &AudioParam) -> ErrorResult {
self.context
.audio_context_impl()
.disconnect_to(self.node_id(),
param.node_id().param(param.param_type()));
.disconnect_to(self.node_id(), param.node_id().param(param.param_type()));
Ok(())
}
@ -186,8 +190,10 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect______(&self, param: &AudioParam, out: u32) -> ErrorResult {
self.context
.audio_context_impl()
.disconnect_output_between_to(self.node_id().output(out),
param.node_id().param(param.param_type()));
.disconnect_output_between_to(
self.node_id().output(out),
param.node_id().param(param.param_type()),
);
Ok(())
}
@ -223,14 +229,14 @@ impl AudioNodeMethods for AudioNode {
},
EventTargetTypeId::AudioNode(AudioNodeTypeId::PannerNode) => {
if value > 2 {
return Err(Error::NotSupported)
}
return Err(Error::NotSupported);
}
},
EventTargetTypeId::AudioNode(AudioNodeTypeId::ChannelMergerNode) => {
if value != 1 {
return Err(Error::InvalidState)
}
return Err(Error::InvalidState);
}
},
// XXX We do not support any of the other AudioNodes with
// constraints yet. Add more cases here as we add support
// for new AudioNodes.
@ -266,14 +272,14 @@ impl AudioNodeMethods for AudioNode {
},
EventTargetTypeId::AudioNode(AudioNodeTypeId::PannerNode) => {
if value == ChannelCountMode::Max {
return Err(Error::NotSupported)
}
return Err(Error::NotSupported);
}
},
EventTargetTypeId::AudioNode(AudioNodeTypeId::ChannelMergerNode) => {
if value != ChannelCountMode::Explicit {
return Err(Error::InvalidState)
}
return Err(Error::InvalidState);
}
},
// XXX We do not support any of the other AudioNodes with
// constraints yet. Add more cases here as we add support
// for new AudioNodes.
@ -321,14 +327,17 @@ impl From<ChannelInterpretation> for ServoMediaChannelInterpretation {
}
}
impl AudioNodeOptions {
pub fn unwrap_or(&self, count: u32, mode: ChannelCountMode,
interpretation: ChannelInterpretation) -> UnwrappedAudioNodeOptions {
pub fn unwrap_or(
&self,
count: u32,
mode: ChannelCountMode,
interpretation: ChannelInterpretation,
) -> UnwrappedAudioNodeOptions {
UnwrappedAudioNodeOptions {
count: self.channelCount.unwrap_or(count),
mode: self.channelCountMode.unwrap_or(mode),
interpretation: self.channelInterpretation.unwrap_or(interpretation)
interpretation: self.channelInterpretation.unwrap_or(interpretation),
}
}
}

View file

@ -76,7 +76,9 @@ impl AudioParam {
}
fn message_node(&self, message: AudioNodeMessage) {
self.context.audio_context_impl().message_node(self.node, message);
self.context
.audio_context_impl()
.message_node(self.node, message);
}
pub fn context(&self) -> &BaseAudioContext {
@ -101,25 +103,25 @@ impl AudioParamMethods for AudioParam {
// https://webaudio.github.io/web-audio-api/#dom-audioparam-automationrate
fn SetAutomationRate(&self, automation_rate: AutomationRate) {
self.automation_rate.set(automation_rate);
self.message_node(
AudioNodeMessage::SetParamRate(self.param, automation_rate.into())
);
self.message_node(AudioNodeMessage::SetParamRate(
self.param,
automation_rate.into(),
));
}
// https://webaudio.github.io/web-audio-api/#dom-audioparam-value
fn Value(&self) -> Finite<f32> {
let (tx, rx) = mpsc::channel();
self.message_node(
AudioNodeMessage::GetParamValue(self.param, tx)
);
self.message_node(AudioNodeMessage::GetParamValue(self.param, tx));
Finite::wrap(rx.recv().unwrap())
}
// https://webaudio.github.io/web-audio-api/#dom-audioparam-value
fn SetValue(&self, value: Finite<f32>) {
self.message_node(
AudioNodeMessage::SetParam(self.param, UserAutomationEvent::SetValue(*value)),
);
self.message_node(AudioNodeMessage::SetParam(
self.param,
UserAutomationEvent::SetValue(*value),
));
}
// https://webaudio.github.io/web-audio-api/#dom-audioparam-defaultvalue
@ -139,12 +141,10 @@ impl AudioParamMethods for AudioParam {
// https://webaudio.github.io/web-audio-api/#dom-audioparam-setvalueattime
fn SetValueAtTime(&self, value: Finite<f32>, start_time: Finite<f64>) -> DomRoot<AudioParam> {
self.message_node(
AudioNodeMessage::SetParam(
self.message_node(AudioNodeMessage::SetParam(
self.param,
UserAutomationEvent::SetValueAtTime(*value, *start_time),
)
);
));
DomRoot::from_ref(self)
}
@ -154,12 +154,10 @@ impl AudioParamMethods for AudioParam {
value: Finite<f32>,
end_time: Finite<f64>,
) -> DomRoot<AudioParam> {
self.message_node(
AudioNodeMessage::SetParam(
self.message_node(AudioNodeMessage::SetParam(
self.param,
UserAutomationEvent::RampToValueAtTime(RampKind::Linear, *value, *end_time),
),
);
));
DomRoot::from_ref(self)
}
@ -169,12 +167,10 @@ impl AudioParamMethods for AudioParam {
value: Finite<f32>,
end_time: Finite<f64>,
) -> DomRoot<AudioParam> {
self.message_node(
AudioNodeMessage::SetParam(
self.message_node(AudioNodeMessage::SetParam(
self.param,
UserAutomationEvent::RampToValueAtTime(RampKind::Exponential, *value, *end_time),
),
);
));
DomRoot::from_ref(self)
}
@ -185,34 +181,28 @@ impl AudioParamMethods for AudioParam {
start_time: Finite<f64>,
time_constant: Finite<f32>,
) -> DomRoot<AudioParam> {
self.message_node(
AudioNodeMessage::SetParam(
self.message_node(AudioNodeMessage::SetParam(
self.param,
UserAutomationEvent::SetTargetAtTime(*target, *start_time, (*time_constant).into()),
),
);
));
DomRoot::from_ref(self)
}
// https://webaudio.github.io/web-audio-api/#dom-audioparam-cancelscheduledvalues
fn CancelScheduledValues(&self, cancel_time: Finite<f64>) -> DomRoot<AudioParam> {
self.message_node(
AudioNodeMessage::SetParam(
self.message_node(AudioNodeMessage::SetParam(
self.param,
UserAutomationEvent::CancelScheduledValues(*cancel_time),
),
);
));
DomRoot::from_ref(self)
}
// https://webaudio.github.io/web-audio-api/#dom-audioparam-cancelandholdattime
fn CancelAndHoldAtTime(&self, cancel_time: Finite<f64>) -> DomRoot<AudioParam> {
self.message_node(
AudioNodeMessage::SetParam(
self.message_node(AudioNodeMessage::SetParam(
self.param,
UserAutomationEvent::CancelAndHoldAtTime(*cancel_time),
),
);
));
DomRoot::from_ref(self)
}
}

View file

@ -84,9 +84,10 @@ impl AudioScheduledSourceNodeMethods for AudioScheduledSourceNode {
);
});
self.node().message(
AudioNodeMessage::AudioScheduledSourceNode(
AudioScheduledSourceNodeMessage::RegisterOnEndedCallback(callback)));
self.node()
.message(AudioNodeMessage::AudioScheduledSourceNode(
AudioScheduledSourceNodeMessage::RegisterOnEndedCallback(callback),
));
self.started.set(true);
self.node

View file

@ -98,7 +98,9 @@ impl BaseAudioContext {
pub fn new_inherited(options: BaseAudioContextOptions) -> BaseAudioContext {
let (sample_rate, channel_count) = match options {
BaseAudioContextOptions::AudioContext(ref opt) => (opt.sample_rate, 2),
BaseAudioContextOptions::OfflineAudioContext(ref opt) => (opt.sample_rate, opt.channels),
BaseAudioContextOptions::OfflineAudioContext(ref opt) => {
(opt.sample_rate, opt.channels)
},
};
let context = BaseAudioContext {
@ -312,9 +314,7 @@ impl BaseAudioContextMethods for BaseAudioContext {
fn Listener(&self) -> DomRoot<AudioListener> {
let global = self.global();
let window = global.as_window();
self.listener.or_init(|| {
AudioListener::new(&window, self)
})
self.listener.or_init(|| AudioListener::new(&window, self))
}
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-onstatechange
@ -425,12 +425,10 @@ impl BaseAudioContextMethods for BaseAudioContext {
.lock()
.unwrap()
.resize(channel_count as usize, Vec::new());
})
.progress(move |buffer, channel| {
}).progress(move |buffer, channel| {
let mut decoded_audio = decoded_audio_.lock().unwrap();
decoded_audio[(channel - 1) as usize].extend_from_slice((*buffer).as_ref());
})
.eos(move || {
}).eos(move || {
let _ = task_source.queue_with_canceller(
task!(audio_decode_eos: move || {
let this = this.root();
@ -456,8 +454,7 @@ impl BaseAudioContextMethods for BaseAudioContext {
}),
&canceller,
);
})
.error(move || {
}).error(move || {
let _ = task_source_.queue_with_canceller(
task!(audio_decode_eos: move || {
let this = this_.root();
@ -473,8 +470,7 @@ impl BaseAudioContextMethods for BaseAudioContext {
}),
&canceller_,
);
})
.build();
}).build();
self.audio_context_impl
.decode_audio_data(audio_data, callbacks);
} else {
@ -491,10 +487,12 @@ impl BaseAudioContextMethods for BaseAudioContext {
impl From<BaseAudioContextOptions> for AudioContextOptions {
fn from(options: BaseAudioContextOptions) -> Self {
match options {
BaseAudioContextOptions::AudioContext(options) =>
AudioContextOptions::RealTimeAudioContext(options),
BaseAudioContextOptions::OfflineAudioContext(options) =>
AudioContextOptions::OfflineAudioContext(options),
BaseAudioContextOptions::AudioContext(options) => {
AudioContextOptions::RealTimeAudioContext(options)
},
BaseAudioContextOptions::OfflineAudioContext(options) => {
AudioContextOptions::OfflineAudioContext(options)
},
}
}
}

View file

@ -33,20 +33,23 @@ impl BeforeUnloadEvent {
}
pub fn new_uninitialized(window: &Window) -> DomRoot<BeforeUnloadEvent> {
reflect_dom_object(Box::new(BeforeUnloadEvent::new_inherited()),
reflect_dom_object(
Box::new(BeforeUnloadEvent::new_inherited()),
window,
BeforeUnloadEventBinding::Wrap)
BeforeUnloadEventBinding::Wrap,
)
}
pub fn new(window: &Window,
pub fn new(
window: &Window,
type_: Atom,
bubbles: EventBubbles,
cancelable: EventCancelable) -> DomRoot<BeforeUnloadEvent> {
cancelable: EventCancelable,
) -> DomRoot<BeforeUnloadEvent> {
let ev = BeforeUnloadEvent::new_uninitialized(window);
{
let event = ev.upcast::<Event>();
event.init_event(type_, bool::from(bubbles),
bool::from(cancelable));
event.init_event(type_, bool::from(bubbles), bool::from(cancelable));
}
ev
}

View file

@ -53,7 +53,7 @@ pub struct CallbackObject {
///
/// ["callback context"]: https://heycam.github.io/webidl/#dfn-callback-context
/// [sometimes]: https://github.com/whatwg/html/issues/2248
incumbent: Option<Dom<GlobalScope>>
incumbent: Option<Dom<GlobalScope>>,
}
impl Default for CallbackObject {
@ -81,8 +81,11 @@ impl CallbackObject {
unsafe fn init(&mut self, cx: *mut JSContext, callback: *mut JSObject) {
self.callback.set(callback);
self.permanent_js_root.set(ObjectValue(callback));
assert!(AddRawValueRoot(cx, self.permanent_js_root.get_unsafe(),
b"CallbackObject::root\n".as_c_char_ptr()));
assert!(AddRawValueRoot(
cx,
self.permanent_js_root.get_unsafe(),
b"CallbackObject::root\n".as_c_char_ptr()
));
}
}
@ -94,7 +97,6 @@ impl Drop for CallbackObject {
RemoveRawValueRoot(cx, self.permanent_js_root.get_unsafe());
}
}
}
impl PartialEq for CallbackObject {
@ -103,7 +105,6 @@ impl PartialEq for CallbackObject {
}
}
/// A trait to be implemented by concrete IDL callback function and
/// callback interface types.
pub trait CallbackContainer {
@ -124,7 +125,6 @@ pub trait CallbackContainer {
}
}
/// A common base class for representing IDL callback function types.
#[derive(JSTraceable, PartialEq)]
#[must_root]
@ -153,9 +153,6 @@ impl CallbackFunction {
}
}
/// A common base class for representing IDL callback interface types.
#[derive(JSTraceable, PartialEq)]
#[must_root]
@ -194,19 +191,22 @@ impl CallbackInterface {
}
if !callable.is_object() || !IsCallable(callable.to_object()) {
return Err(Error::Type(format!("The value of the {} property is not callable",
name)));
return Err(Error::Type(format!(
"The value of the {} property is not callable",
name
)));
}
}
Ok(callable.get())
}
}
/// Wraps the reflector for `p` into the compartment of `cx`.
pub fn wrap_call_this_object<T: DomObject>(cx: *mut JSContext,
pub fn wrap_call_this_object<T: DomObject>(
cx: *mut JSContext,
p: &T,
mut rval: MutableHandleObject) {
mut rval: MutableHandleObject,
) {
rval.set(p.reflector().get_jsobject().get());
assert!(!rval.get().is_null());
@ -217,7 +217,6 @@ pub fn wrap_call_this_object<T: DomObject>(cx: *mut JSContext,
}
}
/// A class that performs whatever setup we need to safely make a call while
/// this class is on the stack. After `new` returns, the call is safe to make.
pub struct CallSetup {
@ -241,9 +240,7 @@ pub struct CallSetup {
impl CallSetup {
/// Performs the setup needed to make a call.
#[allow(unrooted_must_root)]
pub fn new<T: CallbackContainer>(callback: &T,
handling: ExceptionHandling)
-> CallSetup {
pub fn new<T: CallbackContainer>(callback: &T, handling: ExceptionHandling) -> CallSetup {
let global = unsafe { GlobalScope::from_object(callback.callback()) };
let cx = global.get_cx();
@ -270,8 +267,10 @@ impl Drop for CallSetup {
unsafe {
JS_LeaveCompartment(self.cx, self.old_compartment);
if self.handling == ExceptionHandling::Report {
let _ac = JSAutoCompartment::new(self.cx,
self.exception_global.reflector().get_jsobject().get());
let _ac = JSAutoCompartment::new(
self.cx,
self.exception_global.reflector().get_jsobject().get(),
);
report_pending_exception(self.cx, true);
}
drop(self.incumbent_script.take());

View file

@ -55,7 +55,6 @@ impl<T> DomRefCell<T> {
}
}
/// Immutably borrows the wrapped value.
///
/// The borrow lasts until the returned `Ref` exits scope. Multiple
@ -67,7 +66,8 @@ impl<T> DomRefCell<T> {
///
/// Panics if the value is currently mutably borrowed.
pub fn borrow(&self) -> Ref<T> {
self.try_borrow().expect("DomRefCell<T> already mutably borrowed")
self.try_borrow()
.expect("DomRefCell<T> already mutably borrowed")
}
/// Mutably borrows the wrapped value.
@ -81,7 +81,8 @@ impl<T> DomRefCell<T> {
///
/// Panics if the value is currently borrowed.
pub fn borrow_mut(&self) -> RefMut<T> {
self.try_borrow_mut().expect("DomRefCell<T> already borrowed")
self.try_borrow_mut()
.expect("DomRefCell<T> already borrowed")
}
/// Attempts to immutably borrow the wrapped value.

View file

@ -51,16 +51,15 @@ impl ConstantSpec {
/// Defines constants on `obj`.
/// Fails on JSAPI failure.
pub unsafe fn define_constants(
cx: *mut JSContext,
obj: HandleObject,
constants: &[ConstantSpec]) {
pub unsafe fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &[ConstantSpec]) {
for spec in constants {
rooted!(in(cx) let value = spec.get_value());
assert!(JS_DefineProperty(cx,
assert!(JS_DefineProperty(
cx,
obj,
spec.name.as_ptr() as *const libc::c_char,
value.handle(),
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32));
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32
));
}
}

View file

@ -69,8 +69,10 @@ pub trait IDLInterface {
}
/// A trait to mark an IDL interface as deriving from another one.
#[cfg_attr(feature = "unstable",
rustc_on_unimplemented = "The IDL interface `{Self}` is not derived from `{T}`.")]
#[cfg_attr(
feature = "unstable",
rustc_on_unimplemented = "The IDL interface `{Self}` is not derived from `{T}`."
)]
pub trait DerivedFrom<T: Castable>: Castable {}
impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> {
@ -81,20 +83,21 @@ impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> {
}
}
impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite<T> {
impl<T: Float + FromJSValConvertible<Config = ()>> FromJSValConvertible for Finite<T> {
type Config = ();
unsafe fn from_jsval(cx: *mut JSContext,
unsafe fn from_jsval(
cx: *mut JSContext,
value: HandleValue,
option: ())
-> Result<ConversionResult<Finite<T>>, ()> {
option: (),
) -> Result<ConversionResult<Finite<T>>, ()> {
let result = match FromJSValConvertible::from_jsval(cx, value, option)? {
ConversionResult::Success(v) => v,
ConversionResult::Failure(error) => {
// FIXME(emilio): Why throwing instead of propagating the error?
throw_type_error(cx, &error);
return Err(());
}
},
};
match Finite::new(result) {
Some(v) => Ok(ConversionResult::Success(v)),
@ -106,13 +109,14 @@ impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite
}
}
impl <T: DomObject + IDLInterface> FromJSValConvertible for DomRoot<T> {
impl<T: DomObject + IDLInterface> FromJSValConvertible for DomRoot<T> {
type Config = ();
unsafe fn from_jsval(_cx: *mut JSContext,
unsafe fn from_jsval(
_cx: *mut JSContext,
value: HandleValue,
_config: Self::Config)
-> Result<ConversionResult<DomRoot<T>>, ()> {
_config: Self::Config,
) -> Result<ConversionResult<DomRoot<T>>, ()> {
Ok(match root_from_handlevalue(value) {
Ok(result) => ConversionResult::Success(result),
Err(()) => ConversionResult::Failure("value is not an object".into()),
@ -129,19 +133,21 @@ impl<T: ToJSValConvertible + JSTraceable> ToJSValConvertible for RootedTraceable
}
impl<T> FromJSValConvertible for RootedTraceableBox<Heap<T>>
where
where
T: FromJSValConvertible + js::rust::GCMethods + Copy,
Heap<T>: JSTraceable + Default
Heap<T>: JSTraceable + Default,
{
type Config = T::Config;
unsafe fn from_jsval(cx: *mut JSContext,
unsafe fn from_jsval(
cx: *mut JSContext,
value: HandleValue,
config: Self::Config)
-> Result<ConversionResult<Self>, ()> {
config: Self::Config,
) -> Result<ConversionResult<Self>, ()> {
T::from_jsval(cx, value, config).map(|result| match result {
ConversionResult::Success(inner) =>
ConversionResult::Success(RootedTraceableBox::from_box(Heap::boxed(inner))),
ConversionResult::Success(inner) => {
ConversionResult::Success(RootedTraceableBox::from_box(Heap::boxed(inner)))
},
ConversionResult::Failure(msg) => ConversionResult::Failure(msg),
})
}
@ -190,12 +196,12 @@ impl ToJSValConvertible for DOMString {
// https://heycam.github.io/webidl/#es-DOMString
impl FromJSValConvertible for DOMString {
type Config = StringificationBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
unsafe fn from_jsval(
cx: *mut JSContext,
value: HandleValue,
null_behavior: StringificationBehavior)
-> Result<ConversionResult<DOMString>, ()> {
if null_behavior == StringificationBehavior::Empty &&
value.get().is_null() {
null_behavior: StringificationBehavior,
) -> Result<ConversionResult<DOMString>, ()> {
if null_behavior == StringificationBehavior::Empty && value.get().is_null() {
Ok(ConversionResult::Success(DOMString::new()))
} else {
let jsstr = ToString(cx, value);
@ -231,16 +237,19 @@ pub unsafe fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString
"Found an unpaired surrogate in a DOM string. \
If you see this in real web content, \
please comment on https://github.com/servo/servo/issues/6564"
}
};
}
if opts::get().replace_surrogates {
error!(message!());
s.push('\u{FFFD}');
} else {
panic!(concat!(message!(), " Use `-Z replace-surrogates` \
on the command line to make this non-fatal."));
}
panic!(concat!(
message!(),
" Use `-Z replace-surrogates` \
on the command line to make this non-fatal."
));
}
},
}
}
s
@ -250,8 +259,11 @@ pub unsafe fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString
// http://heycam.github.io/webidl/#es-USVString
impl FromJSValConvertible for USVString {
type Config = ();
unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ())
-> Result<ConversionResult<USVString>, ()> {
unsafe fn from_jsval(
cx: *mut JSContext,
value: HandleValue,
_: (),
) -> Result<ConversionResult<USVString>, ()> {
let jsstr = ToString(cx, value);
if jsstr.is_null() {
debug!("ToString failed");
@ -260,23 +272,28 @@ impl FromJSValConvertible for USVString {
let latin1 = JS_StringHasLatin1Chars(jsstr);
if latin1 {
// FIXME(ajeffrey): Convert directly from DOMString to USVString
return Ok(ConversionResult::Success(
USVString(String::from(jsstring_to_str(cx, jsstr)))));
return Ok(ConversionResult::Success(USVString(String::from(
jsstring_to_str(cx, jsstr),
))));
}
let mut length = 0;
let chars = JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), jsstr, &mut length);
assert!(!chars.is_null());
let char_vec = slice::from_raw_parts(chars as *const u16, length as usize);
Ok(ConversionResult::Success(USVString(String::from_utf16_lossy(char_vec))))
Ok(ConversionResult::Success(USVString(
String::from_utf16_lossy(char_vec),
)))
}
}
// http://heycam.github.io/webidl/#es-ByteString
impl ToJSValConvertible for ByteString {
unsafe fn to_jsval(&self, cx: *mut JSContext, mut rval: MutableHandleValue) {
let jsstr = JS_NewStringCopyN(cx,
let jsstr = JS_NewStringCopyN(
cx,
self.as_ptr() as *const libc::c_char,
self.len() as libc::size_t);
self.len() as libc::size_t,
);
if jsstr.is_null() {
panic!("JS_NewStringCopyN failed");
}
@ -287,10 +304,11 @@ impl ToJSValConvertible for ByteString {
// http://heycam.github.io/webidl/#es-ByteString
impl FromJSValConvertible for ByteString {
type Config = ();
unsafe fn from_jsval(cx: *mut JSContext,
unsafe fn from_jsval(
cx: *mut JSContext,
value: HandleValue,
_option: ())
-> Result<ConversionResult<ByteString>, ()> {
_option: (),
) -> Result<ConversionResult<ByteString>, ()> {
let string = ToString(cx, value);
if string.is_null() {
debug!("ToString failed");
@ -304,7 +322,9 @@ impl FromJSValConvertible for ByteString {
assert!(!chars.is_null());
let char_slice = slice::from_raw_parts(chars as *mut u8, length as usize);
return Ok(ConversionResult::Success(ByteString::new(char_slice.to_vec())));
return Ok(ConversionResult::Success(ByteString::new(
char_slice.to_vec(),
)));
}
let mut length = 0;
@ -315,13 +335,13 @@ impl FromJSValConvertible for ByteString {
throw_type_error(cx, "Invalid ByteString");
Err(())
} else {
Ok(ConversionResult::Success(
ByteString::new(char_vec.iter().map(|&c| c as u8).collect())))
Ok(ConversionResult::Success(ByteString::new(
char_vec.iter().map(|&c| c as u8).collect(),
)))
}
}
}
impl ToJSValConvertible for Reflector {
unsafe fn to_jsval(&self, cx: *mut JSContext, mut rval: MutableHandleValue) {
let obj = self.get_jsobject().get();
@ -389,10 +409,12 @@ 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)
-> Result<*const libc::c_void, ()>
where F: Fn(&'static DOMClass) -> bool
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,
{
let dom_class = get_dom_class(obj).or_else(|_| {
if IsWrapper(obj) {
@ -423,11 +445,10 @@ pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject,
/// Get a `*const T` for a DOM object accessible from a `JSObject`.
pub fn native_from_object<T>(obj: *mut JSObject) -> Result<*const T, ()>
where T: DomObject + IDLInterface
where
T: DomObject + IDLInterface,
{
unsafe {
private_from_proto_check(obj, T::derives).map(|ptr| ptr as *const T)
}
unsafe { private_from_proto_check(obj, T::derives).map(|ptr| ptr as *const T) }
}
/// Get a `DomRoot<T>` for the given DOM object, unwrapping any wrapper
@ -437,7 +458,8 @@ pub fn native_from_object<T>(obj: *mut JSObject) -> Result<*const T, ()>
/// not a reflector for a DOM object of the given type (as defined by the
/// proto_id and proto_depth).
pub fn root_from_object<T>(obj: *mut JSObject) -> Result<DomRoot<T>, ()>
where T: DomObject + IDLInterface
where
T: DomObject + IDLInterface,
{
native_from_object(obj).map(|ptr| unsafe { DomRoot::from_ref(&*ptr) })
}
@ -445,7 +467,8 @@ pub fn root_from_object<T>(obj: *mut JSObject) -> Result<DomRoot<T>, ()>
/// Get a `*const T` for a DOM object accessible from a `HandleValue`.
/// Caller is responsible for throwing a JS exception if needed in case of error.
pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<*const T, ()>
where T: DomObject + IDLInterface
where
T: DomObject + IDLInterface,
{
if !v.get().is_object() {
return Err(());
@ -456,7 +479,8 @@ pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<*const T, ()>
/// Get a `DomRoot<T>` for a DOM object accessible from a `HandleValue`.
/// Caller is responsible for throwing a JS exception if needed in case of error.
pub fn root_from_handlevalue<T>(v: HandleValue) -> Result<DomRoot<T>, ()>
where T: DomObject + IDLInterface
where
T: DomObject + IDLInterface,
{
if !v.get().is_object() {
return Err(());
@ -466,7 +490,8 @@ pub fn root_from_handlevalue<T>(v: HandleValue) -> Result<DomRoot<T>, ()>
/// Get a `DomRoot<T>` for a DOM object accessible from a `HandleObject`.
pub fn root_from_handleobject<T>(obj: HandleObject) -> Result<DomRoot<T>, ()>
where T: DomObject + IDLInterface
where
T: DomObject + IDLInterface,
{
root_from_object(obj.get())
}
@ -487,12 +512,12 @@ pub unsafe fn is_array_like(cx: *mut JSContext, value: HandleValue) -> bool {
}
/// Get a property from a JS object.
pub unsafe fn get_property_jsval(cx: *mut JSContext,
pub unsafe fn get_property_jsval(
cx: *mut JSContext,
object: HandleObject,
name: &str,
mut rval: MutableHandleValue)
-> Fallible<()>
{
mut rval: MutableHandleValue,
) -> Fallible<()> {
rval.set(UndefinedValue());
let cname = match ffi::CString::new(name) {
Ok(cname) => cname,
@ -506,12 +531,14 @@ pub unsafe fn get_property_jsval(cx: *mut JSContext,
}
/// Get a property from a JS object, and convert it to a Rust value.
pub unsafe fn get_property<T>(cx: *mut JSContext,
pub unsafe fn get_property<T>(
cx: *mut JSContext,
object: HandleObject,
name: &str,
option: T::Config)
-> Fallible<Option<T>> where
T: FromJSValConvertible
option: T::Config,
) -> Fallible<Option<T>>
where
T: FromJSValConvertible,
{
debug!("Getting property {}.", name);
rooted!(in(cx) let mut result = UndefinedValue());

View file

@ -126,7 +126,7 @@ pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: &GlobalScope, resu
Error::JSFailed => {
assert!(JS_IsExceptionPending(cx));
return;
}
},
};
assert!(!JS_IsExceptionPending(cx));
@ -149,8 +149,7 @@ pub struct ErrorInfo {
}
impl ErrorInfo {
unsafe fn from_native_error(cx: *mut JSContext, object: HandleObject)
-> Option<ErrorInfo> {
unsafe fn from_native_error(cx: *mut JSContext, object: HandleObject) -> Option<ErrorInfo> {
let report = JS_ErrorFromException(cx, object);
if report.is_null() {
return None;
@ -205,7 +204,9 @@ impl ErrorInfo {
/// The `dispatch_event` argument is temporary and non-standard; passing false
/// prevents dispatching the `error` event.
pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool) {
if !JS_IsExceptionPending(cx) { return; }
if !JS_IsExceptionPending(cx) {
return;
}
rooted!(in(cx) let mut value = UndefinedValue());
if !JS_GetPendingException(cx, value.handle_mut()) {
@ -219,23 +220,19 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
rooted!(in(cx) let object = value.to_object());
ErrorInfo::from_native_error(cx, object.handle())
.or_else(|| ErrorInfo::from_dom_exception(object.handle()))
.unwrap_or_else(|| {
ErrorInfo {
.unwrap_or_else(|| ErrorInfo {
message: format!("uncaught exception: unknown (can't convert to string)"),
filename: String::new(),
lineno: 0,
column: 0,
}
})
} else {
match USVString::from_jsval(cx, value.handle(), ()) {
Ok(ConversionResult::Success(USVString(string))) => {
ErrorInfo {
Ok(ConversionResult::Success(USVString(string))) => ErrorInfo {
message: format!("uncaught exception: {}", string),
filename: String::new(),
lineno: 0,
column: 0,
}
},
_ => {
panic!("Uncaught exception: failed to stringify primitive");
@ -243,15 +240,13 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
}
};
error!("Error at {}:{}:{} {}",
error_info.filename,
error_info.lineno,
error_info.column,
error_info.message);
error!(
"Error at {}:{}:{} {}",
error_info.filename, error_info.lineno, error_info.column, error_info.message
);
if dispatch_event {
GlobalScope::from_context(cx)
.report_an_error(error_info, value.handle());
GlobalScope::from_context(cx).report_an_error(error_info, value.handle());
}
}
@ -259,14 +254,21 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
/// given DOM type.
pub unsafe fn throw_invalid_this(cx: *mut JSContext, proto_id: u16) {
debug_assert!(!JS_IsExceptionPending(cx));
let error = format!("\"this\" object does not implement interface {}.",
proto_id_to_name(proto_id));
let error = format!(
"\"this\" object does not implement interface {}.",
proto_id_to_name(proto_id)
);
throw_type_error(cx, &error);
}
impl Error {
/// Convert this error value to a JS value, consuming it in the process.
pub unsafe fn to_jsval(self, cx: *mut JSContext, global: &GlobalScope, rval: MutableHandleValue) {
pub unsafe fn to_jsval(
self,
cx: *mut JSContext,
global: &GlobalScope,
rval: MutableHandleValue,
) {
assert!(!JS_IsExceptionPending(cx));
throw_dom_exception(cx, global, self);
assert!(JS_IsExceptionPending(cx));

View file

@ -89,7 +89,9 @@ use std::ptr;
// https://html.spec.whatwg.org/multipage/#htmlconstructor
pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fallible<DomRoot<T>>
where T: DerivedFrom<Element> {
where
T: DerivedFrom<Element>,
{
let document = window.Document();
// Step 1
@ -101,7 +103,11 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
rooted!(in(window.get_cx()) let new_target = call_args.new_target().to_object());
let definition = match registry.lookup_definition_by_constructor(new_target.handle()) {
Some(definition) => definition,
None => return Err(Error::Type("No custom element definition found for new.target".to_owned())),
None => {
return Err(Error::Type(
"No custom element definition found for new.target".to_owned(),
))
},
};
rooted!(in(window.get_cx()) let callee = UnwrapObject(call_args.callee(), 1));
@ -119,18 +125,25 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
// Since this element is autonomous, its active function object must be the HTMLElement
// Retrieve the constructor object for HTMLElement
HTMLElementBinding::GetConstructorObject(window.get_cx(), global_object.handle(), constructor.handle_mut());
} else {
// Step 5
get_constructor_object_from_local_name(definition.local_name.clone(),
HTMLElementBinding::GetConstructorObject(
window.get_cx(),
global_object.handle(),
constructor.handle_mut());
constructor.handle_mut(),
);
} else {
// Step 5
get_constructor_object_from_local_name(
definition.local_name.clone(),
window.get_cx(),
global_object.handle(),
constructor.handle_mut(),
);
}
// Callee must be the same as the element interface's constructor object.
if constructor.get() != callee.get() {
return Err(Error::Type("Custom element does not extend the proper interface".to_owned()));
return Err(Error::Type(
"Custom element does not extend the proper interface".to_owned(),
));
}
}
@ -176,11 +189,12 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
/// Returns the constructor object for the element associated with the given local name.
/// This list should only include elements marked with the [HTMLConstructor] extended attribute.
pub fn get_constructor_object_from_local_name(name: LocalName,
pub fn get_constructor_object_from_local_name(
name: LocalName,
cx: *mut JSContext,
global: HandleObject,
rval: MutableHandleObject)
-> bool {
rval: MutableHandleObject,
) -> bool {
macro_rules! get_constructor(
($binding:ident) => ({
unsafe { $binding::GetConstructorObject(cx, global, rval); }

View file

@ -16,7 +16,8 @@ use std::mem;
pub trait Castable: IDLInterface + DomObject + Sized {
/// Check whether a DOM object implements one of its deriving interfaces.
fn is<T>(&self) -> bool
where T: DerivedFrom<Self>
where
T: DerivedFrom<Self>,
{
let class = unsafe { get_dom_class(self.reflector().get_jsobject().get()).unwrap() };
T::derives(class)
@ -24,15 +25,17 @@ pub trait Castable: IDLInterface + DomObject + Sized {
/// Cast a DOM object upwards to one of the interfaces it derives from.
fn upcast<T>(&self) -> &T
where T: Castable,
Self: DerivedFrom<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>
where
T: DerivedFrom<Self>,
{
if self.is::<T>() {
Some(unsafe { mem::transmute(self) })

View file

@ -52,11 +52,12 @@ unsafe impl Sync for NonCallbackInterfaceObjectClass {}
impl NonCallbackInterfaceObjectClass {
/// Create a new `NonCallbackInterfaceObjectClass` structure.
pub const fn new(constructor_behavior: &'static InterfaceConstructorBehavior,
pub const fn new(
constructor_behavior: &'static InterfaceConstructorBehavior,
string_rep: &'static [u8],
proto_id: PrototypeList::ID,
proto_depth: u16)
-> NonCallbackInterfaceObjectClass {
proto_depth: u16,
) -> NonCallbackInterfaceObjectClass {
NonCallbackInterfaceObjectClass {
class: Class {
name: b"Function\0" as *const _ as *const libc::c_char,
@ -74,9 +75,7 @@ impl NonCallbackInterfaceObjectClass {
/// cast own reference to `JSClass` reference
pub fn as_jsclass(&self) -> &JSClass {
unsafe {
&*(self as *const _ as *const JSClass)
}
unsafe { &*(self as *const _ as *const JSClass) }
}
}
@ -124,8 +123,7 @@ impl InterfaceConstructorBehavior {
}
/// A trace hook.
pub type TraceHook =
unsafe extern "C" fn(trc: *mut JSTracer, obj: *mut JSObject);
pub type TraceHook = unsafe extern "C" fn(trc: *mut JSTracer, obj: *mut JSObject);
/// Create a global object with the given class.
pub unsafe fn create_global_object(
@ -133,18 +131,21 @@ pub unsafe fn create_global_object(
class: &'static JSClass,
private: *const libc::c_void,
trace: TraceHook,
mut rval: MutableHandleObject) {
mut rval: MutableHandleObject,
) {
assert!(rval.is_null());
let mut options = CompartmentOptions::default();
options.creationOptions_.traceGlobal_ = Some(trace);
options.creationOptions_.sharedMemoryAndAtomics_ = true;
rval.set(JS_NewGlobalObject(cx,
rval.set(JS_NewGlobalObject(
cx,
class,
ptr::null_mut(),
OnNewGlobalHookOption::DontFireOnNewGlobalHook,
&options));
&options,
));
assert!(!rval.is_null());
// Initialize the reserved slots before doing anything that can GC, to
@ -166,7 +167,8 @@ pub unsafe fn create_callback_interface_object(
global: HandleObject,
constants: &[Guard<&[ConstantSpec]>],
name: &[u8],
mut rval: MutableHandleObject) {
mut rval: MutableHandleObject,
) {
assert!(!constants.is_empty());
rval.set(JS_NewObject(cx, ptr::null()));
assert!(!rval.is_null());
@ -184,8 +186,17 @@ pub unsafe fn create_interface_prototype_object(
regular_properties: &[Guard<&'static [JSPropertySpec]>],
constants: &[Guard<&[ConstantSpec]>],
unscopable_names: &[&[u8]],
rval: MutableHandleObject) {
create_object(cx, proto, class, regular_methods, regular_properties, constants, rval);
rval: MutableHandleObject,
) {
create_object(
cx,
proto,
class,
regular_methods,
regular_properties,
constants,
rval,
);
if !unscopable_names.is_empty() {
rooted!(in(cx) let mut unscopable_obj = ptr::null_mut::<JSObject>());
@ -196,8 +207,12 @@ pub unsafe fn create_interface_prototype_object(
rooted!(in(cx) let unscopable_id = RUST_SYMBOL_TO_JSID(unscopable_symbol));
assert!(JS_DefinePropertyById4(
cx, rval.handle(), unscopable_id.handle(), unscopable_obj.handle(),
JSPROP_READONLY as u32))
cx,
rval.handle(),
unscopable_id.handle(),
unscopable_obj.handle(),
JSPROP_READONLY as u32
))
}
}
@ -213,15 +228,22 @@ pub unsafe fn create_noncallback_interface_object(
interface_prototype_object: HandleObject,
name: &[u8],
length: u32,
rval: MutableHandleObject) {
create_object(cx,
rval: MutableHandleObject,
) {
create_object(
cx,
proto,
class.as_jsclass(),
static_methods,
static_properties,
constants,
rval);
assert!(JS_LinkConstructorAndPrototype(cx, rval.handle(), interface_prototype_object));
rval,
);
assert!(JS_LinkConstructorAndPrototype(
cx,
rval.handle(),
interface_prototype_object
));
define_name(cx, rval.handle(), name);
define_length(cx, rval.handle(), i32::try_from(length).expect("overflow"));
define_on_global_object(cx, global, name, rval.handle());
@ -232,26 +254,31 @@ pub unsafe fn create_named_constructors(
cx: *mut JSContext,
global: HandleObject,
named_constructors: &[(ConstructorClassHook, &[u8], u32)],
interface_prototype_object: HandleObject) {
interface_prototype_object: HandleObject,
) {
rooted!(in(cx) let mut constructor = ptr::null_mut::<JSObject>());
for &(native, name, arity) in named_constructors {
assert_eq!(*name.last().unwrap(), b'\0');
let fun = JS_NewFunction(cx,
let fun = JS_NewFunction(
cx,
Some(native),
arity,
JSFUN_CONSTRUCTOR,
name.as_ptr() as *const libc::c_char);
name.as_ptr() as *const libc::c_char,
);
assert!(!fun.is_null());
constructor.set(JS_GetFunctionObject(fun));
assert!(!constructor.is_null());
assert!(JS_DefineProperty2(cx,
assert!(JS_DefineProperty2(
cx,
constructor.handle(),
b"prototype\0".as_ptr() as *const libc::c_char,
interface_prototype_object,
(JSPROP_PERMANENT | JSPROP_READONLY) as u32));
(JSPROP_PERMANENT | JSPROP_READONLY) as u32
));
define_on_global_object(cx, global, name, constructor.handle());
}
@ -265,7 +292,8 @@ pub unsafe fn create_object(
methods: &[Guard<&'static [JSFunctionSpec]>],
properties: &[Guard<&'static [JSPropertySpec]>],
constants: &[Guard<&[ConstantSpec]>],
mut rval: MutableHandleObject) {
mut rval: MutableHandleObject,
) {
rval.set(JS_NewObjectWithUniqueType(cx, class, proto));
assert!(!rval.is_null());
define_guarded_methods(cx, rval.handle(), methods);
@ -277,7 +305,8 @@ pub unsafe fn create_object(
pub unsafe fn define_guarded_constants(
cx: *mut JSContext,
obj: HandleObject,
constants: &[Guard<&[ConstantSpec]>]) {
constants: &[Guard<&[ConstantSpec]>],
) {
for guard in constants {
if let Some(specs) = guard.expose(cx, obj) {
define_constants(cx, obj, specs);
@ -289,7 +318,8 @@ pub unsafe fn define_guarded_constants(
pub unsafe fn define_guarded_methods(
cx: *mut JSContext,
obj: HandleObject,
methods: &[Guard<&'static [JSFunctionSpec]>]) {
methods: &[Guard<&'static [JSFunctionSpec]>],
) {
for guard in methods {
if let Some(specs) = guard.expose(cx, obj) {
define_methods(cx, obj, specs).unwrap();
@ -301,7 +331,8 @@ pub unsafe fn define_guarded_methods(
pub unsafe fn define_guarded_properties(
cx: *mut JSContext,
obj: HandleObject,
properties: &[Guard<&'static [JSPropertySpec]>]) {
properties: &[Guard<&'static [JSPropertySpec]>],
) {
for guard in properties {
if let Some(specs) = guard.expose(cx, obj) {
define_properties(cx, obj, specs).unwrap();
@ -323,13 +354,16 @@ pub unsafe fn define_on_global_object(
cx: *mut JSContext,
global: HandleObject,
name: &[u8],
obj: HandleObject) {
obj: HandleObject,
) {
assert_eq!(*name.last().unwrap(), b'\0');
assert!(JS_DefineProperty2(cx,
assert!(JS_DefineProperty2(
cx,
global,
name.as_ptr() as *const libc::c_char,
obj,
JSPROP_RESOLVING));
JSPROP_RESOLVING
));
}
const OBJECT_OPS: ObjectOps = ObjectOps {
@ -344,10 +378,11 @@ const OBJECT_OPS: ObjectOps = ObjectOps {
funToString: Some(fun_to_string_hook),
};
unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
unsafe extern "C" fn fun_to_string_hook(
cx: *mut JSContext,
obj: RawHandleObject,
_is_to_source: bool)
-> *mut JSString {
_is_to_source: bool,
) -> *mut JSString {
let js_class = get_object_class(obj.get());
assert!(!js_class.is_null());
let repr = (*(js_class as *const NonCallbackInterfaceObjectClass)).representation;
@ -358,17 +393,19 @@ unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
}
/// Hook for instanceof on interface objects.
unsafe extern "C" fn has_instance_hook(cx: *mut JSContext,
unsafe extern "C" fn has_instance_hook(
cx: *mut JSContext,
obj: RawHandleObject,
value: RawMutableHandleValue,
rval: *mut bool) -> bool {
rval: *mut bool,
) -> bool {
let obj_raw = HandleObject::from_raw(obj);
let val_raw = HandleValue::from_raw(value.handle());
match has_instance(cx, obj_raw, val_raw) {
Ok(result) => {
*rval = result;
true
}
},
Err(()) => false,
}
}
@ -378,8 +415,8 @@ unsafe extern "C" fn has_instance_hook(cx: *mut JSContext,
unsafe fn has_instance(
cx: *mut JSContext,
interface_object: HandleObject,
value: HandleValue)
-> Result<bool, ()> {
value: HandleValue,
) -> Result<bool, ()> {
if !value.is_object() {
// Step 1.
return Ok(false);
@ -391,8 +428,10 @@ unsafe fn has_instance(
let js_class = get_object_class(interface_object.get());
let object_class = &*(js_class as *const NonCallbackInterfaceObjectClass);
if let Ok(dom_class) = get_dom_class(UncheckedUnwrapObject(value.get(),
/* stopAtWindowProxy = */ 0)) {
if let Ok(dom_class) = get_dom_class(UncheckedUnwrapObject(
value.get(),
/* stopAtWindowProxy = */ 0,
)) {
if dom_class.interface_chain[object_class.proto_depth as usize] == object_class.proto_id {
// Step 4.
return Ok(true);
@ -424,7 +463,8 @@ unsafe fn has_instance(
unsafe fn create_unscopable_object(
cx: *mut JSContext,
names: &[&[u8]],
mut rval: MutableHandleObject) {
mut rval: MutableHandleObject,
) {
assert!(!names.is_empty());
assert!(rval.is_null());
rval.set(JS_NewPlainObject(cx));
@ -445,26 +485,30 @@ unsafe fn define_name(cx: *mut JSContext, obj: HandleObject, name: &[u8]) {
assert_eq!(*name.last().unwrap(), b'\0');
rooted!(in(cx) let name = JS_AtomizeAndPinString(cx, name.as_ptr() as *const libc::c_char));
assert!(!name.is_null());
assert!(JS_DefineProperty3(cx,
assert!(JS_DefineProperty3(
cx,
obj,
b"name\0".as_ptr() as *const libc::c_char,
name.handle().into(),
JSPROP_READONLY as u32));
JSPROP_READONLY as u32
));
}
unsafe fn define_length(cx: *mut JSContext, obj: HandleObject, length: i32) {
assert!(JS_DefineProperty4(cx,
assert!(JS_DefineProperty4(
cx,
obj,
b"length\0".as_ptr() as *const libc::c_char,
length,
JSPROP_READONLY as u32));
JSPROP_READONLY as u32
));
}
unsafe extern "C" fn invalid_constructor(
cx: *mut JSContext,
_argc: libc::c_uint,
_vp: *mut JSVal)
-> bool {
_vp: *mut JSVal,
) -> bool {
throw_type_error(cx, "Illegal constructor.");
false
}
@ -472,8 +516,8 @@ unsafe extern "C" fn invalid_constructor(
unsafe extern "C" fn non_new_constructor(
cx: *mut JSContext,
_argc: libc::c_uint,
_vp: *mut JSVal)
-> bool {
_vp: *mut JSVal,
) -> bool {
throw_type_error(cx, "This constructor needs to be called with `new`.");
false
}

View file

@ -59,10 +59,11 @@ pub struct IterableIterator<T: DomObject + JSTraceable + Iterable> {
impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
/// Create a new iterator instance for the provided iterable DOM interface.
pub fn new(iterable: &T,
pub fn new(
iterable: &T,
type_: IteratorType,
wrap: unsafe fn(*mut JSContext, &GlobalScope, Box<IterableIterator<T>>)
-> DomRoot<Self>) -> DomRoot<Self> {
wrap: unsafe fn(*mut JSContext, &GlobalScope, Box<IterableIterator<T>>) -> DomRoot<Self>,
) -> DomRoot<Self> {
let iterator = Box::new(IterableIterator {
reflector: Reflector::new(),
type_: type_,
@ -84,37 +85,45 @@ impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
match self.type_ {
IteratorType::Keys => {
unsafe {
self.iterable.get_key_at_index(index).to_jsval(cx, value.handle_mut());
self.iterable
.get_key_at_index(index)
.to_jsval(cx, value.handle_mut());
}
dict_return(cx, rval.handle_mut(), false, value.handle())
}
},
IteratorType::Values => {
unsafe {
self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut());
self.iterable
.get_value_at_index(index)
.to_jsval(cx, value.handle_mut());
}
dict_return(cx, rval.handle_mut(), false, value.handle())
}
},
IteratorType::Entries => {
rooted!(in(cx) let mut key = UndefinedValue());
unsafe {
self.iterable.get_key_at_index(index).to_jsval(cx, key.handle_mut());
self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut());
self.iterable
.get_key_at_index(index)
.to_jsval(cx, key.handle_mut());
self.iterable
.get_value_at_index(index)
.to_jsval(cx, value.handle_mut());
}
key_and_value_return(cx, rval.handle_mut(), key.handle(), value.handle())
}
},
}
};
self.index.set(index + 1);
result.map(|_| {
NonNull::new(rval.get()).expect("got a null pointer")
})
result.map(|_| NonNull::new(rval.get()).expect("got a null pointer"))
}
}
fn dict_return(cx: *mut JSContext,
fn dict_return(
cx: *mut JSContext,
mut result: MutableHandleObject,
done: bool,
value: HandleValue) -> Fallible<()> {
value: HandleValue,
) -> Fallible<()> {
let mut dict = IterableKeyOrValueResult::empty();
dict.done = done;
dict.value.set(value.get());
@ -126,16 +135,20 @@ fn dict_return(cx: *mut JSContext,
Ok(())
}
fn key_and_value_return(cx: *mut JSContext,
fn key_and_value_return(
cx: *mut JSContext,
mut result: MutableHandleObject,
key: HandleValue,
value: HandleValue) -> Fallible<()> {
value: HandleValue,
) -> Fallible<()> {
let mut dict = IterableKeyAndValueResult::empty();
dict.done = false;
dict.value = Some(vec![key, value]
dict.value = Some(
vec![key, value]
.into_iter()
.map(|handle| RootedTraceableBox::from_box(Heap::boxed(handle.get())))
.collect());
.collect(),
);
rooted!(in(cx) let mut dict_value = UndefinedValue());
unsafe {
dict.to_jsval(cx, dict_value.handle_mut());

View file

@ -49,24 +49,37 @@ impl<T> Deref for MozMap<T> {
}
impl<T, C> FromJSValConvertible for MozMap<T>
where T: FromJSValConvertible<Config=C>,
where
T: FromJSValConvertible<Config = C>,
C: Clone,
{
type Config = C;
unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, config: C)
-> Result<ConversionResult<Self>, ()> {
unsafe fn from_jsval(
cx: *mut JSContext,
value: HandleValue,
config: C,
) -> Result<ConversionResult<Self>, ()> {
if !value.is_object() {
return Ok(ConversionResult::Failure("MozMap value was not an object".into()));
return Ok(ConversionResult::Failure(
"MozMap value was not an object".into(),
));
}
rooted!(in(cx) let object = value.to_object());
let ids = IdVector::new(cx);
if !GetPropertyKeys(cx, object.handle(), JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, ids.get()) {
if !GetPropertyKeys(
cx,
object.handle(),
JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS,
ids.get(),
) {
// TODO: can GetPropertyKeys fail?
// (it does so if the object has duplicate keys)
// https://github.com/servo/servo/issues/21462
report_pending_exception(cx, false);
return Ok(ConversionResult::Failure("Getting MozMap value property keys failed".into()));
return Ok(ConversionResult::Failure(
"Getting MozMap value property keys failed".into(),
));
}
let mut map = HashMap::new();
@ -90,9 +103,7 @@ impl<T, C> FromJSValConvertible for MozMap<T>
}
}
Ok(ConversionResult::Success(MozMap {
map: map,
}))
Ok(ConversionResult::Success(MozMap { map: map }))
}
}
@ -107,12 +118,14 @@ impl<T: ToJSValConvertible> ToJSValConvertible for MozMap<T> {
let key = key.encode_utf16().collect::<Vec<_>>();
value.to_jsval(cx, js_value.handle_mut());
assert!(JS_DefineUCProperty2(cx,
assert!(JS_DefineUCProperty2(
cx,
js_object.handle(),
key.as_ptr(),
key.len(),
js_value.handle(),
JSPROP_ENUMERATE as u32));
JSPROP_ENUMERATE as u32
));
}
rval.set(ObjectValue(js_object.handle().get()));

View file

@ -36,7 +36,8 @@ pub unsafe fn create_namespace_object(
class: &'static NamespaceObjectClass,
methods: &[Guard<&'static [JSFunctionSpec]>],
name: &[u8],
rval: MutableHandleObject) {
rval: MutableHandleObject,
) {
create_object(cx, proto, &class.0, methods, &[], &[], rval);
define_on_global_object(cx, global, name, rval.handle());
}

View file

@ -26,8 +26,10 @@ 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)
}
}

View file

@ -30,12 +30,12 @@ use js::rust::wrappers::JS_AlreadyHasOwnPropertyById;
use js::rust::wrappers::JS_NewObjectWithGivenProto;
use std::ptr;
/// Determine if this id shadows any existing properties for this proxy.
pub unsafe extern "C" fn shadow_check_callback(cx: *mut JSContext,
pub unsafe extern "C" fn shadow_check_callback(
cx: *mut JSContext,
object: RawHandleObject,
id: RawHandleId)
-> DOMProxyShadowsResult {
id: RawHandleId,
) -> DOMProxyShadowsResult {
// TODO: support OverrideBuiltins when #12978 is fixed.
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
@ -59,19 +59,19 @@ pub unsafe extern "C" fn shadow_check_callback(cx: *mut JSContext,
/// Initialize the infrastructure for DOM proxy objects.
pub unsafe fn init() {
SetDOMProxyInformation(GetProxyHandlerFamily(),
Some(shadow_check_callback));
SetDOMProxyInformation(GetProxyHandlerFamily(), Some(shadow_check_callback));
}
/// Invoke the [[GetOwnProperty]] trap (`getOwnPropertyDescriptor`) on `proxy`,
/// 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 "C" fn get_property_descriptor(cx: *mut JSContext,
pub unsafe extern "C" fn get_property_descriptor(
cx: *mut JSContext,
proxy: RawHandleObject,
id: RawHandleId,
desc: RawMutableHandle<PropertyDescriptor>)
-> bool {
desc: RawMutableHandle<PropertyDescriptor>,
) -> bool {
let handler = GetProxyHandler(proxy.get());
if !InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) {
return false;
@ -91,23 +91,25 @@ pub unsafe extern "C" fn get_property_descriptor(cx: *mut JSContext,
}
/// Defines an expando on the given `proxy`.
pub unsafe extern "C" fn define_property(cx: *mut JSContext,
pub unsafe extern "C" fn define_property(
cx: *mut JSContext,
proxy: RawHandleObject,
id: RawHandleId,
desc: RawHandle<PropertyDescriptor>,
result: *mut ObjectOpResult)
-> bool {
result: *mut ObjectOpResult,
) -> bool {
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
ensure_expando_object(cx, proxy, expando.handle_mut());
JS_DefinePropertyById(cx, expando.handle().into(), id, desc, result)
}
/// Deletes an expando off the given `proxy`.
pub unsafe extern "C" fn delete(cx: *mut JSContext,
pub unsafe extern "C" fn delete(
cx: *mut JSContext,
proxy: RawHandleObject,
id: RawHandleId,
bp: *mut ObjectOpResult)
-> bool {
bp: *mut ObjectOpResult,
) -> bool {
rooted!(in(cx) let mut expando = ptr::null_mut::<JSObject>());
get_expando_object(proxy, expando.handle_mut());
if expando.is_null() {
@ -119,19 +121,21 @@ pub unsafe extern "C" fn delete(cx: *mut JSContext,
}
/// Controls whether the Extensible bit can be changed
pub unsafe extern "C" fn prevent_extensions(_cx: *mut JSContext,
pub unsafe extern "C" fn prevent_extensions(
_cx: *mut JSContext,
_proxy: RawHandleObject,
result: *mut ObjectOpResult)
-> bool {
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 "C" fn is_extensible(_cx: *mut JSContext,
pub unsafe extern "C" fn is_extensible(
_cx: *mut JSContext,
_proxy: RawHandleObject,
succeeded: *mut bool)
-> bool {
succeeded: *mut bool,
) -> bool {
*succeeded = true;
true
}
@ -145,11 +149,12 @@ pub unsafe extern "C" fn is_extensible(_cx: *mut JSContext,
/// This implementation always handles the case of the ordinary
/// `[[GetPrototypeOf]]` behavior. An alternative implementation will be
/// necessary for the Location object.
pub unsafe extern "C" fn get_prototype_if_ordinary(_: *mut JSContext,
pub unsafe extern "C" fn get_prototype_if_ordinary(
_: *mut JSContext,
proxy: RawHandleObject,
is_ordinary: *mut bool,
proto: RawMutableHandleObject)
-> bool {
proto: RawMutableHandleObject,
) -> bool {
*is_ordinary = true;
proto.set(GetStaticPrototype(proxy.get()));
true
@ -169,11 +174,19 @@ pub unsafe fn get_expando_object(obj: RawHandleObject, mut expando: MutableHandl
/// Get the expando object, or create it if it doesn't exist yet.
/// Fails on JSAPI failure.
pub unsafe fn ensure_expando_object(cx: *mut JSContext, obj: RawHandleObject, mut expando: MutableHandleObject) {
pub unsafe fn ensure_expando_object(
cx: *mut JSContext,
obj: RawHandleObject,
mut expando: MutableHandleObject,
) {
assert!(is_dom_proxy(obj.get()));
get_expando_object(obj, expando);
if expando.is_null() {
expando.set(JS_NewObjectWithGivenProto(cx, ptr::null_mut(), HandleObject::null()));
expando.set(JS_NewObjectWithGivenProto(
cx,
ptr::null_mut(),
HandleObject::null(),
));
assert!(!expando.is_null());
SetProxyPrivate(obj.get(), &ObjectValue(expando.get()));
@ -182,9 +195,11 @@ pub unsafe fn ensure_expando_object(cx: *mut JSContext, obj: RawHandleObject, mu
/// Set the property descriptor's object to `obj` and set it to enumerable,
/// and writable if `readonly` is true.
pub fn fill_property_descriptor(mut desc: MutableHandle<PropertyDescriptor>,
pub fn fill_property_descriptor(
mut desc: MutableHandle<PropertyDescriptor>,
obj: *mut JSObject,
attrs: u32) {
attrs: u32,
) {
desc.obj = obj;
desc.attrs = attrs;
desc.getter = None;

View file

@ -39,9 +39,9 @@ use std::rc::Rc;
use std::sync::{Arc, Weak};
use task::TaskOnce;
#[allow(missing_docs)] // FIXME
mod dummy { // Attributes dont apply through the macro.
mod dummy {
// Attributes dont apply through the macro.
use std::cell::RefCell;
use std::rc::Rc;
use super::LiveDOMReferences;
@ -50,7 +50,6 @@ mod dummy { // Attributes dont apply through the macro.
}
pub use self::dummy::LIVE_REFERENCES;
/// A pointer to a Rust DOM object that needs to be destroyed.
pub struct TrustedReference(*const libc::c_void);
unsafe impl Send for TrustedReference {}
@ -98,19 +97,28 @@ impl TrustedPromise {
LIVE_REFERENCES.with(|ref r| {
let r = r.borrow();
let live_references = r.as_ref().unwrap();
assert_eq!(self.owner_thread, (&*live_references) as *const _ as *const libc::c_void);
assert_eq!(
self.owner_thread,
(&*live_references) as *const _ as *const libc::c_void
);
// Borrow-check error requires the redundant `let promise = ...; promise` here.
let promise = match live_references.promise_table.borrow_mut().entry(self.dom_object) {
let promise = match live_references
.promise_table
.borrow_mut()
.entry(self.dom_object)
{
Occupied(mut entry) => {
let promise = {
let promises = entry.get_mut();
promises.pop().expect("rooted promise list unexpectedly empty")
promises
.pop()
.expect("rooted promise list unexpectedly empty")
};
if entry.get().is_empty() {
entry.remove();
}
promise
}
},
Vacant(_) => unreachable!(),
};
promise
@ -182,9 +190,7 @@ impl<T: DomObject> Trusted<T> {
let live_references = r.as_ref().unwrap();
self.owner_thread == (&*live_references) as *const _ as *const libc::c_void
}));
unsafe {
DomRoot::from_ref(&*(self.refcount.0 as *const T))
}
unsafe { DomRoot::from_ref(&*(self.refcount.0 as *const T)) }
}
}
@ -246,15 +252,15 @@ impl LiveDOMReferences {
let refcount = Arc::new(TrustedReference::new(ptr));
entry.insert(Arc::downgrade(&refcount));
refcount
}
},
}
}
}
/// Remove null entries from the live references table
fn remove_nulls<K: Eq + Hash + Clone, V> (table: &mut HashMap<K, Weak<V>>) {
let to_remove: Vec<K> =
table.iter()
fn remove_nulls<K: Eq + Hash + Clone, V>(table: &mut HashMap<K, Weak<V>>) {
let to_remove: Vec<K> = table
.iter()
.filter(|&(_, value)| Weak::upgrade(value).is_none())
.map(|(key, _)| key.clone())
.collect();

View file

@ -16,14 +16,14 @@ use std::default::Default;
pub fn reflect_dom_object<T, U>(
obj: Box<T>,
global: &U,
wrap_fn: unsafe fn(*mut JSContext, &GlobalScope, Box<T>) -> DomRoot<T>)
-> DomRoot<T>
where T: DomObject, U: DerivedFrom<GlobalScope>
wrap_fn: unsafe fn(*mut JSContext, &GlobalScope, Box<T>) -> DomRoot<T>,
) -> DomRoot<T>
where
T: DomObject,
U: DerivedFrom<GlobalScope>,
{
let global_scope = global.upcast();
unsafe {
wrap_fn(global_scope.get_cx(), global_scope, obj)
}
unsafe { wrap_fn(global_scope.get_cx(), global_scope, obj) }
}
/// A struct to store a reference to the reflector of a DOM object.
@ -79,7 +79,10 @@ pub trait DomObject: 'static {
fn reflector(&self) -> &Reflector;
/// Returns the global scope of the realm that the DomObject was created in.
fn global(&self) -> DomRoot<GlobalScope> where Self: Sized {
fn global(&self) -> DomRoot<GlobalScope>
where
Self: Sized,
{
GlobalScope::from_reflector(self)
}
}

View file

@ -96,9 +96,7 @@ where
trace_reflector(tracer, "on stack", &self.0);
}
}
unsafe {
&*(self.reflector() as *const Reflector as *const ReflectorStackRoot)
}
unsafe { &*(self.reflector() as *const Reflector as *const ReflectorStackRoot) }
}
}
@ -131,15 +129,17 @@ pub type DomRoot<T> = Root<Dom<T>>;
impl<T: Castable> DomRoot<T> {
/// Cast a DOM object root upwards to one of the interfaces it derives from.
pub fn upcast<U>(root: DomRoot<T>) -> DomRoot<U>
where U: Castable,
T: DerivedFrom<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: DomRoot<T>) -> Option<DomRoot<U>>
where U: DerivedFrom<T>
where
U: DerivedFrom<T>,
{
if root.is::<U>() {
Some(unsafe { mem::transmute(root) })
@ -207,9 +207,7 @@ pub struct ThreadLocalStackRoots<'a>(PhantomData<&'a u32>);
impl<'a> ThreadLocalStackRoots<'a> {
pub fn new(roots: &'a RootCollection) -> Self {
STACK_ROOTS.with(|ref r| {
r.set(Some(roots))
});
STACK_ROOTS.with(|ref r| r.set(Some(roots)));
ThreadLocalStackRoots(PhantomData)
}
}
@ -363,9 +361,7 @@ unsafe impl<T: DomObject> JSTraceable for Dom<T> {
#[cfg(not(all(feature = "unstable", debug_assertions)))]
let trace_info = "for DOM object on heap";
trace_reflector(trc,
trace_info,
(*self.ptr.as_ptr()).reflector());
trace_reflector(trc, trace_info, (*self.ptr.as_ptr()).reflector());
}
}
@ -379,8 +375,9 @@ pub struct LayoutDom<T> {
impl<T: Castable> LayoutDom<T> {
/// Cast a DOM object root upwards to one of the interfaces it derives from.
pub fn upcast<U>(&self) -> LayoutDom<U>
where U: Castable,
T: DerivedFrom<U>
where
U: Castable,
T: DerivedFrom<U>,
{
debug_assert!(thread_state::get().is_layout());
let ptr: *mut T = self.ptr.as_ptr();
@ -391,7 +388,8 @@ impl<T: Castable> LayoutDom<T> {
/// Cast a DOM object downwards to one of the interfaces it might implement.
pub fn downcast<U>(&self) -> Option<LayoutDom<U>>
where U: DerivedFrom<T>
where
U: DerivedFrom<T>,
{
debug_assert!(thread_state::get().is_layout());
unsafe {
@ -429,7 +427,6 @@ impl<'a, T: DomObject> PartialEq<&'a T> for Dom<T> {
}
}
impl<T> Eq for Dom<T> {}
impl<T> PartialEq for LayoutDom<T> {
@ -452,7 +449,7 @@ impl<T> Hash for LayoutDom<T> {
}
}
impl <T> Clone for Dom<T> {
impl<T> Clone for Dom<T> {
#[inline]
#[allow(unrooted_must_root)]
fn clone(&self) -> Dom<T> {
@ -463,7 +460,7 @@ impl <T> Clone for Dom<T> {
}
}
impl <T> Clone for LayoutDom<T> {
impl<T> Clone for LayoutDom<T> {
#[inline]
fn clone(&self) -> LayoutDom<T> {
debug_assert!(thread_state::get().is_layout());
@ -516,9 +513,7 @@ impl<T: DomObject> MutDom<T> {
/// Get the value in this `MutDom`.
pub fn get(&self) -> DomRoot<T> {
debug_assert!(thread_state::get().is_script());
unsafe {
DomRoot::from_ref(&*ptr::read(self.val.get()))
}
unsafe { DomRoot::from_ref(&*ptr::read(self.val.get())) }
}
}
@ -531,17 +526,13 @@ impl<T: DomObject> MallocSizeOf for MutDom<T> {
impl<T: DomObject> PartialEq for MutDom<T> {
fn eq(&self, other: &Self) -> bool {
unsafe {
*self.val.get() == *other.val.get()
}
unsafe { *self.val.get() == *other.val.get() }
}
}
impl<T: DomObject + PartialEq> PartialEq<T> for MutDom<T> {
fn eq(&self, other: &T) -> bool {
unsafe {
**self.val.get() == *other
}
unsafe { **self.val.get() == *other }
}
}
@ -569,7 +560,8 @@ impl<T: DomObject> MutNullableDom<T> {
/// Retrieve a copy of the current inner value. If it is `None`, it is
/// initialized with the result of `cb` first.
pub fn or_init<F>(&self, cb: F) -> DomRoot<T>
where F: FnOnce() -> DomRoot<T>
where
F: FnOnce() -> DomRoot<T>,
{
debug_assert!(thread_state::get().is_script());
match self.get() {
@ -594,9 +586,7 @@ impl<T: DomObject> MutNullableDom<T> {
#[allow(unrooted_must_root)]
pub fn get(&self) -> Option<DomRoot<T>> {
debug_assert!(thread_state::get().is_script());
unsafe {
ptr::read(self.ptr.get()).map(|o| DomRoot::from_ref(&*o))
}
unsafe { ptr::read(self.ptr.get()).map(|o| DomRoot::from_ref(&*o)) }
}
/// Set this `MutNullableDom` to the given value.
@ -617,17 +607,13 @@ impl<T: DomObject> MutNullableDom<T> {
impl<T: DomObject> PartialEq for MutNullableDom<T> {
fn eq(&self, other: &Self) -> bool {
unsafe {
*self.ptr.get() == *other.ptr.get()
}
unsafe { *self.ptr.get() == *other.ptr.get() }
}
}
impl<'a, T: DomObject> PartialEq<Option<&'a T>> for MutNullableDom<T> {
fn eq(&self, other: &Option<&T>) -> bool {
unsafe {
*self.ptr.get() == other.map(Dom::from_ref)
}
unsafe { *self.ptr.get() == other.map(Dom::from_ref) }
}
}
@ -661,13 +647,14 @@ pub struct DomOnceCell<T: DomObject> {
impl<T> DomOnceCell<T>
where
T: DomObject
T: DomObject,
{
/// Retrieve a copy of the current inner value. If it is `None`, it is
/// initialized with the result of `cb` first.
#[allow(unrooted_must_root)]
pub fn init_once<F>(&self, cb: F) -> &T
where F: FnOnce() -> DomRoot<T>
where
F: FnOnce() -> DomRoot<T>,
{
debug_assert!(thread_state::get().is_script());
&self.ptr.init_once(|| Dom::from_ref(&cb()))
@ -725,14 +712,17 @@ pub trait OptionalHeapSetter {
fn set(&mut self, v: Option<Self::Value>);
}
impl<T: GCMethods + Copy> OptionalHeapSetter for Option<Heap<T>> where Heap<T>: Default {
impl<T: GCMethods + Copy> OptionalHeapSetter for Option<Heap<T>>
where
Heap<T>: Default,
{
type Value = T;
fn set(&mut self, v: Option<T>) {
let v = match v {
None => {
*self = None;
return;
}
},
Some(v) => v,
};

View file

@ -36,9 +36,7 @@ pub unsafe fn trace(tracer: *mut JSTracer) {
}
pub fn is_execution_stack_empty() -> bool {
STACK.with(|stack| {
stack.borrow().is_empty()
})
STACK.with(|stack| stack.borrow().is_empty())
}
/// RAII struct that pushes and pops entries from the script settings stack.
@ -69,9 +67,10 @@ impl Drop for AutoEntryScript {
STACK.with(|stack| {
let mut stack = stack.borrow_mut();
let entry = stack.pop().unwrap();
assert_eq!(&*entry.global as *const GlobalScope,
&*self.global as *const GlobalScope,
"Dropped AutoEntryScript out of order.");
assert_eq!(
&*entry.global as *const GlobalScope, &*self.global as *const GlobalScope,
"Dropped AutoEntryScript out of order."
);
assert_eq!(entry.kind, StackEntryKind::Entry);
trace!("Clean up after running script with {:p}", &*entry.global);
});
@ -87,8 +86,10 @@ impl Drop for AutoEntryScript {
///
/// ["entry"]: https://html.spec.whatwg.org/multipage/#entry
pub fn entry_global() -> DomRoot<GlobalScope> {
STACK.with(|stack| {
stack.borrow()
STACK
.with(|stack| {
stack
.borrow()
.iter()
.rev()
.find(|entry| entry.kind == StackEntryKind::Entry)
@ -133,11 +134,15 @@ impl Drop for AutoIncumbentScript {
let mut stack = stack.borrow_mut();
let entry = stack.pop().unwrap();
// Step 3.
assert_eq!(&*entry.global as *const GlobalScope as usize,
self.global,
"Dropped AutoIncumbentScript out of order.");
assert_eq!(
&*entry.global as *const GlobalScope as usize, self.global,
"Dropped AutoIncumbentScript out of order."
);
assert_eq!(entry.kind, StackEntryKind::Incumbent);
trace!("Clean up after running a callback with {:p}", &*entry.global);
trace!(
"Clean up after running a callback with {:p}",
&*entry.global
);
});
unsafe {
// Step 1-2.
@ -169,7 +174,8 @@ pub fn incumbent_global() -> Option<DomRoot<GlobalScope>> {
// Step 2: nothing from the JS engine. Let's use whatever's on the explicit stack.
STACK.with(|stack| {
stack.borrow()
stack
.borrow()
.last()
.map(|entry| DomRoot::from_ref(&*entry.global))
})

View file

@ -82,7 +82,6 @@ impl ops::Deref for ByteString {
#[derive(Clone, Default, MallocSizeOf)]
pub struct USVString(pub String);
/// Returns whether `s` is a `token`, as defined by
/// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-17).
pub fn is_token(s: &[u8]) -> bool {
@ -93,31 +92,14 @@ pub fn is_token(s: &[u8]) -> bool {
// 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,
}
})
}
/// A DOMString.
///
/// This type corresponds to the [`DOMString`](idl) type in WebIDL.
@ -196,14 +178,16 @@ impl DOMString {
/// Removes leading and trailing ASCII whitespaces according to
/// <https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace>.
pub fn strip_leading_and_trailing_ascii_whitespace(&mut self) {
if self.0.len() == 0 { return; }
if self.0.len() == 0 {
return;
}
let last_non_whitespace = match self.0.rfind(|ref c| !char::is_ascii_whitespace(c)) {
Some(idx) => idx + 1,
None => {
self.0.clear();
return;
}
},
};
let first_non_whitespace = self.0.find(|ref c| !char::is_ascii_whitespace(c)).unwrap();
@ -231,17 +215,21 @@ impl DOMString {
Done,
Error,
}
let next_state = |valid: bool, next: State| -> State { if valid { next } else { State::Error } };
let next_state = |valid: bool, next: State| -> State {
if valid {
next
} else {
State::Error
}
};
let state = self.chars().fold(State::HourHigh, |state, c| {
match state {
// Step 1 "HH"
State::HourHigh => {
match c {
State::HourHigh => match c {
'0' | '1' => State::HourLow09,
'2' => State::HourLow03,
_ => State::Error,
}
},
State::HourLow09 => next_state(c.is_digit(10), State::MinuteColon),
State::HourLow03 => next_state(c.is_digit(4), State::MinuteColon),
@ -323,15 +311,21 @@ impl DOMString {
/// where date and time are both valid, and the time string must be as short as possible
/// https://html.spec.whatwg.org/multipage/#valid-normalised-local-date-and-time-string
pub fn convert_valid_normalized_local_date_and_time_string(&mut self) -> Result<(), ()> {
let ((year, month, day), (hour, minute, second)) = parse_local_date_and_time_string(&*self.0)?;
let ((year, month, day), (hour, minute, second)) =
parse_local_date_and_time_string(&*self.0)?;
if second == 0.0 {
self.0 = format!("{:04}-{:02}-{:02}T{:02}:{:02}", year, month, day, hour, minute);
self.0 = format!(
"{:04}-{:02}-{:02}T{:02}:{:02}",
year, month, day, hour, minute
);
} else {
self.0 = format!("{:04}-{:02}-{:02}T{:02}:{:02}:{}", year, month, day, hour, minute, second);
self.0 = format!(
"{:04}-{:02}-{:02}T{:02}:{:02}:{}",
year, month, day, hour, minute, second
);
}
Ok(())
}
}
impl Borrow<str> for DOMString {
@ -452,7 +446,10 @@ impl<'a> Into<CowRcStr<'a>> for DOMString {
}
impl Extend<char> for DOMString {
fn extend<I>(&mut self, iterable: I) where I: IntoIterator<Item=char> {
fn extend<I>(&mut self, iterable: I)
where
I: IntoIterator<Item = char>,
{
self.0.extend(iterable)
}
}
@ -611,12 +608,12 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> {
return Err(());
}
},
None => {}
None => {},
}
second.parse::<f32>().map_err(|_| ())?
},
None => 0.0
None => 0.0,
};
// Step 8
@ -651,8 +648,8 @@ fn parse_local_date_and_time_string(value: &str) -> Result<((u32, u32, u32), (u
fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
match month_num {
1|3|5|7|8|10|12 => Ok(31),
4|6|9|11 => Ok(30),
1 | 3 | 5 | 7 | 8 | 10 | 12 => Ok(31),
4 | 6 | 9 | 11 => Ok(30),
2 => {
if is_leap_year(year_num) {
Ok(29)
@ -660,7 +657,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
Ok(28)
}
},
_ => Err(())
_ => Err(()),
}
}
@ -669,7 +666,7 @@ fn max_week_in_year(year: u32) -> u32 {
match Utc.ymd(year as i32, 1, 1).weekday() {
Weekday::Thu => 53,
Weekday::Wed if is_leap_year(year) => 53,
_ => 52
_ => 52,
}
}
@ -681,14 +678,16 @@ fn is_leap_year(year: u32) -> bool {
/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-floating-point-number-values
fn parse_floating_point_number(input: &str) -> Result<f64, ()> {
match input.trim().parse::<f64>() {
Ok(val) if !(
Ok(val)
if !(
// A valid number is the same as what rust considers to be valid,
// except for +1., NaN, and Infinity.
val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+")
) => {
) =>
{
// TODO(#19773): need consider `min`, `max`, `step`, when they are implemented
Ok(val.round())
},
_ => Err(())
}
_ => Err(()),
}
}

View file

@ -47,34 +47,38 @@ enum StructuredCloneTags {
}
#[cfg(target_pointer_width = "64")]
unsafe fn write_length(w: *mut JSStructuredCloneWriter,
length: usize) {
unsafe fn write_length(w: *mut JSStructuredCloneWriter, length: usize) {
let high: u32 = (length >> 32) as u32;
let low: u32 = length as u32;
assert!(JS_WriteUint32Pair(w, high, low));
}
#[cfg(target_pointer_width = "32")]
unsafe fn write_length(w: *mut JSStructuredCloneWriter,
length: usize) {
unsafe fn write_length(w: *mut JSStructuredCloneWriter, length: usize) {
assert!(JS_WriteUint32Pair(w, length as u32, 0));
}
#[cfg(target_pointer_width = "64")]
unsafe fn read_length(r: *mut JSStructuredCloneReader)
-> usize {
unsafe fn read_length(r: *mut JSStructuredCloneReader) -> usize {
let mut high: u32 = 0;
let mut low: u32 = 0;
assert!(JS_ReadUint32Pair(r, &mut high as *mut u32, &mut low as *mut u32));
assert!(JS_ReadUint32Pair(
r,
&mut high as *mut u32,
&mut low as *mut u32
));
return (low << high) as usize;
}
#[cfg(target_pointer_width = "32")]
unsafe fn read_length(r: *mut JSStructuredCloneReader)
-> usize {
unsafe fn read_length(r: *mut JSStructuredCloneReader) -> usize {
let mut length: u32 = 0;
let mut zero: u32 = 0;
assert!(JS_ReadUint32Pair(r, &mut length as *mut u32, &mut zero as *mut u32));
assert!(JS_ReadUint32Pair(
r,
&mut length as *mut u32,
&mut zero as *mut u32
));
return length as usize;
}
@ -86,7 +90,11 @@ impl StructuredCloneWriter {
unsafe fn write_slice(&self, v: &[u8]) {
let type_length = v.len();
write_length(self.w, type_length);
assert!(JS_WriteBytes(self.w, v.as_ptr() as *const raw::c_void, type_length));
assert!(JS_WriteBytes(
self.w,
v.as_ptr() as *const raw::c_void,
type_length
));
}
unsafe fn write_str(&self, s: &str) {
self.write_slice(s.as_bytes());
@ -101,7 +109,11 @@ impl StructuredCloneReader {
unsafe fn read_bytes(&self) -> Vec<u8> {
let mut bytes = vec![0u8; read_length(self.r)];
let blob_length = bytes.len();
assert!(JS_ReadBytes(self.r, bytes.as_mut_ptr() as *mut raw::c_void, blob_length));
assert!(JS_ReadBytes(
self.r,
bytes.as_mut_ptr() as *mut raw::c_void,
blob_length
));
return bytes;
}
unsafe fn read_str(&self) -> String {
@ -110,87 +122,105 @@ impl StructuredCloneReader {
}
}
unsafe fn read_blob(cx: *mut JSContext,
unsafe fn read_blob(
cx: *mut JSContext,
r: *mut JSStructuredCloneReader,
sc_holder: &mut StructuredCloneHolder)
-> *mut JSObject {
sc_holder: &mut StructuredCloneHolder,
) -> *mut JSObject {
let structured_reader = StructuredCloneReader { r: r };
let blob_buffer = structured_reader.read_bytes();
let type_str = structured_reader.read_str();
let target_global = GlobalScope::from_context(cx);
let blob = Blob::new(&target_global, BlobImpl::new_from_bytes(blob_buffer), type_str);
let blob = Blob::new(
&target_global,
BlobImpl::new_from_bytes(blob_buffer),
type_str,
);
let js_object = blob.reflector().get_jsobject().get();
sc_holder.blob = Some(blob);
js_object
}
unsafe fn write_blob(blob: DomRoot<Blob>,
w: *mut JSStructuredCloneWriter)
-> Result<(), ()> {
unsafe fn write_blob(blob: DomRoot<Blob>, w: *mut JSStructuredCloneWriter) -> Result<(), ()> {
let structured_writer = StructuredCloneWriter { w: w };
let blob_vec = blob.get_bytes()?;
assert!(JS_WriteUint32Pair(w, StructuredCloneTags::DomBlob as u32, 0));
assert!(JS_WriteUint32Pair(
w,
StructuredCloneTags::DomBlob as u32,
0
));
structured_writer.write_slice(&blob_vec);
structured_writer.write_str(&blob.type_string());
return Ok(())
return Ok(());
}
unsafe extern "C" fn read_callback(cx: *mut JSContext,
unsafe extern "C" fn read_callback(
cx: *mut JSContext,
r: *mut JSStructuredCloneReader,
tag: u32,
_data: u32,
closure: *mut raw::c_void)
-> *mut JSObject {
assert!(tag < StructuredCloneTags::Max as u32, "tag should be lower than StructuredCloneTags::Max");
assert!(tag > StructuredCloneTags::Min as u32, "tag should be higher than StructuredCloneTags::Min");
closure: *mut raw::c_void,
) -> *mut JSObject {
assert!(
tag < StructuredCloneTags::Max as u32,
"tag should be lower than StructuredCloneTags::Max"
);
assert!(
tag > StructuredCloneTags::Min as u32,
"tag should be higher than StructuredCloneTags::Min"
);
if tag == StructuredCloneTags::DomBlob as u32 {
return read_blob(cx, r, &mut *(closure as *mut StructuredCloneHolder))
return read_blob(cx, r, &mut *(closure as *mut StructuredCloneHolder));
}
return ptr::null_mut()
return ptr::null_mut();
}
unsafe extern "C" fn write_callback(_cx: *mut JSContext,
unsafe extern "C" fn write_callback(
_cx: *mut JSContext,
w: *mut JSStructuredCloneWriter,
obj: RawHandleObject,
_closure: *mut raw::c_void)
-> bool {
_closure: *mut raw::c_void,
) -> bool {
if let Ok(blob) = root_from_handleobject::<Blob>(Handle::from_raw(obj)) {
return write_blob(blob, w).is_ok()
return write_blob(blob, w).is_ok();
}
return false
return false;
}
unsafe extern "C" fn read_transfer_callback(_cx: *mut JSContext,
unsafe extern "C" fn read_transfer_callback(
_cx: *mut JSContext,
_r: *mut JSStructuredCloneReader,
_tag: u32,
_content: *mut raw::c_void,
_extra_data: u64,
_closure: *mut raw::c_void,
_return_object: RawMutableHandleObject)
-> bool {
_return_object: RawMutableHandleObject,
) -> bool {
false
}
unsafe extern "C" fn write_transfer_callback(_cx: *mut JSContext,
unsafe extern "C" fn write_transfer_callback(
_cx: *mut JSContext,
_obj: RawHandleObject,
_closure: *mut raw::c_void,
_tag: *mut u32,
_ownership: *mut TransferableOwnership,
_content: *mut *mut raw::c_void,
_extra_data: *mut u64)
-> bool {
_extra_data: *mut u64,
) -> bool {
false
}
unsafe extern "C" fn free_transfer_callback(_tag: u32,
unsafe extern "C" fn free_transfer_callback(
_tag: u32,
_ownership: TransferableOwnership,
_content: *mut raw::c_void,
_extra_data: u64,
_closure: *mut raw::c_void) {
_closure: *mut raw::c_void,
) {
}
unsafe extern "C" fn report_error_callback(_cx: *mut JSContext, _errorid: u32) {
}
unsafe extern "C" fn report_error_callback(_cx: *mut JSContext, _errorid: u32) {}
static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredCloneCallbacks {
read: Some(read_callback),
@ -202,7 +232,7 @@ static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredClon
};
struct StructuredCloneHolder {
blob: Option<DomRoot<Blob>>
blob: Option<DomRoot<Blob>>,
}
/// A buffer for a structured clone.
@ -210,7 +240,7 @@ pub enum StructuredCloneData {
/// A non-serializable (default) variant
Struct(*mut u64, size_t),
/// A variant that can be serialized
Vector(Vec<u8>)
Vector(Vec<u8>),
}
impl StructuredCloneData {
@ -218,21 +248,25 @@ impl StructuredCloneData {
/// Writes a structured clone. Returns a `DataClone` error if that fails.
pub fn write(cx: *mut JSContext, message: HandleValue) -> Fallible<StructuredCloneData> {
unsafe {
let scbuf = NewJSAutoStructuredCloneBuffer(StructuredCloneScope::DifferentProcess,
&STRUCTURED_CLONE_CALLBACKS);
let scbuf = NewJSAutoStructuredCloneBuffer(
StructuredCloneScope::DifferentProcess,
&STRUCTURED_CLONE_CALLBACKS,
);
let scdata = &mut ((*scbuf).data_);
let policy = CloneDataPolicy {
// TODO: SAB?
sharedArrayBuffer_: false,
};
let result = JS_WriteStructuredClone(cx,
let result = JS_WriteStructuredClone(
cx,
message,
scdata,
StructuredCloneScope::DifferentProcess,
policy,
&STRUCTURED_CLONE_CALLBACKS,
ptr::null_mut(),
HandleValue::undefined());
HandleValue::undefined(),
);
if !result {
JS_ClearPendingException(cx);
return Err(Error::DataClone);
@ -252,41 +286,40 @@ impl StructuredCloneData {
/// Converts a StructuredCloneData to Vec<u8> for inter-thread sharing
pub fn move_to_arraybuffer(self) -> Vec<u8> {
match self {
StructuredCloneData::Struct(data, nbytes) => {
unsafe {
StructuredCloneData::Struct(data, nbytes) => unsafe {
slice::from_raw_parts(data as *mut u8, nbytes).to_vec()
}
}
StructuredCloneData::Vector(msg) => msg
},
StructuredCloneData::Vector(msg) => msg,
}
}
/// Reads a structured clone.
///
/// Panics if `JS_ReadStructuredClone` fails.
fn read_clone(global: &GlobalScope,
data: *mut u64,
nbytes: size_t,
rval: MutableHandleValue) {
fn read_clone(global: &GlobalScope, data: *mut u64, nbytes: size_t, rval: MutableHandleValue) {
let cx = global.get_cx();
let globalhandle = global.reflector().get_jsobject();
let _ac = JSAutoCompartment::new(cx, globalhandle.get());
let mut sc_holder = StructuredCloneHolder { blob: None };
let sc_holder_ptr = &mut sc_holder as *mut _;
unsafe {
let scbuf = NewJSAutoStructuredCloneBuffer(StructuredCloneScope::DifferentProcess,
&STRUCTURED_CLONE_CALLBACKS);
let scbuf = NewJSAutoStructuredCloneBuffer(
StructuredCloneScope::DifferentProcess,
&STRUCTURED_CLONE_CALLBACKS,
);
let scdata = &mut ((*scbuf).data_);
WriteBytesToJSStructuredCloneData(data as *const u8, nbytes, scdata);
assert!(JS_ReadStructuredClone(cx,
assert!(JS_ReadStructuredClone(
cx,
scdata,
JS_STRUCTURED_CLONE_VERSION,
StructuredCloneScope::DifferentProcess,
rval,
&STRUCTURED_CLONE_CALLBACKS,
sc_holder_ptr as *mut raw::c_void));
sc_holder_ptr as *mut raw::c_void
));
DeleteJSAutoStructuredCloneBuffer(scbuf);
}
@ -299,8 +332,10 @@ impl StructuredCloneData {
let nbytes = vec_msg.len();
let data = vec_msg.as_mut_ptr() as *mut u64;
StructuredCloneData::read_clone(global, data, nbytes, rval);
}
StructuredCloneData::Struct(data, nbytes) => StructuredCloneData::read_clone(global, data, nbytes, rval)
},
StructuredCloneData::Struct(data, nbytes) => {
StructuredCloneData::read_clone(global, data, nbytes, rval)
},
}
}
}

View file

@ -149,9 +149,11 @@ pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>)
}
trace!("tracing value {}", description);
CallValueTracer(tracer,
CallValueTracer(
tracer,
val.ptr.get() as *mut _,
GCTraceKindToAscii(val.get().trace_kind()));
GCTraceKindToAscii(val.get().trace_kind()),
);
}
}
@ -166,9 +168,11 @@ pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Ref
pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: &Heap<*mut JSObject>) {
unsafe {
trace!("tracing {}", description);
CallObjectTracer(tracer,
CallObjectTracer(
tracer,
obj.ptr.get() as *mut _,
GCTraceKindToAscii(TraceKind::Object));
GCTraceKindToAscii(TraceKind::Object),
);
}
}
@ -295,7 +299,8 @@ unsafe impl<T: JSTraceable, U: JSTraceable> JSTraceable for Result<T, U> {
}
unsafe impl<K, V, S> JSTraceable for HashMap<K, V, S>
where K: Hash + Eq + JSTraceable,
where
K: Hash + Eq + JSTraceable,
V: JSTraceable,
S: BuildHasher,
{
@ -309,7 +314,8 @@ unsafe impl<K, V, S> JSTraceable for HashMap<K, V, S>
}
unsafe impl<T, S> JSTraceable for HashSet<T, S>
where T: Hash + Eq + JSTraceable,
where
T: Hash + Eq + JSTraceable,
S: BuildHasher,
{
#[inline]
@ -365,7 +371,12 @@ unsafe_no_jsmanaged_fields!(PropertyDeclarationBlock);
// These three are interdependent, if you plan to put jsmanaged data
// in one of these make sure it is propagated properly to containing structs
unsafe_no_jsmanaged_fields!(DocumentActivity, WindowSizeData, WindowSizeType);
unsafe_no_jsmanaged_fields!(BrowsingContextId, HistoryStateId, PipelineId, TopLevelBrowsingContextId);
unsafe_no_jsmanaged_fields!(
BrowsingContextId,
HistoryStateId,
PipelineId,
TopLevelBrowsingContextId
);
unsafe_no_jsmanaged_fields!(TimerEventId, TimerSource);
unsafe_no_jsmanaged_fields!(TimelineMarkerType);
unsafe_no_jsmanaged_fields!(WorkerId);
@ -459,7 +470,10 @@ unsafe impl<'a, A, B> JSTraceable for fn(&A) -> B {
}
}
unsafe impl<T> JSTraceable for IpcSender<T> where T: for<'de> Deserialize<'de> + Serialize {
unsafe impl<T> JSTraceable for IpcSender<T>
where
T: for<'de> Deserialize<'de> + Serialize,
{
#[inline]
unsafe fn trace(&self, _: *mut JSTracer) {
// Do nothing
@ -481,7 +495,10 @@ unsafe impl JSTraceable for () {
}
}
unsafe impl<T> JSTraceable for IpcReceiver<T> where T: for<'de> Deserialize<'de> + Serialize {
unsafe impl<T> JSTraceable for IpcReceiver<T>
where
T: for<'de> Deserialize<'de> + Serialize,
{
#[inline]
unsafe fn trace(&self, _: *mut JSTracer) {
// Do nothing
@ -509,14 +526,20 @@ unsafe impl<T: Send> JSTraceable for Sender<T> {
}
}
unsafe impl<T: Send> JSTraceable for WebGLReceiver<T> where T: for<'de> Deserialize<'de> + Serialize {
unsafe impl<T: Send> JSTraceable for WebGLReceiver<T>
where
T: for<'de> Deserialize<'de> + Serialize,
{
#[inline]
unsafe fn trace(&self, _: *mut JSTracer) {
// Do nothing
}
}
unsafe impl<T: Send> JSTraceable for WebGLSender<T> where T: for<'de> Deserialize<'de> + Serialize {
unsafe impl<T: Send> JSTraceable for WebGLSender<T>
where
T: for<'de> Deserialize<'de> + Serialize,
{
#[inline]
unsafe fn trace(&self, _: *mut JSTracer) {
// Do nothing
@ -665,7 +688,10 @@ unsafe impl JSTraceable for StyleLocked<MediaList> {
}
}
unsafe impl<T> JSTraceable for TypedArray<T, Box<Heap<*mut JSObject>>> where T: TypedArrayElement {
unsafe impl<T> JSTraceable for TypedArray<T, Box<Heap<*mut JSObject>>>
where
T: TypedArrayElement,
{
unsafe fn trace(&self, trc: *mut JSTracer) {
self.underlying_object().trace(trc);
}
@ -682,31 +708,23 @@ where
}
}
/// Holds a set of JSTraceables that need to be rooted
struct RootedTraceableSet {
set: Vec<*const JSTraceable>,
}
thread_local!(
/// TLV Holds a set of JSTraceables that need to be rooted
static ROOTED_TRACEABLES: RefCell<RootedTraceableSet> =
RefCell::new(RootedTraceableSet::new());
);
thread_local!(/// TLV Holds a set of JSTraceables that need to be rooted
static ROOTED_TRACEABLES: RefCell<RootedTraceableSet> = RefCell::new(RootedTraceableSet::new()););
impl RootedTraceableSet {
fn new() -> RootedTraceableSet {
RootedTraceableSet {
set: vec![],
}
RootedTraceableSet { set: vec![] }
}
unsafe fn remove(traceable: *const JSTraceable) {
ROOTED_TRACEABLES.with(|ref traceables| {
let mut traceables = traceables.borrow_mut();
let idx =
match traceables.set.iter()
.rposition(|x| *x == traceable) {
let idx = match traceables.set.iter().rposition(|x| *x == traceable) {
Some(idx) => idx,
None => unreachable!(),
};
@ -744,9 +762,7 @@ impl<'a, T: JSTraceable + 'static> RootedTraceable<'a, T> {
unsafe {
RootedTraceableSet::add(traceable);
}
RootedTraceable {
ptr: traceable,
}
RootedTraceable { ptr: traceable }
}
}
@ -787,14 +803,12 @@ impl<T: JSTraceable + 'static> RootedTraceableBox<T> {
unsafe {
RootedTraceableSet::add(traceable);
}
RootedTraceableBox {
ptr: traceable,
}
RootedTraceableBox { ptr: traceable }
}
}
impl<T> RootedTraceableBox<Heap<T>>
where
where
Heap<T>: JSTraceable + 'static,
T: GCMethods + Copy,
{
@ -812,17 +826,13 @@ impl<T: JSTraceable + Default> Default for RootedTraceableBox<T> {
impl<T: JSTraceable> Deref for RootedTraceableBox<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
&*self.ptr
}
unsafe { &*self.ptr }
}
}
impl<T: JSTraceable> DerefMut for RootedTraceableBox<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
&mut *self.ptr
}
unsafe { &mut *self.ptr }
}
}
@ -849,9 +859,7 @@ pub struct RootableVec<T: JSTraceable> {
impl<T: JSTraceable> RootableVec<T> {
/// Create a vector of items of type T that can be rooted later.
pub fn new_unrooted() -> RootableVec<T> {
RootableVec {
v: vec![],
}
RootableVec { v: vec![] }
}
}
@ -868,9 +876,7 @@ impl<'a, T: 'static + JSTraceable> RootedVec<'a, T> {
unsafe {
RootedTraceableSet::add(root);
}
RootedVec {
root: root,
}
RootedVec { root: root }
}
}
@ -878,15 +884,14 @@ impl<'a, T: 'static + JSTraceable + DomObject> RootedVec<'a, Dom<T>> {
/// Create a vector of items of type Dom<T> that is rooted for
/// the lifetime of this struct
pub fn from_iter<I>(root: &'a mut RootableVec<Dom<T>>, iter: I) -> Self
where I: Iterator<Item = DomRoot<T>>
where
I: Iterator<Item = DomRoot<T>>,
{
unsafe {
RootedTraceableSet::add(root);
}
root.v.extend(iter.map(|item| Dom::from_ref(&*item)));
RootedVec {
root: root,
}
RootedVec { root: root }
}
}

View file

@ -85,7 +85,6 @@ pub const DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT;
// changes.
pub const JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1;
/// The struct that holds inheritance information for DOM object reflectors.
#[derive(Clone, Copy)]
pub struct DOMClass {
@ -137,13 +136,14 @@ pub type ProtoOrIfaceArray = [*mut JSObject; PROTO_OR_IFACE_LENGTH];
/// set to true and `*vp` to the value, otherwise `*found` is set to false.
///
/// Returns false on JSAPI failure.
pub unsafe fn get_property_on_prototype(cx: *mut JSContext,
pub unsafe fn get_property_on_prototype(
cx: *mut JSContext,
proxy: HandleObject,
receiver: HandleValue,
id: HandleId,
found: *mut bool,
vp: MutableHandleValue)
-> bool {
vp: MutableHandleValue,
) -> bool {
rooted!(in(cx) let mut proto = ptr::null_mut::<JSObject>());
if !JS_GetPrototype(cx, proxy, proto.handle_mut()) || proto.is_null() {
*found = false;
@ -184,23 +184,29 @@ pub fn get_array_index_from_id(_cx: *mut JSContext, id: HandleId) -> Option<u32>
return if StringIsArray(str, &mut i) != 0 { i } else { -1 }
} else {
IdToInt32(cx, id);
}*/
}
}*/}
/// Find the enum equivelent of a string given by `v` in `pairs`.
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and
/// `Ok((None, value))` if there was no matching string.
pub unsafe fn find_enum_value<'a, T>(cx: *mut JSContext,
pub unsafe fn find_enum_value<'a, T>(
cx: *mut JSContext,
v: HandleValue,
pairs: &'a [(&'static str, T)])
-> Result<(Option<&'a T>, DOMString), ()> {
pairs: &'a [(&'static str, T)],
) -> Result<(Option<&'a T>, DOMString), ()> {
let jsstr = ToString(cx, v);
if jsstr.is_null() {
return Err(());
}
let search = jsstring_to_str(cx, jsstr);
Ok((pairs.iter().find(|&&(key, _)| search == *key).map(|&(_, ref ev)| ev), search))
Ok((
pairs
.iter()
.find(|&&(key, _)| search == *key)
.map(|&(_, ref ev)| ev),
search,
))
}
/// Returns wether `obj` is a platform object
@ -228,23 +234,26 @@ pub fn is_platform_object(obj: *mut JSObject) -> bool {
/// Get the property with name `property` from `object`.
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and
/// `Ok(false)` if there was no property with the given name.
pub fn get_dictionary_property(cx: *mut JSContext,
pub fn get_dictionary_property(
cx: *mut JSContext,
object: HandleObject,
property: &str,
rval: MutableHandleValue)
-> Result<bool, ()> {
fn has_property(cx: *mut JSContext,
rval: MutableHandleValue,
) -> Result<bool, ()> {
fn has_property(
cx: *mut JSContext,
object: HandleObject,
property: &CString,
found: &mut bool)
-> bool {
found: &mut bool,
) -> bool {
unsafe { JS_HasProperty(cx, object, property.as_ptr(), found) }
}
fn get_property(cx: *mut JSContext,
fn get_property(
cx: *mut JSContext,
object: HandleObject,
property: &CString,
value: MutableHandleValue)
-> bool {
value: MutableHandleValue,
) -> bool {
unsafe { JS_GetProperty(cx, object, property.as_ptr(), value) }
}
@ -272,11 +281,12 @@ pub fn get_dictionary_property(cx: *mut JSContext,
/// Set the property with name `property` from `object`.
/// Returns `Err(())` on JSAPI failure, or null object,
/// and Ok(()) otherwise
pub fn set_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(());
}
@ -292,11 +302,12 @@ pub fn set_dictionary_property(cx: *mut JSContext,
}
/// Returns whether `proxy` has a property `id` on its prototype.
pub unsafe fn has_property_on_prototype(cx: *mut JSContext,
pub unsafe fn has_property_on_prototype(
cx: *mut JSContext,
proxy: HandleObject,
id: HandleId,
found: &mut bool)
-> bool {
found: &mut bool,
) -> bool {
rooted!(in(cx) let mut proto = ptr::null_mut::<JSObject>());
if !JS_GetPrototype(cx, proxy, proto.handle_mut()) {
return false;
@ -322,9 +333,11 @@ 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,
trace_object(
tracer,
"prototype",
&*(proto as *const *mut JSObject as *const Heap<*mut JSObject>));
&*(proto as *const *mut JSObject as *const Heap<*mut JSObject>),
);
}
}
}
@ -346,8 +359,8 @@ pub unsafe extern "C" fn resolve_global(
cx: *mut JSContext,
obj: RawHandleObject,
id: RawHandleId,
rval: *mut bool)
-> bool {
rval: *mut bool,
) -> bool {
assert!(JS_IsGlobalObject(obj.get()));
if !JS_ResolveStandardClass(cx, obj, id, rval) {
return false;
@ -379,20 +392,23 @@ pub unsafe extern "C" fn resolve_global(
true
}
unsafe extern "C" fn wrap(cx: *mut JSContext,
unsafe extern "C" fn wrap(
cx: *mut JSContext,
_existing: RawHandleObject,
obj: RawHandleObject)
-> *mut JSObject {
obj: RawHandleObject,
) -> *mut JSObject {
// FIXME terrible idea. need security wrappers
// https://github.com/servo/servo/issues/2382
WrapperNew(cx, obj, GetCrossCompartmentWrapper(), ptr::null(), false)
}
unsafe extern "C" fn pre_wrap(cx: *mut JSContext,
unsafe extern "C" fn pre_wrap(
cx: *mut JSContext,
_scope: RawHandleObject,
obj: RawHandleObject,
_object_passed_to_wrap: RawHandleObject,
rval: RawMutableHandleObject) {
rval: RawMutableHandleObject,
) {
let _ac = JSAutoCompartment::new(cx, obj.get());
let obj = ToWindowProxyIfWindow(obj.get());
assert!(!obj.is_null());
@ -406,23 +422,29 @@ pub static WRAP_CALLBACKS: JSWrapObjectCallbacks = JSWrapObjectCallbacks {
};
/// Deletes the property `id` from `object`.
pub unsafe fn delete_property_by_id(cx: *mut JSContext,
pub unsafe fn delete_property_by_id(
cx: *mut JSContext,
object: HandleObject,
id: HandleId,
bp: *mut ObjectOpResult)
-> bool {
bp: *mut ObjectOpResult,
) -> bool {
JS_DeletePropertyById(cx, object, id, bp)
}
unsafe fn generic_call(cx: *mut JSContext,
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,
RawHandleObject, *mut libc::c_void, u32,
*mut JSVal)
-> bool)
-> bool {
call: unsafe extern "C" fn(
*const JSJitInfo,
*mut JSContext,
RawHandleObject,
*mut libc::c_void,
u32,
*mut JSVal,
) -> bool,
) -> bool {
let args = CallArgs::from_vp(vp, argc);
let info = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
@ -441,9 +463,8 @@ unsafe fn generic_call(cx: *mut JSContext,
};
rooted!(in(cx) let obj = obj);
let depth = (*info).depth;
let proto_check = |class: &'static DOMClass| {
class.interface_chain[depth as usize] as u16 == proto_id
};
let proto_check =
|class: &'static DOMClass| class.interface_chain[depth as usize] as u16 == proto_id;
let this = match private_from_proto_check(obj.get(), proto_check) {
Ok(val) => val,
Err(()) => {
@ -455,42 +476,53 @@ unsafe fn generic_call(cx: *mut JSContext,
throw_invalid_this(cx, proto_id);
return false;
}
}
},
};
call(info, cx, obj.handle().into(), this as *mut libc::c_void, argc, vp)
call(
info,
cx,
obj.handle().into(),
this as *mut libc::c_void,
argc,
vp,
)
}
/// Generic method of IDL interface.
pub unsafe extern "C" fn generic_method(cx: *mut JSContext,
pub unsafe extern "C" fn generic_method(
cx: *mut JSContext,
argc: libc::c_uint,
vp: *mut JSVal)
-> bool {
vp: *mut JSVal,
) -> bool {
generic_call(cx, argc, vp, false, CallJitMethodOp)
}
/// Generic getter of IDL interface.
pub unsafe extern "C" fn generic_getter(cx: *mut JSContext,
pub unsafe extern "C" fn generic_getter(
cx: *mut JSContext,
argc: libc::c_uint,
vp: *mut JSVal)
-> bool {
vp: *mut JSVal,
) -> bool {
generic_call(cx, argc, vp, false, CallJitGetterOp)
}
/// Generic lenient getter of IDL interface.
pub unsafe extern "C" fn generic_lenient_getter(cx: *mut JSContext,
pub unsafe extern "C" fn generic_lenient_getter(
cx: *mut JSContext,
argc: libc::c_uint,
vp: *mut JSVal)
-> bool {
vp: *mut JSVal,
) -> bool {
generic_call(cx, argc, vp, true, CallJitGetterOp)
}
unsafe extern "C" fn call_setter(info: *const JSJitInfo,
unsafe extern "C" fn call_setter(
info: *const JSJitInfo,
cx: *mut JSContext,
handle: RawHandleObject,
this: *mut libc::c_void,
argc: u32,
vp: *mut JSVal)
-> bool {
vp: *mut JSVal,
) -> bool {
if !CallJitSetterOp(info, cx, handle, this, argc, vp) {
return false;
}
@ -499,25 +531,28 @@ unsafe extern "C" fn call_setter(info: *const JSJitInfo,
}
/// Generic setter of IDL interface.
pub unsafe extern "C" fn generic_setter(cx: *mut JSContext,
pub unsafe extern "C" fn generic_setter(
cx: *mut JSContext,
argc: libc::c_uint,
vp: *mut JSVal)
-> bool {
vp: *mut JSVal,
) -> bool {
generic_call(cx, argc, vp, false, call_setter)
}
/// Generic lenient setter of IDL interface.
pub unsafe extern "C" fn generic_lenient_setter(cx: *mut JSContext,
pub unsafe extern "C" fn generic_lenient_setter(
cx: *mut JSContext,
argc: libc::c_uint,
vp: *mut JSVal)
-> bool {
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,
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

View file

@ -70,9 +70,11 @@ pub trait WeakReferenceable: DomObject + Sized {
let box_ = &*ptr;
assert!(box_.value.get().is_some());
let new_count = box_.count.get() + 1;
trace!("Incrementing WeakBox refcount for {:p} to {}.",
trace!(
"Incrementing WeakBox refcount for {:p} to {}.",
self,
new_count);
new_count
);
box_.count.set(new_count);
WeakRef {
ptr: ptr::NonNull::new_unchecked(ptr),
@ -91,9 +93,10 @@ impl<T: WeakReferenceable> WeakRef<T> {
/// DomRoot a weak reference. Returns `None` if the object was already collected.
pub fn root(&self) -> Option<DomRoot<T>> {
unsafe { &*self.ptr.as_ptr() }.value.get().map(|ptr| unsafe {
DomRoot::from_ref(&*ptr.as_ptr())
})
unsafe { &*self.ptr.as_ptr() }
.value
.get()
.map(|ptr| unsafe { DomRoot::from_ref(&*ptr.as_ptr()) })
}
/// Return whether the weakly-referenced object is still alive.
@ -108,9 +111,7 @@ impl<T: WeakReferenceable> Clone for WeakRef<T> {
let box_ = &*self.ptr.as_ptr();
let new_count = box_.count.get() + 1;
box_.count.set(new_count);
WeakRef {
ptr: self.ptr,
}
WeakRef { ptr: self.ptr }
}
}
}
@ -190,7 +191,9 @@ impl<T: WeakReferenceable> MutableWeakRef<T> {
/// DomRoot a mutable weak reference. Returns `None` if the object
/// was already collected.
pub fn root(&self) -> Option<DomRoot<T>> {
unsafe { &*self.cell.get() }.as_ref().and_then(WeakRef::root)
unsafe { &*self.cell.get() }
.as_ref()
.and_then(WeakRef::root)
}
}
@ -233,7 +236,10 @@ impl<T: WeakReferenceable> WeakRefVec<T> {
let mut i = 0;
while i < self.vec.len() {
if self.vec[i].is_alive() {
f(WeakRefEntry { vec: self, index: &mut i });
f(WeakRefEntry {
vec: self,
index: &mut i,
});
} else {
self.vec.swap_remove(i);
}
@ -293,13 +299,13 @@ impl<'a, T: WeakReferenceable + 'a> Drop for WeakRefEntry<'a, T> {
#[derive(MallocSizeOf)]
pub struct DOMTracker<T: WeakReferenceable> {
dom_objects: DomRefCell<WeakRefVec<T>>
dom_objects: DomRefCell<WeakRefVec<T>>,
}
impl<T: WeakReferenceable> DOMTracker<T> {
pub fn new() -> Self {
Self {
dom_objects: DomRefCell::new(WeakRefVec::new())
dom_objects: DomRefCell::new(WeakRefVec::new()),
}
}

View file

@ -25,9 +25,10 @@ pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult {
/// 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)
-> Fallible<(Namespace, Option<Prefix>, LocalName)> {
pub fn validate_and_extract(
namespace: Option<DOMString>,
qualified_name: &str,
) -> Fallible<(Namespace, Option<Prefix>, LocalName)> {
// Step 1.
let namespace = namespace_from_domstring(namespace);
@ -76,7 +77,7 @@ pub fn validate_and_extract(namespace: Option<DOMString>,
(ns, p) => {
// Step 10.
Ok((ns, p.map(Prefix::from), LocalName::from(local_name)))
}
},
}
}
@ -115,14 +116,10 @@ pub fn xml_name_type(name: &str) -> XMLName {
}
fn is_valid_continuation(c: char) -> bool {
is_valid_start(c) ||
match c {
'-' |
'.' |
'0'...'9' |
'\u{B7}' |
'\u{300}'...'\u{36F}' |
'\u{203F}'...'\u{2040}' => true,
is_valid_start(c) || match c {
'-' | '.' | '0'...'9' | '\u{B7}' | '\u{300}'...'\u{36F}' | '\u{203F}'...'\u{2040}' => {
true
},
_ => false,
}
}
@ -140,7 +137,7 @@ pub fn xml_name_type(name: &str) -> XMLName {
non_qname_colons = true;
}
c
}
},
};
for c in iter {

View file

@ -30,7 +30,6 @@ pub struct FileBlob {
size: u64,
}
/// Different backends of Blob
#[must_root]
#[derive(JSTraceable)]
@ -43,7 +42,7 @@ pub enum BlobImpl {
/// relative positions of current slicing range,
/// IMPORTANT: The depth of tree is only two, i.e. the parent Blob must be
/// either File-based or Memory-based
Sliced(Dom<Blob>, RelativePos)
Sliced(Dom<Blob>, RelativePos),
}
impl BlobImpl {
@ -76,9 +75,7 @@ pub struct Blob {
impl Blob {
#[allow(unrooted_must_root)]
pub fn new(
global: &GlobalScope, blob_impl: BlobImpl, typeString: String)
-> DomRoot<Blob> {
pub fn new(global: &GlobalScope, blob_impl: BlobImpl, typeString: String) -> DomRoot<Blob> {
let boxed_blob = Box::new(Blob::new_inherited(blob_impl, typeString));
reflect_dom_object(boxed_blob, global, BlobBinding::Wrap)
}
@ -95,41 +92,49 @@ impl Blob {
}
#[allow(unrooted_must_root)]
fn new_sliced(parent: &Blob, rel_pos: RelativePos,
relative_content_type: DOMString) -> DomRoot<Blob> {
fn new_sliced(
parent: &Blob,
rel_pos: RelativePos,
relative_content_type: DOMString,
) -> DomRoot<Blob> {
let blob_impl = match *parent.blob_impl.borrow() {
BlobImpl::File(_) => {
// Create new parent node
BlobImpl::Sliced(Dom::from_ref(parent), rel_pos)
}
},
BlobImpl::Memory(_) => {
// Create new parent node
BlobImpl::Sliced(Dom::from_ref(parent), rel_pos)
}
},
BlobImpl::Sliced(ref grandparent, ref old_rel_pos) => {
// Adjust the slicing position, using same parent
BlobImpl::Sliced(grandparent.clone(), old_rel_pos.slice_inner(&rel_pos))
}
},
};
Blob::new(&parent.global(), blob_impl, relative_content_type.into())
}
// https://w3c.github.io/FileAPI/#constructorBlob
pub fn Constructor(global: &GlobalScope,
pub fn Constructor(
global: &GlobalScope,
blobParts: Option<Vec<ArrayBufferOrArrayBufferViewOrBlobOrString>>,
blobPropertyBag: &BlobBinding::BlobPropertyBag)
-> Fallible<DomRoot<Blob>> {
blobPropertyBag: &BlobBinding::BlobPropertyBag,
) -> Fallible<DomRoot<Blob>> {
// TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView
let bytes: Vec<u8> = match blobParts {
None => Vec::new(),
Some(blobparts) => match blob_parts_to_bytes(blobparts) {
Ok(bytes) => bytes,
Err(_) => return Err(Error::InvalidCharacter),
}
},
};
Ok(Blob::new(global, BlobImpl::new_from_bytes(bytes), blobPropertyBag.type_.to_string()))
Ok(Blob::new(
global,
BlobImpl::new_from_bytes(bytes),
blobPropertyBag.type_.to_string(),
))
}
/// Get a slice to inner data, this might incur synchronous read and caching
@ -141,7 +146,7 @@ impl Blob {
None => {
let bytes = read_file(&self.global(), f.id.clone())?;
(bytes, true)
}
},
};
// Cache
@ -150,14 +155,12 @@ impl Blob {
}
Ok(buffer)
}
},
BlobImpl::Memory(ref s) => Ok(s.clone()),
BlobImpl::Sliced(ref parent, ref rel_pos) => {
parent.get_bytes().map(|v| {
BlobImpl::Sliced(ref parent, ref rel_pos) => parent.get_bytes().map(|v| {
let range = rel_pos.to_abs_range(v.len());
v.index(range).to_vec()
})
}
}),
}
}
@ -171,13 +174,19 @@ impl Blob {
pub fn get_blob_url_id(&self) -> Uuid {
let opt_sliced_parent = match *self.blob_impl.borrow() {
BlobImpl::Sliced(ref parent, ref rel_pos) => {
Some((parent.promote(/* set_valid is */ false), rel_pos.clone(), parent.Size()))
}
_ => None
Some((
parent.promote(/* set_valid is */ false),
rel_pos.clone(),
parent.Size(),
))
},
_ => None,
};
match opt_sliced_parent {
Some((parent_id, rel_pos, size)) => self.create_sliced_url_id(&parent_id, &rel_pos, size),
Some((parent_id, rel_pos, size)) => {
self.create_sliced_url_id(&parent_id, &rel_pos, size)
},
None => self.promote(/* set_valid is */ true),
}
}
@ -196,13 +205,15 @@ impl Blob {
debug!("Sliced can't have a sliced parent");
// Return dummy id
return Uuid::new_v4();
}
},
BlobImpl::File(ref f) => {
if set_valid {
let origin = get_blob_origin(&global_url);
let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
let (tx, rx) =
ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
let msg = FileManagerThreadMsg::ActivateBlobURL(f.id.clone(), tx, origin.clone());
let msg =
FileManagerThreadMsg::ActivateBlobURL(f.id.clone(), tx, origin.clone());
self.send_to_file_manager(msg);
match rx.recv().unwrap() {
@ -214,7 +225,7 @@ impl Blob {
// no need to activate
return f.id.clone();
}
}
},
BlobImpl::Memory(ref mut bytes_in) => mem::swap(bytes_in, &mut bytes),
};
@ -240,21 +251,28 @@ impl Blob {
size: bytes.len() as u64,
});
id
}
},
// Dummy id
Err(_) => Uuid::new_v4(),
}
}
/// Get a FileID representing sliced parent-blob content
fn create_sliced_url_id(&self, parent_id: &Uuid,
rel_pos: &RelativePos, parent_len: u64) -> Uuid {
fn create_sliced_url_id(
&self,
parent_id: &Uuid,
rel_pos: &RelativePos,
parent_len: u64,
) -> Uuid {
let origin = get_blob_origin(&self.global().get_url());
let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
let msg = FileManagerThreadMsg::AddSlicedURLEntry(parent_id.clone(),
let msg = FileManagerThreadMsg::AddSlicedURLEntry(
parent_id.clone(),
rel_pos.clone(),
tx, origin.clone());
tx,
origin.clone(),
);
self.send_to_file_manager(msg);
match rx.recv().expect("File manager thread is down") {
Ok(new_id) => {
@ -267,11 +285,11 @@ impl Blob {
// Return the indirect id reference
new_id
}
},
Err(_) => {
// Return dummy id
Uuid::new_v4()
}
},
}
}
@ -303,7 +321,7 @@ impl Drop for Blob {
fn read_file(global: &GlobalScope, id: Uuid) -> Result<Vec<u8>, ()> {
let resource_threads = global.resource_threads();
let (chan, recv) = ipc::channel(global.time_profiler_chan().clone()).map_err(|_|())?;
let (chan, recv) = ipc::channel(global.time_profiler_chan().clone()).map_err(|_| ())?;
let origin = get_blob_origin(&global.get_url());
let check_url_validity = false;
let msg = FileManagerThreadMsg::ReadFile(chan, id, check_url_validity, origin);
@ -315,13 +333,13 @@ fn read_file(global: &GlobalScope, id: Uuid) -> Result<Vec<u8>, ()> {
match recv.recv().unwrap() {
Ok(ReadFileProgress::Meta(mut blob_buf)) => {
bytes.append(&mut blob_buf.bytes);
}
},
Ok(ReadFileProgress::Partial(mut bytes_in)) => {
bytes.append(&mut bytes_in);
}
},
Ok(ReadFileProgress::EOF) => {
return Ok(bytes);
}
},
Err(_) => return Err(()),
}
}
@ -330,7 +348,9 @@ fn read_file(global: &GlobalScope, id: Uuid) -> Result<Vec<u8>, ()> {
/// Extract bytes from BlobParts, used by Blob and File constructor
/// <https://w3c.github.io/FileAPI/#constructorBlob>
#[allow(unsafe_code)]
pub fn blob_parts_to_bytes(mut blobparts: Vec<ArrayBufferOrArrayBufferViewOrBlobOrString>) -> Result<Vec<u8>, ()> {
pub fn blob_parts_to_bytes(
mut blobparts: Vec<ArrayBufferOrArrayBufferViewOrBlobOrString>,
) -> Result<Vec<u8>, ()> {
let mut ret = vec![];
for blobpart in &mut blobparts {
match blobpart {
@ -348,7 +368,7 @@ pub fn blob_parts_to_bytes(mut blobparts: Vec<ArrayBufferOrArrayBufferViewOrBlob
&mut ArrayBufferOrArrayBufferViewOrBlobOrString::ArrayBufferView(ref mut a) => unsafe {
let bytes = a.as_slice();
ret.extend(bytes);
}
},
}
}
@ -361,8 +381,9 @@ impl BlobMethods for Blob {
match *self.blob_impl.borrow() {
BlobImpl::File(ref f) => f.size,
BlobImpl::Memory(ref v) => v.len() as u64,
BlobImpl::Sliced(ref parent, ref rel_pos) =>
rel_pos.to_abs_range(parent.Size() as usize).len() as u64,
BlobImpl::Sliced(ref parent, ref rel_pos) => {
rel_pos.to_abs_range(parent.Size() as usize).len() as u64
},
}
}
@ -372,11 +393,12 @@ impl BlobMethods for Blob {
}
// https://w3c.github.io/FileAPI/#slice-method-algo
fn Slice(&self,
fn Slice(
&self,
start: Option<i64>,
end: Option<i64>,
content_type: Option<DOMString>)
-> DomRoot<Blob> {
content_type: Option<DOMString>,
) -> DomRoot<Blob> {
let rel_pos = RelativePos::from_opts(start, end);
Blob::new_sliced(self, rel_pos, content_type.unwrap_or(DOMString::from("")))
}

View file

@ -12,7 +12,7 @@ use dom::bindings::codegen::Bindings::BluetoothBinding::{self, BluetoothDataFilt
use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothMethods, RequestDeviceOptions};
use dom::bindings::codegen::Bindings::BluetoothPermissionResultBinding::BluetoothPermissionDescriptor;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerBinding::
BluetoothRemoteGATTServerMethods;
BluetoothRemoteGATTServerMethods;
use dom::bindings::codegen::Bindings::PermissionStatusBinding::{PermissionName, PermissionState};
use dom::bindings::codegen::UnionTypes::{ArrayBufferViewOrArrayBuffer, StringOrUnsignedLong};
use dom::bindings::error::Error::{self, Network, Security, Type};
@ -42,20 +42,26 @@ use std::str::FromStr;
use std::sync::{Arc, Mutex};
use task::TaskOnce;
const KEY_CONVERSION_ERROR: &'static str = "This `manufacturerData` key can not be parsed as unsigned short:";
const FILTER_EMPTY_ERROR: &'static str = "'filters' member, if present, must be nonempty to find any devices.";
const KEY_CONVERSION_ERROR: &'static str =
"This `manufacturerData` key can not be parsed as unsigned short:";
const FILTER_EMPTY_ERROR: &'static str =
"'filters' member, if present, must be nonempty to find any devices.";
const FILTER_ERROR: &'static str = "A filter must restrict the devices in some way.";
const MANUFACTURER_DATA_ERROR: &'static str = "'manufacturerData', if present, must be non-empty to filter devices.";
const MASK_LENGTH_ERROR: &'static str = "`mask`, if present, must have the same length as `dataPrefix`.";
const MANUFACTURER_DATA_ERROR: &'static str =
"'manufacturerData', if present, must be non-empty to filter devices.";
const MASK_LENGTH_ERROR: &'static str =
"`mask`, if present, must have the same length as `dataPrefix`.";
// 248 is the maximum number of UTF-8 code units in a Bluetooth Device Name.
const MAX_DEVICE_NAME_LENGTH: usize = 248;
const NAME_PREFIX_ERROR: &'static str = "'namePrefix', if present, must be nonempty.";
const NAME_TOO_LONG_ERROR: &'static str = "A device name can't be longer than 248 bytes.";
const SERVICE_DATA_ERROR: &'static str = "'serviceData', if present, must be non-empty to filter devices.";
const SERVICE_DATA_ERROR: &'static str =
"'serviceData', if present, must be non-empty to filter devices.";
const SERVICE_ERROR: &'static str = "'services', if present, must contain at least one service.";
const OPTIONS_ERROR: &'static str = "Fields of 'options' conflict with each other.
Either 'acceptAllDevices' member must be true, or 'filters' member must be set to a value.";
const BT_DESC_CONVERSION_ERROR: &'static str = "Can't convert to an IDL value of type BluetoothPermissionDescriptor";
const BT_DESC_CONVERSION_ERROR: &'static str =
"Can't convert to an IDL value of type BluetoothPermissionDescriptor";
#[derive(JSTraceable, MallocSizeOf)]
pub struct AllowedBluetoothDevice {
@ -84,7 +90,10 @@ impl BluetoothExtraPermissionData {
}
pub fn allowed_devices_contains_id(&self, id: DOMString) -> bool {
self.allowed_devices.borrow().iter().any(|d| d.deviceId == id)
self.allowed_devices
.borrow()
.iter()
.any(|d| d.deviceId == id)
}
}
@ -132,9 +141,11 @@ impl Bluetooth {
}
pub fn new(global: &GlobalScope) -> DomRoot<Bluetooth> {
reflect_dom_object(Box::new(Bluetooth::new_inherited()),
reflect_dom_object(
Box::new(Bluetooth::new_inherited()),
global,
BluetoothBinding::Wrap)
BluetoothBinding::Wrap,
)
}
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
@ -146,15 +157,17 @@ impl Bluetooth {
}
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
fn request_bluetooth_devices(&self,
fn request_bluetooth_devices(
&self,
p: &Rc<Promise>,
filters: &Option<Vec<BluetoothLEScanFilterInit>>,
optional_services: &Option<Vec<BluetoothServiceUUID>>,
sender: IpcSender<BluetoothResponseResult>) {
sender: IpcSender<BluetoothResponseResult>,
) {
// TODO: Step 1: Triggered by user activation.
// Step 2.2: There are no requiredServiceUUIDS, we scan for all devices.
let mut uuid_filters = vec!();
let mut uuid_filters = vec![];
if let &Some(ref filters) = filters {
// Step 2.1.
@ -180,7 +193,7 @@ impl Bluetooth {
}
}
let mut optional_services_uuids = vec!();
let mut optional_services_uuids = vec![];
if let &Some(ref opt_services) = optional_services {
for opt_service in opt_services {
// Step 2.5 - 2.6.
@ -201,30 +214,39 @@ impl Bluetooth {
}
}
let option = RequestDeviceoptions::new(BluetoothScanfilterSequence::new(uuid_filters),
ServiceUUIDSequence::new(optional_services_uuids));
let option = RequestDeviceoptions::new(
BluetoothScanfilterSequence::new(uuid_filters),
ServiceUUIDSequence::new(optional_services_uuids),
);
// Step 4 - 5.
if let PermissionState::Denied = get_descriptor_permission_state(PermissionName::Bluetooth, None) {
if let PermissionState::Denied =
get_descriptor_permission_state(PermissionName::Bluetooth, None)
{
return p.reject_error(Error::NotFound);
}
// Note: Step 3, 6 - 8 are implemented in
// components/net/bluetooth_thread.rs in request_device function.
self.get_bluetooth_thread().send(BluetoothRequest::RequestDevice(option, sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::RequestDevice(option, sender))
.unwrap();
}
}
pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>(
promise: &Rc<Promise>,
receiver: &T) -> IpcSender<BluetoothResponseResult> {
receiver: &T,
) -> IpcSender<BluetoothResponseResult> {
let (action_sender, action_receiver) = ipc::channel().unwrap();
let task_source = receiver.global().networking_task_source();
let context = Arc::new(Mutex::new(BluetoothContext {
promise: Some(TrustedPromise::new(promise.clone())),
receiver: Trusted::new(receiver),
}));
ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| {
ROUTER.add_route(
action_receiver.to_opaque(),
Box::new(move |message| {
struct ListenerTask<T: AsyncBluetoothListener + DomObject> {
context: Arc<Mutex<BluetoothContext<T>>>,
action: BluetoothResponseResult,
@ -249,23 +271,26 @@ pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>(
if let Err(err) = result {
warn!("failed to deliver network data: {:?}", err);
}
}));
}),
);
action_sender
}
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
pub fn get_gatt_children<T, F> (
pub fn get_gatt_children<T, F>(
attribute: &T,
single: bool,
uuid_canonicalizer: F,
uuid: Option<StringOrUnsignedLong>,
instance_id: String,
connected: bool,
child_type: GATTType)
-> Rc<Promise>
where T: AsyncBluetoothListener + DomObject + 'static,
F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID> {
child_type: GATTType,
) -> Rc<Promise>
where
T: AsyncBluetoothListener + DomObject + 'static,
F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID>,
{
let p = Promise::new(&attribute.global());
let result_uuid = if let Some(u) = uuid {
@ -275,7 +300,7 @@ pub fn get_gatt_children<T, F> (
Err(e) => {
p.reject_error(e);
return p;
}
},
};
// Step 2.
if uuid_is_blocklisted(canonicalized.as_ref(), Blocklist::All) {
@ -298,8 +323,17 @@ pub fn get_gatt_children<T, F> (
// Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_descriptor function
// and in handle_response function.
let sender = response_async(&p, attribute);
attribute.global().as_window().bluetooth_thread().send(
BluetoothRequest::GetGATTChildren(instance_id, result_uuid, single, child_type, sender)).unwrap();
attribute
.global()
.as_window()
.bluetooth_thread()
.send(BluetoothRequest::GetGATTChildren(
instance_id,
result_uuid,
single,
child_type,
sender,
)).unwrap();
return p;
}
@ -310,7 +344,8 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth
filter.name.is_none() &&
filter.namePrefix.is_none() &&
filter.manufacturerData.is_none() &&
filter.serviceData.is_none() {
filter.serviceData.is_none()
{
return Err(Type(FILTER_ERROR.to_owned()));
}
@ -325,7 +360,7 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth
return Err(Type(SERVICE_ERROR.to_owned()));
}
let mut services_vec = vec!();
let mut services_vec = vec![];
for service in services {
// Step 3.2 - 3.3.
@ -333,7 +368,7 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth
// Step 3.4.
if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) {
return Err(Security)
return Err(Security);
}
services_vec.push(uuid);
@ -341,7 +376,7 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth
// Step 3.5.
services_vec
},
None => vec!(),
None => vec![],
};
// Step 4.
@ -388,13 +423,18 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth
// Step 7.1 - 7.2.
let manufacturer_id = match u16::from_str(key.as_ref()) {
Ok(id) => id,
Err(err) => return Err(Type(format!("{} {} {}", KEY_CONVERSION_ERROR, key, err))),
Err(err) => {
return Err(Type(format!("{} {} {}", KEY_CONVERSION_ERROR, key, err)))
},
};
// Step 7.3: No need to convert to IDL values since this is only used by native code.
// Step 7.4 - 7.5.
map.insert(manufacturer_id, canonicalize_bluetooth_data_filter_init(bdfi)?);
map.insert(
manufacturer_id,
canonicalize_bluetooth_data_filter_init(bdfi)?,
);
}
Some(map)
},
@ -414,7 +454,7 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth
// Step 9.1.
Ok(number) => StringOrUnsignedLong::UnsignedLong(number),
// Step 9.2.
_ => StringOrUnsignedLong::String(key.clone())
_ => StringOrUnsignedLong::String(key.clone()),
};
// Step 9.3 - 9.4.
@ -436,16 +476,24 @@ fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<Bluetooth
};
// Step 10.
Ok(BluetoothScanfilter::new(name, name_prefix, services_vec, manufacturer_data, service_data))
Ok(BluetoothScanfilter::new(
name,
name_prefix,
services_vec,
manufacturer_data,
service_data,
))
}
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdatafilterinit-canonicalizing
fn canonicalize_bluetooth_data_filter_init(bdfi: &BluetoothDataFilterInit) -> Fallible<(Vec<u8>, Vec<u8>)> {
fn canonicalize_bluetooth_data_filter_init(
bdfi: &BluetoothDataFilterInit,
) -> Fallible<(Vec<u8>, Vec<u8>)> {
// Step 1.
let data_prefix = match bdfi.dataPrefix {
Some(ArrayBufferViewOrArrayBuffer::ArrayBufferView(ref avb)) => avb.to_vec(),
Some(ArrayBufferViewOrArrayBuffer::ArrayBuffer(ref ab)) => ab.to_vec(),
None => vec![]
None => vec![],
};
// Step 2.
@ -454,7 +502,7 @@ fn canonicalize_bluetooth_data_filter_init(bdfi: &BluetoothDataFilterInit) -> Fa
let mask = match bdfi.mask {
Some(ArrayBufferViewOrArrayBuffer::ArrayBufferView(ref avb)) => avb.to_vec(),
Some(ArrayBufferViewOrArrayBuffer::ArrayBuffer(ref ab)) => ab.to_vec(),
None => vec![0xFF; data_prefix.len()]
None => vec![0xFF; data_prefix.len()],
};
// Step 3.
@ -486,7 +534,8 @@ impl BluetoothMethods for Bluetooth {
let p = Promise::new(&self.global());
// Step 1.
if (option.filters.is_some() && option.acceptAllDevices) ||
(option.filters.is_none() && !option.acceptAllDevices) {
(option.filters.is_none() && !option.acceptAllDevices)
{
p.reject_error(Error::Type(OPTIONS_ERROR.to_owned()));
return p;
}
@ -505,13 +554,18 @@ impl BluetoothMethods for Bluetooth {
// Step 1. We did not override the method
// Step 2 - 3. in handle_response
let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
BluetoothRequest::GetAvailability(sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::GetAvailability(sender))
.unwrap();
p
}
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-onavailabilitychanged
event_handler!(availabilitychanged, GetOnavailabilitychanged, SetOnavailabilitychanged);
event_handler!(
availabilitychanged,
GetOnavailabilitychanged,
SetOnavailabilitychanged
);
}
impl AsyncBluetoothListener for Bluetooth {
@ -524,18 +578,21 @@ impl AsyncBluetoothListener for Bluetooth {
if let Some(existing_device) = device_instance_map.get(&device.id.clone()) {
return promise.resolve_native(&**existing_device);
}
let bt_device = BluetoothDevice::new(&self.global(),
let bt_device = BluetoothDevice::new(
&self.global(),
DOMString::from(device.id.clone()),
device.name.map(DOMString::from),
&self);
&self,
);
device_instance_map.insert(device.id.clone(), Dom::from_ref(&bt_device));
self.global().as_window().bluetooth_extra_permission_data().add_new_allowed_device(
AllowedBluetoothDevice {
self.global()
.as_window()
.bluetooth_extra_permission_data()
.add_new_allowed_device(AllowedBluetoothDevice {
deviceId: DOMString::from(device.id),
mayUseGATT: true,
}
);
});
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
// Step 5.
promise.resolve_native(&bt_device);
@ -544,7 +601,7 @@ impl AsyncBluetoothListener for Bluetooth {
// Step 2 - 3.
BluetoothResponse::GetAvailability(is_available) => {
promise.resolve_native(&is_available);
}
},
_ => promise.reject_error(Error::Type("Something went wrong...".to_owned())),
}
}
@ -555,11 +612,14 @@ impl PermissionAlgorithm for Bluetooth {
type Status = BluetoothPermissionResult;
#[allow(unsafe_code)]
fn create_descriptor(cx: *mut JSContext,
permission_descriptor_obj: *mut JSObject)
-> Result<BluetoothPermissionDescriptor, Error> {
fn create_descriptor(
cx: *mut JSContext,
permission_descriptor_obj: *mut JSObject,
) -> Result<BluetoothPermissionDescriptor, Error> {
rooted!(in(cx) let mut property = UndefinedValue());
property.handle_mut().set(ObjectValue(permission_descriptor_obj));
property
.handle_mut()
.set(ObjectValue(permission_descriptor_obj));
unsafe {
match BluetoothPermissionDescriptor::new(cx, property.handle()) {
Ok(ConversionResult::Success(descriptor)) => Ok(descriptor),
@ -592,7 +652,10 @@ impl PermissionAlgorithm for Bluetooth {
// Step 5.
let global = status.global();
let allowed_devices = global.as_window().bluetooth_extra_permission_data().get_allowed_devices();
let allowed_devices = global
.as_window()
.bluetooth_extra_permission_data()
.get_allowed_devices();
let bluetooth = status.get_bluetooth();
let device_map = bluetooth.get_device_map().borrow();
@ -622,11 +685,15 @@ impl PermissionAlgorithm for Bluetooth {
// Step 6.2.2.
// Instead of creating an internal slot we send an ipc message to the Bluetooth thread
// to check if one of the filters matches.
let (sender, receiver) = ProfiledIpc::channel(global.time_profiler_chan().clone()).unwrap();
status.get_bluetooth_thread()
.send(BluetoothRequest::MatchesFilter(device_id.clone(),
let (sender, receiver) =
ProfiledIpc::channel(global.time_profiler_chan().clone()).unwrap();
status
.get_bluetooth_thread()
.send(BluetoothRequest::MatchesFilter(
device_id.clone(),
BluetoothScanfilterSequence::new(scan_filters),
sender)).unwrap();
sender,
)).unwrap();
match receiver.recv().unwrap() {
Ok(true) => (),
@ -666,17 +733,28 @@ impl PermissionAlgorithm for Bluetooth {
// Step 2.
let sender = response_async(promise, status);
let bluetooth = status.get_bluetooth();
bluetooth.request_bluetooth_devices(promise, &descriptor.filters, &descriptor.optionalServices, sender);
bluetooth.request_bluetooth_devices(
promise,
&descriptor.filters,
&descriptor.optionalServices,
sender,
);
// NOTE: Step 3. is in BluetoothPermissionResult's `handle_response` function.
}
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#revoke-bluetooth-access
fn permission_revoke(_descriptor: &BluetoothPermissionDescriptor, status: &BluetoothPermissionResult) {
fn permission_revoke(
_descriptor: &BluetoothPermissionDescriptor,
status: &BluetoothPermissionResult,
) {
// Step 1.
let global = status.global();
let allowed_devices = global.as_window().bluetooth_extra_permission_data().get_allowed_devices();
let allowed_devices = global
.as_window()
.bluetooth_extra_permission_data()
.get_allowed_devices();
// Step 2.
let bluetooth = status.get_bluetooth();
let device_map = bluetooth.get_device_map().borrow();
@ -684,7 +762,8 @@ impl PermissionAlgorithm for Bluetooth {
let id = DOMString::from(id.clone());
// Step 2.1.
if allowed_devices.iter().any(|d| d.deviceId == id) &&
!device.is_represented_device_null() {
!device.is_represented_device_null()
{
// Note: We don't need to update the allowed_services,
// because we store it in the lower level
// where it is already up-to-date

View file

@ -29,12 +29,13 @@ pub struct BluetoothAdvertisingEvent {
}
impl BluetoothAdvertisingEvent {
pub fn new_inherited(device: &BluetoothDevice,
pub fn new_inherited(
device: &BluetoothDevice,
name: Option<DOMString>,
appearance: Option<u16>,
tx_power: Option<i8>,
rssi: Option<i8>)
-> BluetoothAdvertisingEvent {
rssi: Option<i8>,
) -> BluetoothAdvertisingEvent {
BluetoothAdvertisingEvent {
event: Event::new_inherited(),
device: Dom::from_ref(device),
@ -45,7 +46,8 @@ impl BluetoothAdvertisingEvent {
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
type_: Atom,
bubbles: EventBubbles,
cancelable: EventCancelable,
@ -53,18 +55,14 @@ impl BluetoothAdvertisingEvent {
name: Option<DOMString>,
appearance: Option<u16>,
txPower: Option<i8>,
rssi: Option<i8>)
-> DomRoot<BluetoothAdvertisingEvent> {
rssi: Option<i8>,
) -> DomRoot<BluetoothAdvertisingEvent> {
let ev = reflect_dom_object(
Box::new(BluetoothAdvertisingEvent::new_inherited(
device,
name,
appearance,
txPower,
rssi
device, name, appearance, txPower, rssi,
)),
global,
BluetoothAdvertisingEventBinding::Wrap
BluetoothAdvertisingEventBinding::Wrap,
);
{
let event = ev.upcast::<Event>();
@ -74,10 +72,11 @@ impl BluetoothAdvertisingEvent {
}
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-bluetoothadvertisingevent
pub fn Constructor(window: &Window,
pub fn Constructor(
window: &Window,
type_: DOMString,
init: &BluetoothAdvertisingEventInit)
-> Fallible<DomRoot<BluetoothAdvertisingEvent>> {
init: &BluetoothAdvertisingEventInit,
) -> Fallible<DomRoot<BluetoothAdvertisingEvent>> {
let global = window.upcast::<GlobalScope>();
let device = init.device.r();
let name = init.name.clone();
@ -86,7 +85,8 @@ impl BluetoothAdvertisingEvent {
let rssi = init.rssi.clone();
let bubbles = EventBubbles::from(init.parent.bubbles);
let cancelable = EventCancelable::from(init.parent.cancelable);
Ok(BluetoothAdvertisingEvent::new(global,
Ok(BluetoothAdvertisingEvent::new(
global,
Atom::from(type_),
bubbles,
cancelable,
@ -94,7 +94,8 @@ impl BluetoothAdvertisingEvent {
name,
appearance,
txPower,
rssi))
rssi,
))
}
}

View file

@ -4,14 +4,14 @@
use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding;
use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding::
BluetoothCharacteristicPropertiesMethods;
BluetoothCharacteristicPropertiesMethods;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::root::DomRoot;
use dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
// https://webbluetoothcg.github.io/web-bluetooth/#characteristicproperties
#[dom_struct]
#[dom_struct]
pub struct BluetoothCharacteristicProperties {
reflector_: Reflector,
broadcast: bool,
@ -26,7 +26,8 @@ pub struct BluetoothCharacteristicProperties {
}
impl BluetoothCharacteristicProperties {
pub fn new_inherited(broadcast: bool,
pub fn new_inherited(
broadcast: bool,
read: bool,
write_without_response: bool,
write: bool,
@ -34,8 +35,8 @@ impl BluetoothCharacteristicProperties {
indicate: bool,
authenticated_signed_writes: bool,
reliable_write: bool,
writable_auxiliaries: bool)
-> BluetoothCharacteristicProperties {
writable_auxiliaries: bool,
) -> BluetoothCharacteristicProperties {
BluetoothCharacteristicProperties {
reflector_: Reflector::new(),
broadcast: broadcast,
@ -50,7 +51,8 @@ impl BluetoothCharacteristicProperties {
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
broadcast: bool,
read: bool,
writeWithoutResponse: bool,
@ -59,8 +61,8 @@ impl BluetoothCharacteristicProperties {
indicate: bool,
authenticatedSignedWrites: bool,
reliableWrite: bool,
writableAuxiliaries: bool)
-> DomRoot<BluetoothCharacteristicProperties> {
writableAuxiliaries: bool,
) -> DomRoot<BluetoothCharacteristicProperties> {
reflect_dom_object(
Box::new(BluetoothCharacteristicProperties::new_inherited(
broadcast,
@ -71,10 +73,10 @@ impl BluetoothCharacteristicProperties {
indicate,
authenticatedSignedWrites,
reliableWrite,
writableAuxiliaries
writableAuxiliaries,
)),
global,
BluetoothCharacteristicPropertiesBinding::Wrap
BluetoothCharacteristicPropertiesBinding::Wrap,
)
}
}

View file

@ -38,79 +38,90 @@ pub struct BluetoothDevice {
name: Option<DOMString>,
gatt: MutNullableDom<BluetoothRemoteGATTServer>,
context: Dom<Bluetooth>,
attribute_instance_map: (DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTService>>>,
attribute_instance_map: (
DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTService>>>,
DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTCharacteristic>>>,
DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTDescriptor>>>),
DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTDescriptor>>>,
),
watching_advertisements: Cell<bool>,
}
impl BluetoothDevice {
pub fn new_inherited(id: DOMString,
pub fn new_inherited(
id: DOMString,
name: Option<DOMString>,
context: &Bluetooth)
-> BluetoothDevice {
context: &Bluetooth,
) -> BluetoothDevice {
BluetoothDevice {
eventtarget: EventTarget::new_inherited(),
id: id,
name: name,
gatt: Default::default(),
context: Dom::from_ref(context),
attribute_instance_map: (DomRefCell::new(HashMap::new()),
attribute_instance_map: (
DomRefCell::new(HashMap::new()),
DomRefCell::new(HashMap::new())),
DomRefCell::new(HashMap::new()),
DomRefCell::new(HashMap::new()),
),
watching_advertisements: Cell::new(false),
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
id: DOMString,
name: Option<DOMString>,
context: &Bluetooth)
-> DomRoot<BluetoothDevice> {
reflect_dom_object(Box::new(BluetoothDevice::new_inherited(id, name, context)),
context: &Bluetooth,
) -> DomRoot<BluetoothDevice> {
reflect_dom_object(
Box::new(BluetoothDevice::new_inherited(id, name, context)),
global,
BluetoothDeviceBinding::Wrap)
BluetoothDeviceBinding::Wrap,
)
}
pub fn get_gatt(&self) -> DomRoot<BluetoothRemoteGATTServer> {
self.gatt.or_init(|| {
BluetoothRemoteGATTServer::new(&self.global(), self)
})
self.gatt
.or_init(|| BluetoothRemoteGATTServer::new(&self.global(), self))
}
fn get_context(&self) -> DomRoot<Bluetooth> {
DomRoot::from_ref(&self.context)
}
pub fn get_or_create_service(&self,
pub fn get_or_create_service(
&self,
service: &BluetoothServiceMsg,
server: &BluetoothRemoteGATTServer)
-> DomRoot<BluetoothRemoteGATTService> {
server: &BluetoothRemoteGATTServer,
) -> DomRoot<BluetoothRemoteGATTService> {
let (ref service_map_ref, _, _) = self.attribute_instance_map;
let mut service_map = service_map_ref.borrow_mut();
if let Some(existing_service) = service_map.get(&service.instance_id) {
return DomRoot::from_ref(&existing_service);
}
let bt_service = BluetoothRemoteGATTService::new(&server.global(),
let bt_service = BluetoothRemoteGATTService::new(
&server.global(),
&server.Device(),
DOMString::from(service.uuid.clone()),
service.is_primary,
service.instance_id.clone());
service.instance_id.clone(),
);
service_map.insert(service.instance_id.clone(), Dom::from_ref(&bt_service));
return bt_service;
}
pub fn get_or_create_characteristic(&self,
pub fn get_or_create_characteristic(
&self,
characteristic: &BluetoothCharacteristicMsg,
service: &BluetoothRemoteGATTService)
-> DomRoot<BluetoothRemoteGATTCharacteristic> {
service: &BluetoothRemoteGATTService,
) -> DomRoot<BluetoothRemoteGATTCharacteristic> {
let (_, ref characteristic_map_ref, _) = self.attribute_instance_map;
let mut characteristic_map = characteristic_map_ref.borrow_mut();
if let Some(existing_characteristic) = characteristic_map.get(&characteristic.instance_id) {
return DomRoot::from_ref(&existing_characteristic);
}
let properties =
BluetoothCharacteristicProperties::new(&service.global(),
let properties = BluetoothCharacteristicProperties::new(
&service.global(),
characteristic.broadcast,
characteristic.read,
characteristic.write_without_response,
@ -119,37 +130,52 @@ impl BluetoothDevice {
characteristic.indicate,
characteristic.authenticated_signed_writes,
characteristic.reliable_write,
characteristic.writable_auxiliaries);
let bt_characteristic = BluetoothRemoteGATTCharacteristic::new(&service.global(),
characteristic.writable_auxiliaries,
);
let bt_characteristic = BluetoothRemoteGATTCharacteristic::new(
&service.global(),
service,
DOMString::from(characteristic.uuid.clone()),
&properties,
characteristic.instance_id.clone());
characteristic_map.insert(characteristic.instance_id.clone(), Dom::from_ref(&bt_characteristic));
characteristic.instance_id.clone(),
);
characteristic_map.insert(
characteristic.instance_id.clone(),
Dom::from_ref(&bt_characteristic),
);
return bt_characteristic;
}
pub fn is_represented_device_null(&self) -> bool {
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
self.get_bluetooth_thread().send(
BluetoothRequest::IsRepresentedDeviceNull(self.Id().to_string(), sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::IsRepresentedDeviceNull(
self.Id().to_string(),
sender,
)).unwrap();
receiver.recv().unwrap()
}
pub fn get_or_create_descriptor(&self,
pub fn get_or_create_descriptor(
&self,
descriptor: &BluetoothDescriptorMsg,
characteristic: &BluetoothRemoteGATTCharacteristic)
-> DomRoot<BluetoothRemoteGATTDescriptor> {
characteristic: &BluetoothRemoteGATTCharacteristic,
) -> DomRoot<BluetoothRemoteGATTDescriptor> {
let (_, _, ref descriptor_map_ref) = self.attribute_instance_map;
let mut descriptor_map = descriptor_map_ref.borrow_mut();
if let Some(existing_descriptor) = descriptor_map.get(&descriptor.instance_id) {
return DomRoot::from_ref(&existing_descriptor);
}
let bt_descriptor = BluetoothRemoteGATTDescriptor::new(&characteristic.global(),
let bt_descriptor = BluetoothRemoteGATTDescriptor::new(
&characteristic.global(),
characteristic,
DOMString::from(descriptor.uuid.clone()),
descriptor.instance_id.clone());
descriptor_map.insert(descriptor.instance_id.clone(), Dom::from_ref(&bt_descriptor));
descriptor.instance_id.clone(),
);
descriptor_map.insert(
descriptor.instance_id.clone(),
Dom::from_ref(&bt_descriptor),
);
return bt_descriptor;
}
@ -180,11 +206,17 @@ impl BluetoothDevice {
// Step 5, 6.4, 7.
// TODO: Step 6: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic.
let _ = self.get_bluetooth_thread().send(
BluetoothRequest::SetRepresentedToNull(service_ids, characteristic_ids, descriptor_ids));
let _ = self
.get_bluetooth_thread()
.send(BluetoothRequest::SetRepresentedToNull(
service_ids,
characteristic_ids,
descriptor_ids,
));
// Step 8.
self.upcast::<EventTarget>().fire_bubbling_event(atom!("gattserverdisconnected"));
self.upcast::<EventTarget>()
.fire_bubbling_event(atom!("gattserverdisconnected"));
}
// https://webbluetoothcg.github.io/web-bluetooth/#garbage-collect-the-connection
@ -206,8 +238,11 @@ impl BluetoothDevice {
// Step 3.
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
self.get_bluetooth_thread().send(
BluetoothRequest::GATTServerDisconnect(String::from(self.Id()), sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::GATTServerDisconnect(
String::from(self.Id()),
sender,
)).unwrap();
receiver.recv().unwrap().map_err(Error::from)
}
}
@ -226,9 +261,14 @@ impl BluetoothDeviceMethods for BluetoothDevice {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-gatt
fn GetGatt(&self) -> Option<DomRoot<BluetoothRemoteGATTServer>> {
// Step 1.
if self.global().as_window().bluetooth_extra_permission_data()
.allowed_devices_contains_id(self.id.clone()) && !self.is_represented_device_null() {
return Some(self.get_gatt())
if self
.global()
.as_window()
.bluetooth_extra_permission_data()
.allowed_devices_contains_id(self.id.clone()) &&
!self.is_represented_device_null()
{
return Some(self.get_gatt());
}
// Step 2.
None
@ -242,8 +282,11 @@ impl BluetoothDeviceMethods for BluetoothDevice {
// TODO: Step 1.
// Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function
// and in handle_response function.
self.get_bluetooth_thread().send(
BluetoothRequest::WatchAdvertisements(String::from(self.Id()), sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::WatchAdvertisements(
String::from(self.Id()),
sender,
)).unwrap();
return p;
}
@ -260,7 +303,11 @@ impl BluetoothDeviceMethods for BluetoothDevice {
}
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdeviceeventhandlers-ongattserverdisconnected
event_handler!(gattserverdisconnected, GetOngattserverdisconnected, SetOngattserverdisconnected);
event_handler!(
gattserverdisconnected,
GetOngattserverdisconnected,
SetOngattserverdisconnected
);
}
impl AsyncBluetoothListener for BluetoothDevice {

View file

@ -40,10 +40,15 @@ impl BluetoothPermissionResult {
result
}
pub fn new(global: &GlobalScope, status: &PermissionStatus) -> DomRoot<BluetoothPermissionResult> {
reflect_dom_object(Box::new(BluetoothPermissionResult::new_inherited(status)),
pub fn new(
global: &GlobalScope,
status: &PermissionStatus,
) -> DomRoot<BluetoothPermissionResult> {
reflect_dom_object(
Box::new(BluetoothPermissionResult::new_inherited(status)),
global,
BluetoothPermissionResultBinding::Wrap)
BluetoothPermissionResultBinding::Wrap,
)
}
pub fn get_bluetooth(&self) -> DomRoot<Bluetooth> {
@ -75,8 +80,12 @@ impl BluetoothPermissionResult {
impl BluetoothPermissionResultMethods for BluetoothPermissionResult {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothpermissionresult-devices
fn Devices(&self) -> Vec<DomRoot<BluetoothDevice>> {
let device_vec: Vec<DomRoot<BluetoothDevice>> =
self.devices.borrow().iter().map(|d| DomRoot::from_ref(&**d)).collect();
let device_vec: Vec<DomRoot<BluetoothDevice>> = self
.devices
.borrow()
.iter()
.map(|d| DomRoot::from_ref(&**d))
.collect();
device_vec
}
}
@ -93,26 +102,29 @@ impl AsyncBluetoothListener for BluetoothPermissionResult {
if let Some(ref existing_device) = device_instance_map.get(&device.id) {
// https://webbluetoothcg.github.io/web-bluetooth/#request-the-bluetooth-permission
// Step 3.
self.set_devices(vec!(Dom::from_ref(&*existing_device)));
self.set_devices(vec![Dom::from_ref(&*existing_device)]);
// https://w3c.github.io/permissions/#dom-permissions-request
// Step 8.
return promise.resolve_native(self);
}
let bt_device = BluetoothDevice::new(&self.global(),
let bt_device = BluetoothDevice::new(
&self.global(),
DOMString::from(device.id.clone()),
device.name.map(DOMString::from),
&bluetooth);
&bluetooth,
);
device_instance_map.insert(device.id.clone(), Dom::from_ref(&bt_device));
self.global().as_window().bluetooth_extra_permission_data().add_new_allowed_device(
AllowedBluetoothDevice {
self.global()
.as_window()
.bluetooth_extra_permission_data()
.add_new_allowed_device(AllowedBluetoothDevice {
deviceId: DOMString::from(device.id),
mayUseGATT: true,
}
);
});
// https://webbluetoothcg.github.io/web-bluetooth/#request-the-bluetooth-permission
// Step 3.
self.set_devices(vec!(Dom::from_ref(&bt_device)));
self.set_devices(vec![Dom::from_ref(&bt_device)]);
// https://w3c.github.io/permissions/#dom-permissions-request
// Step 8.

View file

@ -6,10 +6,10 @@ use bluetooth_traits::{BluetoothRequest, BluetoothResponse, GATTType};
use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted};
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding::
BluetoothCharacteristicPropertiesMethods;
BluetoothCharacteristicPropertiesMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding::
BluetoothRemoteGATTCharacteristicMethods;
BluetoothRemoteGATTCharacteristicMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
use dom::bindings::codegen::UnionTypes::ArrayBufferViewOrArrayBuffer;
@ -45,11 +45,12 @@ pub struct BluetoothRemoteGATTCharacteristic {
}
impl BluetoothRemoteGATTCharacteristic {
pub fn new_inherited(service: &BluetoothRemoteGATTService,
pub fn new_inherited(
service: &BluetoothRemoteGATTService,
uuid: DOMString,
properties: &BluetoothCharacteristicProperties,
instance_id: String)
-> BluetoothRemoteGATTCharacteristic {
instance_id: String,
) -> BluetoothRemoteGATTCharacteristic {
BluetoothRemoteGATTCharacteristic {
eventtarget: EventTarget::new_inherited(),
service: Dom::from_ref(service),
@ -60,18 +61,19 @@ impl BluetoothRemoteGATTCharacteristic {
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
service: &BluetoothRemoteGATTService,
uuid: DOMString,
properties: &BluetoothCharacteristicProperties,
instanceID: String)
-> DomRoot<BluetoothRemoteGATTCharacteristic> {
instanceID: String,
) -> DomRoot<BluetoothRemoteGATTCharacteristic> {
reflect_dom_object(
Box::new(BluetoothRemoteGATTCharacteristic::new_inherited(
service, uuid, properties, instanceID
service, uuid, properties, instanceID,
)),
global,
BluetoothRemoteGATTCharacteristicBinding::Wrap
BluetoothRemoteGATTCharacteristicBinding::Wrap,
)
}
@ -103,17 +105,29 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise> {
get_gatt_children(self, true, BluetoothUUID::descriptor, Some(descriptor), self.get_instance_id(),
self.Service().Device().get_gatt().Connected(), GATTType::Descriptor)
get_gatt_children(
self,
true,
BluetoothUUID::descriptor,
Some(descriptor),
self.get_instance_id(),
self.Service().Device().get_gatt().Connected(),
GATTType::Descriptor,
)
}
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
fn GetDescriptors(&self,
descriptor: Option<BluetoothDescriptorUUID>)
-> Rc<Promise> {
get_gatt_children(self, false, BluetoothUUID::descriptor, descriptor, self.get_instance_id(),
self.Service().Device().get_gatt().Connected(), GATTType::Descriptor)
fn GetDescriptors(&self, descriptor: Option<BluetoothDescriptorUUID>) -> Rc<Promise> {
get_gatt_children(
self,
false,
BluetoothUUID::descriptor,
descriptor,
self.get_instance_id(),
self.Service().Device().get_gatt().Connected(),
GATTType::Descriptor,
)
}
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value
@ -149,8 +163,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// Note: Steps 3 - 4 and the remaining substeps of Step 5 are implemented in components/bluetooth/lib.rs
// in readValue function and in handle_response function.
let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
BluetoothRequest::ReadValue(self.get_instance_id(), sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::ReadValue(self.get_instance_id(), sender))
.unwrap();
return p;
}
@ -187,7 +202,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// Step 7.1.
if !(self.Properties().Write() ||
self.Properties().WriteWithoutResponse() ||
self.Properties().AuthenticatedSignedWrites()) {
self.Properties().AuthenticatedSignedWrites())
{
p.reject_error(NotSupported);
return p;
}
@ -195,8 +211,12 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// Note: Steps 5 - 6 and the remaining substeps of Step 7 are implemented in components/bluetooth/lib.rs
// in writeValue function and in handle_response function.
let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
BluetoothRequest::WriteValue(self.get_instance_id(), vec, sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::WriteValue(
self.get_instance_id(),
vec,
sender,
)).unwrap();
return p;
}
@ -218,8 +238,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
}
// Step 5.
if !(self.Properties().Notify() ||
self.Properties().Indicate()) {
if !(self.Properties().Notify() || self.Properties().Indicate()) {
p.reject_error(NotSupported);
return p;
}
@ -229,10 +248,12 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// Note: Steps 3 - 4, 7 - 11 are implemented in components/bluetooth/lib.rs in enable_notification function
// and in handle_response function.
let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
BluetoothRequest::EnableNotification(self.get_instance_id(),
self.get_bluetooth_thread()
.send(BluetoothRequest::EnableNotification(
self.get_instance_id(),
true,
sender)).unwrap();
sender,
)).unwrap();
return p;
}
@ -246,15 +267,21 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// Note: Steps 1 - 2, and part of Step 4 and Step 5 are implemented in components/bluetooth/lib.rs
// in enable_notification function and in handle_response function.
self.get_bluetooth_thread().send(
BluetoothRequest::EnableNotification(self.get_instance_id(),
self.get_bluetooth_thread()
.send(BluetoothRequest::EnableNotification(
self.get_instance_id(),
false,
sender)).unwrap();
sender,
)).unwrap();
return p;
}
// https://webbluetoothcg.github.io/web-bluetooth/#dom-characteristiceventhandlers-oncharacteristicvaluechanged
event_handler!(characteristicvaluechanged, GetOncharacteristicvaluechanged, SetOncharacteristicvaluechanged);
event_handler!(
characteristicvaluechanged,
GetOncharacteristicvaluechanged,
SetOncharacteristicvaluechanged
);
}
impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
@ -265,10 +292,12 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
// Step 7.
BluetoothResponse::GetDescriptors(descriptors_vec, single) => {
if single {
promise.resolve_native(&device.get_or_create_descriptor(&descriptors_vec[0], &self));
promise.resolve_native(
&device.get_or_create_descriptor(&descriptors_vec[0], &self),
);
return;
}
let mut descriptors = vec!();
let mut descriptors = vec![];
for descriptor in descriptors_vec {
let bt_descriptor = device.get_or_create_descriptor(&descriptor, &self);
descriptors.push(bt_descriptor);
@ -285,7 +314,8 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
*self.value.borrow_mut() = Some(value.clone());
// Step 5.5.3.
self.upcast::<EventTarget>().fire_bubbling_event(atom!("characteristicvaluechanged"));
self.upcast::<EventTarget>()
.fire_bubbling_event(atom!("characteristicvaluechanged"));
// Step 5.5.4.
promise.resolve_native(&value);

View file

@ -6,7 +6,7 @@ use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted};
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding::
BluetoothRemoteGATTCharacteristicMethods;
BluetoothRemoteGATTCharacteristicMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding::BluetoothRemoteGATTDescriptorMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
@ -35,10 +35,11 @@ pub struct BluetoothRemoteGATTDescriptor {
}
impl BluetoothRemoteGATTDescriptor {
pub fn new_inherited(characteristic: &BluetoothRemoteGATTCharacteristic,
pub fn new_inherited(
characteristic: &BluetoothRemoteGATTCharacteristic,
uuid: DOMString,
instance_id: String)
-> BluetoothRemoteGATTDescriptor {
instance_id: String,
) -> BluetoothRemoteGATTDescriptor {
BluetoothRemoteGATTDescriptor {
reflector_: Reflector::new(),
characteristic: Dom::from_ref(characteristic),
@ -48,17 +49,20 @@ impl BluetoothRemoteGATTDescriptor {
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
characteristic: &BluetoothRemoteGATTCharacteristic,
uuid: DOMString,
instanceID: String)
-> DomRoot<BluetoothRemoteGATTDescriptor>{
instanceID: String,
) -> DomRoot<BluetoothRemoteGATTDescriptor> {
reflect_dom_object(
Box::new(BluetoothRemoteGATTDescriptor::new_inherited(
characteristic, uuid, instanceID
characteristic,
uuid,
instanceID,
)),
global,
BluetoothRemoteGATTDescriptorBinding::Wrap
BluetoothRemoteGATTDescriptorBinding::Wrap,
)
}
@ -99,7 +103,13 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
}
// Step 2.
if !self.Characteristic().Service().Device().get_gatt().Connected() {
if !self
.Characteristic()
.Service()
.Device()
.get_gatt()
.Connected()
{
p.reject_error(Network);
return p;
}
@ -108,8 +118,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
// Note: Steps 3 - 4 and substeps of Step 5 are implemented in components/bluetooth/lib.rs
// in readValue function and in handle_response function.
let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
BluetoothRequest::ReadValue(self.get_instance_id(), sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::ReadValue(self.get_instance_id(), sender))
.unwrap();
return p;
}
@ -135,7 +146,13 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
}
// Step 4.
if !self.Characteristic().Service().Device().get_gatt().Connected() {
if !self
.Characteristic()
.Service()
.Device()
.get_gatt()
.Connected()
{
p.reject_error(Network);
return p;
}
@ -144,8 +161,12 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
// Note: Steps 5 - 6 and substeps of Step 7 are implemented in components/bluetooth/lib.rs
// in writeValue function and in handle_response function.
let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
BluetoothRequest::WriteValue(self.get_instance_id(), vec, sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::WriteValue(
self.get_instance_id(),
vec,
sender,
)).unwrap();
return p;
}
}

View file

@ -37,10 +37,15 @@ impl BluetoothRemoteGATTServer {
}
}
pub fn new(global: &GlobalScope, device: &BluetoothDevice) -> DomRoot<BluetoothRemoteGATTServer> {
reflect_dom_object(Box::new(BluetoothRemoteGATTServer::new_inherited(device)),
pub fn new(
global: &GlobalScope,
device: &BluetoothDevice,
) -> DomRoot<BluetoothRemoteGATTServer> {
reflect_dom_object(
Box::new(BluetoothRemoteGATTServer::new_inherited(device)),
global,
BluetoothRemoteGATTServerBinding::Wrap)
BluetoothRemoteGATTServerBinding::Wrap,
)
}
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
@ -78,8 +83,11 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
// Note: Steps 2, 5.1.1 and 5.1.3 are in components/bluetooth/lib.rs in the gatt_server_connect function.
// Steps 5.2.3 - 5.2.5 are in response function.
self.get_bluetooth_thread().send(
BluetoothRequest::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap();
self.get_bluetooth_thread()
.send(BluetoothRequest::GATTServerConnect(
String::from(self.Device().Id()),
sender,
)).unwrap();
// Step 5: return promise.
return p;
}
@ -90,7 +98,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
// Step 2.
if !self.Connected() {
return Ok(())
return Ok(());
}
// Step 3.
@ -104,17 +112,30 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> {
// Step 1 - 2.
get_gatt_children(self, true, BluetoothUUID::service, Some(service), String::from(self.Device().Id()),
self.Device().get_gatt().Connected(), GATTType::PrimaryService)
get_gatt_children(
self,
true,
BluetoothUUID::service,
Some(service),
String::from(self.Device().Id()),
self.Device().get_gatt().Connected(),
GATTType::PrimaryService,
)
}
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
fn GetPrimaryServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> {
// Step 1 - 2.
get_gatt_children(self, false, BluetoothUUID::service, service, String::from(self.Device().Id()),
self.Connected(), GATTType::PrimaryService)
get_gatt_children(
self,
false,
BluetoothUUID::service,
service,
String::from(self.Device().Id()),
self.Connected(),
GATTType::PrimaryService,
)
}
}
@ -145,7 +166,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
promise.resolve_native(&device.get_or_create_service(&services_vec[0], &self));
return;
}
let mut services = vec!();
let mut services = vec![];
for service in services_vec {
let bt_service = device.get_or_create_service(&service, &self);
services.push(bt_service);

View file

@ -30,11 +30,12 @@ pub struct BluetoothRemoteGATTService {
}
impl BluetoothRemoteGATTService {
pub fn new_inherited(device: &BluetoothDevice,
pub fn new_inherited(
device: &BluetoothDevice,
uuid: DOMString,
is_primary: bool,
instance_id: String)
-> BluetoothRemoteGATTService {
instance_id: String,
) -> BluetoothRemoteGATTService {
BluetoothRemoteGATTService {
eventtarget: EventTarget::new_inherited(),
device: Dom::from_ref(device),
@ -44,18 +45,19 @@ impl BluetoothRemoteGATTService {
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
device: &BluetoothDevice,
uuid: DOMString,
isPrimary: bool,
instanceID: String)
-> DomRoot<BluetoothRemoteGATTService> {
instanceID: String,
) -> DomRoot<BluetoothRemoteGATTService> {
reflect_dom_object(
Box::new(BluetoothRemoteGATTService::new_inherited(
device, uuid, isPrimary, instanceID
device, uuid, isPrimary, instanceID,
)),
global,
BluetoothRemoteGATTServiceBinding::Wrap
BluetoothRemoteGATTServiceBinding::Wrap,
)
}
@ -82,39 +84,61 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
fn GetCharacteristic(&self,
characteristic: BluetoothCharacteristicUUID)
-> Rc<Promise> {
get_gatt_children(self, true, BluetoothUUID::characteristic, Some(characteristic), self.get_instance_id(),
self.Device().get_gatt().Connected(), GATTType::Characteristic)
fn GetCharacteristic(&self, characteristic: BluetoothCharacteristicUUID) -> Rc<Promise> {
get_gatt_children(
self,
true,
BluetoothUUID::characteristic,
Some(characteristic),
self.get_instance_id(),
self.Device().get_gatt().Connected(),
GATTType::Characteristic,
)
}
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
fn GetCharacteristics(&self,
characteristic: Option<BluetoothCharacteristicUUID>)
-> Rc<Promise> {
get_gatt_children(self, false, BluetoothUUID::characteristic, characteristic, self.get_instance_id(),
self.Device().get_gatt().Connected(), GATTType::Characteristic)
fn GetCharacteristics(
&self,
characteristic: Option<BluetoothCharacteristicUUID>,
) -> Rc<Promise> {
get_gatt_children(
self,
false,
BluetoothUUID::characteristic,
characteristic,
self.get_instance_id(),
self.Device().get_gatt().Connected(),
GATTType::Characteristic,
)
}
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
fn GetIncludedService(&self,
service: BluetoothServiceUUID)
-> Rc<Promise> {
get_gatt_children(self, false, BluetoothUUID::service, Some(service), self.get_instance_id(),
self.Device().get_gatt().Connected(), GATTType::IncludedService)
fn GetIncludedService(&self, service: BluetoothServiceUUID) -> Rc<Promise> {
get_gatt_children(
self,
false,
BluetoothUUID::service,
Some(service),
self.get_instance_id(),
self.Device().get_gatt().Connected(),
GATTType::IncludedService,
)
}
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
fn GetIncludedServices(&self,
service: Option<BluetoothServiceUUID>)
-> Rc<Promise> {
get_gatt_children(self, false, BluetoothUUID::service, service, self.get_instance_id(),
self.Device().get_gatt().Connected(), GATTType::IncludedService)
fn GetIncludedServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> {
get_gatt_children(
self,
false,
BluetoothUUID::service,
service,
self.get_instance_id(),
self.Device().get_gatt().Connected(),
GATTType::IncludedService,
)
}
// https://webbluetoothcg.github.io/web-bluetooth/#dom-serviceeventhandlers-onserviceadded
@ -135,12 +159,15 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService {
// Step 7.
BluetoothResponse::GetCharacteristics(characteristics_vec, single) => {
if single {
promise.resolve_native(&device.get_or_create_characteristic(&characteristics_vec[0], &self));
promise.resolve_native(
&device.get_or_create_characteristic(&characteristics_vec[0], &self),
);
return;
}
let mut characteristics = vec!();
let mut characteristics = vec![];
for characteristic in characteristics_vec {
let bt_characteristic = device.get_or_create_characteristic(&characteristic, &self);
let bt_characteristic =
device.get_or_create_characteristic(&characteristic, &self);
characteristics.push(bt_characteristic);
}
promise.resolve_native(&characteristics);
@ -149,9 +176,11 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService {
// Step 7.
BluetoothResponse::GetIncludedServices(services_vec, single) => {
if single {
return promise.resolve_native(&device.get_or_create_service(&services_vec[0], &device.get_gatt()));
return promise.resolve_native(
&device.get_or_create_service(&services_vec[0], &device.get_gatt()),
);
}
let mut services = vec!();
let mut services = vec![];
for service in services_vec {
let bt_service = device.get_or_create_service(&service, &device.get_gatt());
services.push(bt_service);

View file

@ -17,7 +17,7 @@ pub type BluetoothCharacteristicUUID = StringOrUnsignedLong;
pub type BluetoothDescriptorUUID = StringOrUnsignedLong;
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothuuid
#[dom_struct]
#[dom_struct]
pub struct BluetoothUUID {
reflector_: Reflector,
}
@ -30,10 +30,16 @@ const BLUETOOTH_ASSIGNED_SERVICES: &'static [(&'static str, u32)] = &[
("org.bluetooth.service.blood_pressure", 0x1810_u32),
("org.bluetooth.service.body_composition", 0x181b_u32),
("org.bluetooth.service.bond_management", 0x181e_u32),
("org.bluetooth.service.continuous_glucose_monitoring", 0x181f_u32),
(
"org.bluetooth.service.continuous_glucose_monitoring",
0x181f_u32,
),
("org.bluetooth.service.current_time", 0x1805_u32),
("org.bluetooth.service.cycling_power", 0x1818_u32),
("org.bluetooth.service.cycling_speed_and_cadence", 0x1816_u32),
(
"org.bluetooth.service.cycling_speed_and_cadence",
0x1816_u32,
),
("org.bluetooth.service.device_information", 0x180a_u32),
("org.bluetooth.service.environmental_sensing", 0x181a_u32),
("org.bluetooth.service.generic_access", 0x1800_u32),
@ -45,7 +51,10 @@ const BLUETOOTH_ASSIGNED_SERVICES: &'static [(&'static str, u32)] = &[
("org.bluetooth.service.human_interface_device", 0x1812_u32),
("org.bluetooth.service.immediate_alert", 0x1802_u32),
("org.bluetooth.service.indoor_positioning", 0x1821_u32),
("org.bluetooth.service.internet_protocol_support", 0x1820_u32),
(
"org.bluetooth.service.internet_protocol_support",
0x1820_u32,
),
("org.bluetooth.service.link_loss", 0x1803_u32),
("org.bluetooth.service.location_and_navigation", 0x1819_u32),
("org.bluetooth.service.next_dst_change", 0x1807_u32),
@ -53,7 +62,10 @@ const BLUETOOTH_ASSIGNED_SERVICES: &'static [(&'static str, u32)] = &[
("org.bluetooth.service.phone_alert_status", 0x180e_u32),
("org.bluetooth.service.pulse_oximeter", 0x1822_u32),
("org.bluetooth.service.reference_time_update", 0x1806_u32),
("org.bluetooth.service.running_speed_and_cadence", 0x1814_u32),
(
"org.bluetooth.service.running_speed_and_cadence",
0x1814_u32,
),
("org.bluetooth.service.scan_parameters", 0x1813_u32),
("org.bluetooth.service.transport_discovery", 0x1824),
("org.bluetooth.service.tx_power", 0x1804_u32),
@ -63,57 +75,150 @@ const BLUETOOTH_ASSIGNED_SERVICES: &'static [(&'static str, u32)] = &[
//https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
const BLUETOOTH_ASSIGNED_CHARCTERISTICS: &'static [(&'static str, u32)] = &[
("org.bluetooth.characteristic.aerobic_heart_rate_lower_limit", 0x2a7e_u32),
("org.bluetooth.characteristic.aerobic_heart_rate_upper_limit", 0x2a84_u32),
(
"org.bluetooth.characteristic.aerobic_heart_rate_lower_limit",
0x2a7e_u32,
),
(
"org.bluetooth.characteristic.aerobic_heart_rate_upper_limit",
0x2a84_u32,
),
("org.bluetooth.characteristic.aerobic_threshold", 0x2a7f_u32),
("org.bluetooth.characteristic.age", 0x2a80_u32),
("org.bluetooth.characteristic.aggregate", 0x2a5a_u32),
("org.bluetooth.characteristic.alert_category_id", 0x2a43_u32),
("org.bluetooth.characteristic.alert_category_id_bit_mask", 0x2a42_u32),
(
"org.bluetooth.characteristic.alert_category_id_bit_mask",
0x2a42_u32,
),
("org.bluetooth.characteristic.alert_level", 0x2a06_u32),
("org.bluetooth.characteristic.alert_notification_control_point", 0x2a44_u32),
(
"org.bluetooth.characteristic.alert_notification_control_point",
0x2a44_u32,
),
("org.bluetooth.characteristic.alert_status", 0x2a3f_u32),
("org.bluetooth.characteristic.altitude", 0x2ab3_u32),
("org.bluetooth.characteristic.anaerobic_heart_rate_lower_limit", 0x2a81_u32),
("org.bluetooth.characteristic.anaerobic_heart_rate_upper_limit", 0x2a82_u32),
("org.bluetooth.characteristic.anaerobic_threshold", 0x2a83_u32),
(
"org.bluetooth.characteristic.anaerobic_heart_rate_lower_limit",
0x2a81_u32,
),
(
"org.bluetooth.characteristic.anaerobic_heart_rate_upper_limit",
0x2a82_u32,
),
(
"org.bluetooth.characteristic.anaerobic_threshold",
0x2a83_u32,
),
("org.bluetooth.characteristic.analog", 0x2a58_u32),
("org.bluetooth.characteristic.apparent_wind_direction", 0x2a73_u32),
("org.bluetooth.characteristic.apparent_wind_speed", 0x2a72_u32),
(
"org.bluetooth.characteristic.apparent_wind_direction",
0x2a73_u32,
),
(
"org.bluetooth.characteristic.apparent_wind_speed",
0x2a72_u32,
),
("org.bluetooth.characteristic.gap.appearance", 0x2a01_u32),
("org.bluetooth.characteristic.barometric_pressure_trend", 0x2aa3_u32),
(
"org.bluetooth.characteristic.barometric_pressure_trend",
0x2aa3_u32,
),
("org.bluetooth.characteristic.battery_level", 0x2a19_u32),
("org.bluetooth.characteristic.blood_pressure_feature", 0x2a49_u32),
("org.bluetooth.characteristic.blood_pressure_measurement", 0x2a35_u32),
("org.bluetooth.characteristic.body_composition_feature", 0x2a9b_u32),
("org.bluetooth.characteristic.body_composition_measurement", 0x2a9c_u32),
("org.bluetooth.characteristic.body_sensor_location", 0x2a38_u32),
("org.bluetooth.characteristic.bond_management_control_point", 0x2aa4_u32),
("org.bluetooth.characteristic.bond_management_feature", 0x2aa5_u32),
("org.bluetooth.characteristic.boot_keyboard_input_report", 0x2a22_u32),
("org.bluetooth.characteristic.boot_keyboard_output_report", 0x2a32_u32),
("org.bluetooth.characteristic.boot_mouse_input_report", 0x2a33_u32),
("org.bluetooth.characteristic.gap.central_address_resolution_support", 0x2aa6_u32),
(
"org.bluetooth.characteristic.blood_pressure_feature",
0x2a49_u32,
),
(
"org.bluetooth.characteristic.blood_pressure_measurement",
0x2a35_u32,
),
(
"org.bluetooth.characteristic.body_composition_feature",
0x2a9b_u32,
),
(
"org.bluetooth.characteristic.body_composition_measurement",
0x2a9c_u32,
),
(
"org.bluetooth.characteristic.body_sensor_location",
0x2a38_u32,
),
(
"org.bluetooth.characteristic.bond_management_control_point",
0x2aa4_u32,
),
(
"org.bluetooth.characteristic.bond_management_feature",
0x2aa5_u32,
),
(
"org.bluetooth.characteristic.boot_keyboard_input_report",
0x2a22_u32,
),
(
"org.bluetooth.characteristic.boot_keyboard_output_report",
0x2a32_u32,
),
(
"org.bluetooth.characteristic.boot_mouse_input_report",
0x2a33_u32,
),
(
"org.bluetooth.characteristic.gap.central_address_resolution_support",
0x2aa6_u32,
),
("org.bluetooth.characteristic.cgm_feature", 0x2aa8_u32),
("org.bluetooth.characteristic.cgm_measurement", 0x2aa7_u32),
("org.bluetooth.characteristic.cgm_session_run_time", 0x2aab_u32),
("org.bluetooth.characteristic.cgm_session_start_time", 0x2aaa_u32),
("org.bluetooth.characteristic.cgm_specific_ops_control_point", 0x2aac_u32),
(
"org.bluetooth.characteristic.cgm_session_run_time",
0x2aab_u32,
),
(
"org.bluetooth.characteristic.cgm_session_start_time",
0x2aaa_u32,
),
(
"org.bluetooth.characteristic.cgm_specific_ops_control_point",
0x2aac_u32,
),
("org.bluetooth.characteristic.cgm_status", 0x2aa9_u32),
("org.bluetooth.characteristic.csc_feature", 0x2a5c_u32),
("org.bluetooth.characteristic.csc_measurement", 0x2a5b_u32),
("org.bluetooth.characteristic.current_time", 0x2a2b_u32),
("org.bluetooth.characteristic.cycling_power_control_point", 0x2a66_u32),
("org.bluetooth.characteristic.cycling_power_feature", 0x2a65_u32),
("org.bluetooth.characteristic.cycling_power_measurement", 0x2a63_u32),
("org.bluetooth.characteristic.cycling_power_vector", 0x2a64_u32),
("org.bluetooth.characteristic.database_change_increment", 0x2a99_u32),
(
"org.bluetooth.characteristic.cycling_power_control_point",
0x2a66_u32,
),
(
"org.bluetooth.characteristic.cycling_power_feature",
0x2a65_u32,
),
(
"org.bluetooth.characteristic.cycling_power_measurement",
0x2a63_u32,
),
(
"org.bluetooth.characteristic.cycling_power_vector",
0x2a64_u32,
),
(
"org.bluetooth.characteristic.database_change_increment",
0x2a99_u32,
),
("org.bluetooth.characteristic.date_of_birth", 0x2a85_u32),
("org.bluetooth.characteristic.date_of_threshold_assessment", 0x2a86_u32),
(
"org.bluetooth.characteristic.date_of_threshold_assessment",
0x2a86_u32,
),
("org.bluetooth.characteristic.date_time", 0x2a08_u32),
("org.bluetooth.characteristic.day_date_time", 0x2a0a_u32),
("org.bluetooth.characteristic.day_of_week", 0x2a09_u32),
("org.bluetooth.characteristic.descriptor_value_changed", 0x2a7d_u32),
(
"org.bluetooth.characteristic.descriptor_value_changed",
0x2a7d_u32,
),
("org.bluetooth.characteristic.gap.device_name", 0x2a00_u32),
("org.bluetooth.characteristic.dew_point", 0x2a7b_u32),
("org.bluetooth.characteristic.digital", 0x2a56_u32),
@ -121,140 +226,332 @@ const BLUETOOTH_ASSIGNED_CHARCTERISTICS: &'static [(&'static str, u32)] = &[
("org.bluetooth.characteristic.elevation", 0x2a6c_u32),
("org.bluetooth.characteristic.email_address", 0x2a87_u32),
("org.bluetooth.characteristic.exact_time_256", 0x2a0c_u32),
("org.bluetooth.characteristic.fat_burn_heart_rate_lower_limit", 0x2a88_u32),
("org.bluetooth.characteristic.fat_burn_heart_rate_upper_limit", 0x2a89_u32),
("org.bluetooth.characteristic.firmware_revision_string", 0x2a26_u32),
(
"org.bluetooth.characteristic.fat_burn_heart_rate_lower_limit",
0x2a88_u32,
),
(
"org.bluetooth.characteristic.fat_burn_heart_rate_upper_limit",
0x2a89_u32,
),
(
"org.bluetooth.characteristic.firmware_revision_string",
0x2a26_u32,
),
("org.bluetooth.characteristic.first_name", 0x2a8a_u32),
("org.bluetooth.characteristic.five_zone_heart_rate_limits", 0x2a8b_u32),
(
"org.bluetooth.characteristic.five_zone_heart_rate_limits",
0x2a8b_u32,
),
("org.bluetooth.characteristic.floor_number", 0x2ab2_u32),
("org.bluetooth.characteristic.gender", 0x2a8c_u32),
("org.bluetooth.characteristic.glucose_feature", 0x2a51_u32),
("org.bluetooth.characteristic.glucose_measurement", 0x2a18_u32),
("org.bluetooth.characteristic.glucose_measurement_context", 0x2a34_u32),
(
"org.bluetooth.characteristic.glucose_measurement",
0x2a18_u32,
),
(
"org.bluetooth.characteristic.glucose_measurement_context",
0x2a34_u32,
),
("org.bluetooth.characteristic.gust_factor", 0x2a74_u32),
("org.bluetooth.characteristic.hardware_revision_string", 0x2a27_u32),
("org.bluetooth.characteristic.heart_rate_control_point", 0x2a39_u32),
(
"org.bluetooth.characteristic.hardware_revision_string",
0x2a27_u32,
),
(
"org.bluetooth.characteristic.heart_rate_control_point",
0x2a39_u32,
),
("org.bluetooth.characteristic.heart_rate_max", 0x2a8d_u32),
("org.bluetooth.characteristic.heart_rate_measurement", 0x2a37_u32),
(
"org.bluetooth.characteristic.heart_rate_measurement",
0x2a37_u32,
),
("org.bluetooth.characteristic.heat_index", 0x2a7a_u32),
("org.bluetooth.characteristic.height", 0x2a8e_u32),
("org.bluetooth.characteristic.hid_control_point", 0x2a4c_u32),
("org.bluetooth.characteristic.hid_information", 0x2a4a_u32),
("org.bluetooth.characteristic.hip_circumference", 0x2a8f_u32),
("org.bluetooth.characteristic.http_control_point", 0x2aba_u32),
(
"org.bluetooth.characteristic.http_control_point",
0x2aba_u32,
),
("org.bluetooth.characteristic.http_entity_body", 0x2ab9_u32),
("org.bluetooth.characteristic.http_headers", 0x2ab7_u32),
("org.bluetooth.characteristic.http_status_code", 0x2ab8_u32),
("org.bluetooth.characteristic.https_security", 0x2abb_u32),
("org.bluetooth.characteristic.humidity", 0x2a6f_u32),
("org.bluetooth.characteristic.ieee_11073-20601_regulatory_certification_data_list", 0x2a2a_u32),
("org.bluetooth.characteristic.indoor_positioning_configuration", 0x2aad_u32),
("org.bluetooth.characteristic.intermediate_cuff_pressure", 0x2a36_u32),
("org.bluetooth.characteristic.intermediate_temperature", 0x2a1e_u32),
(
"org.bluetooth.characteristic.ieee_11073-20601_regulatory_certification_data_list",
0x2a2a_u32,
),
(
"org.bluetooth.characteristic.indoor_positioning_configuration",
0x2aad_u32,
),
(
"org.bluetooth.characteristic.intermediate_cuff_pressure",
0x2a36_u32,
),
(
"org.bluetooth.characteristic.intermediate_temperature",
0x2a1e_u32,
),
("org.bluetooth.characteristic.irradiance", 0x2a77_u32),
("org.bluetooth.characteristic.language", 0x2aa2_u32),
("org.bluetooth.characteristic.last_name", 0x2a90_u32),
("org.bluetooth.characteristic.latitude", 0x2aae_u32),
("org.bluetooth.characteristic.ln_control_point", 0x2a6b_u32),
("org.bluetooth.characteristic.ln_feature", 0x2a6a_u32),
("org.bluetooth.characteristic.local_east_coordinate.xml", 0x2ab1_u32),
("org.bluetooth.characteristic.local_north_coordinate", 0x2ab0_u32),
("org.bluetooth.characteristic.local_time_information", 0x2a0f_u32),
("org.bluetooth.characteristic.location_and_speed", 0x2a67_u32),
(
"org.bluetooth.characteristic.local_east_coordinate.xml",
0x2ab1_u32,
),
(
"org.bluetooth.characteristic.local_north_coordinate",
0x2ab0_u32,
),
(
"org.bluetooth.characteristic.local_time_information",
0x2a0f_u32,
),
(
"org.bluetooth.characteristic.location_and_speed",
0x2a67_u32,
),
("org.bluetooth.characteristic.location_name", 0x2ab5_u32),
("org.bluetooth.characteristic.longitude", 0x2aaf_u32),
("org.bluetooth.characteristic.magnetic_declination", 0x2a2c_u32),
("org.bluetooth.characteristic.magnetic_flux_density_2d", 0x2aa0_u32),
("org.bluetooth.characteristic.magnetic_flux_density_3d", 0x2aa1_u32),
("org.bluetooth.characteristic.manufacturer_name_string", 0x2a29_u32),
("org.bluetooth.characteristic.maximum_recommended_heart_rate", 0x2a91_u32),
("org.bluetooth.characteristic.measurement_interval", 0x2a21_u32),
("org.bluetooth.characteristic.model_number_string", 0x2a24_u32),
(
"org.bluetooth.characteristic.magnetic_declination",
0x2a2c_u32,
),
(
"org.bluetooth.characteristic.magnetic_flux_density_2d",
0x2aa0_u32,
),
(
"org.bluetooth.characteristic.magnetic_flux_density_3d",
0x2aa1_u32,
),
(
"org.bluetooth.characteristic.manufacturer_name_string",
0x2a29_u32,
),
(
"org.bluetooth.characteristic.maximum_recommended_heart_rate",
0x2a91_u32,
),
(
"org.bluetooth.characteristic.measurement_interval",
0x2a21_u32,
),
(
"org.bluetooth.characteristic.model_number_string",
0x2a24_u32,
),
("org.bluetooth.characteristic.navigation", 0x2a68_u32),
("org.bluetooth.characteristic.new_alert", 0x2a46_u32),
("org.bluetooth.characteristic.object_action_control_point", 0x2ac5_u32),
(
"org.bluetooth.characteristic.object_action_control_point",
0x2ac5_u32,
),
("org.bluetooth.characteristic.object_changed", 0x2ac8_u32),
("org.bluetooth.characteristic.object_first_created", 0x2ac1_u32),
(
"org.bluetooth.characteristic.object_first_created",
0x2ac1_u32,
),
("org.bluetooth.characteristic.object_id", 0x2ac3_u32),
("org.bluetooth.characteristic.object_last_modified", 0x2ac2_u32),
("org.bluetooth.characteristic.object_list_control_point", 0x2ac6_u32),
("org.bluetooth.characteristic.object_list_filter", 0x2ac7_u32),
(
"org.bluetooth.characteristic.object_last_modified",
0x2ac2_u32,
),
(
"org.bluetooth.characteristic.object_list_control_point",
0x2ac6_u32,
),
(
"org.bluetooth.characteristic.object_list_filter",
0x2ac7_u32,
),
("org.bluetooth.characteristic.object_name", 0x2abe_u32),
("org.bluetooth.characteristic.object_properties", 0x2ac4_u32),
("org.bluetooth.characteristic.object_size", 0x2ac0_u32),
("org.bluetooth.characteristic.object_type", 0x2abf_u32),
("org.bluetooth.characteristic.ots_feature", 0x2abd_u32),
("org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters", 0x2a04_u32),
("org.bluetooth.characteristic.gap.peripheral_privacy_flag", 0x2a02_u32),
("org.bluetooth.characteristic.plx_continuous_measurement", 0x2a5f_u32),
(
"org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters",
0x2a04_u32,
),
(
"org.bluetooth.characteristic.gap.peripheral_privacy_flag",
0x2a02_u32,
),
(
"org.bluetooth.characteristic.plx_continuous_measurement",
0x2a5f_u32,
),
("org.bluetooth.characteristic.plx_features", 0x2a60_u32),
("org.bluetooth.characteristic.plx_spot_check_measurement", 0x2a5e_u32),
(
"org.bluetooth.characteristic.plx_spot_check_measurement",
0x2a5e_u32,
),
("org.bluetooth.characteristic.pnp_id", 0x2a50_u32),
("org.bluetooth.characteristic.pollen_concentration", 0x2a75_u32),
(
"org.bluetooth.characteristic.pollen_concentration",
0x2a75_u32,
),
("org.bluetooth.characteristic.position_quality", 0x2a69_u32),
("org.bluetooth.characteristic.pressure", 0x2a6d_u32),
("org.bluetooth.characteristic.protocol_mode", 0x2a4e_u32),
("org.bluetooth.characteristic.rainfall", 0x2a78_u32),
("org.bluetooth.characteristic.gap.reconnection_address", 0x2a03_u32),
("org.bluetooth.characteristic.record_access_control_point", 0x2a52_u32),
("org.bluetooth.characteristic.reference_time_information", 0x2a14_u32),
(
"org.bluetooth.characteristic.gap.reconnection_address",
0x2a03_u32,
),
(
"org.bluetooth.characteristic.record_access_control_point",
0x2a52_u32,
),
(
"org.bluetooth.characteristic.reference_time_information",
0x2a14_u32,
),
("org.bluetooth.characteristic.report", 0x2a4d_u32),
("org.bluetooth.characteristic.report_map", 0x2a4b_u32),
("org.bluetooth.characteristic.resting_heart_rate", 0x2a92_u32),
("org.bluetooth.characteristic.ringer_control_point", 0x2a40_u32),
(
"org.bluetooth.characteristic.resting_heart_rate",
0x2a92_u32,
),
(
"org.bluetooth.characteristic.ringer_control_point",
0x2a40_u32,
),
("org.bluetooth.characteristic.ringer_setting", 0x2a41_u32),
("org.bluetooth.characteristic.rsc_feature", 0x2a54_u32),
("org.bluetooth.characteristic.rsc_measurement", 0x2a53_u32),
("org.bluetooth.characteristic.sc_control_point", 0x2a55_u32),
("org.bluetooth.characteristic.scan_interval_window", 0x2a4f_u32),
(
"org.bluetooth.characteristic.scan_interval_window",
0x2a4f_u32,
),
("org.bluetooth.characteristic.scan_refresh", 0x2a31_u32),
("org.bluetooth.characteristic.sensor_location", 0x2a5d_u32),
("org.bluetooth.characteristic.serial_number_string", 0x2a25_u32),
("org.bluetooth.characteristic.gatt.service_changed", 0x2a05_u32),
("org.bluetooth.characteristic.software_revision_string", 0x2a28_u32),
("org.bluetooth.characteristic.sport_type_for_aerobic_and_anaerobic_thresholds", 0x2a93_u32),
("org.bluetooth.characteristic.supported_new_alert_category", 0x2a47_u32),
("org.bluetooth.characteristic.supported_unread_alert_category", 0x2a48_u32),
(
"org.bluetooth.characteristic.serial_number_string",
0x2a25_u32,
),
(
"org.bluetooth.characteristic.gatt.service_changed",
0x2a05_u32,
),
(
"org.bluetooth.characteristic.software_revision_string",
0x2a28_u32,
),
(
"org.bluetooth.characteristic.sport_type_for_aerobic_and_anaerobic_thresholds",
0x2a93_u32,
),
(
"org.bluetooth.characteristic.supported_new_alert_category",
0x2a47_u32,
),
(
"org.bluetooth.characteristic.supported_unread_alert_category",
0x2a48_u32,
),
("org.bluetooth.characteristic.system_id", 0x2a23_u32),
("org.bluetooth.characteristic.tds_control_point", 0x2abc_u32),
("org.bluetooth.characteristic.temperature", 0x2a6e_u32),
("org.bluetooth.characteristic.temperature_measurement", 0x2a1c_u32),
(
"org.bluetooth.characteristic.temperature_measurement",
0x2a1c_u32,
),
("org.bluetooth.characteristic.temperature_type", 0x2a1d_u32),
("org.bluetooth.characteristic.three_zone_heart_rate_limits", 0x2a94_u32),
(
"org.bluetooth.characteristic.three_zone_heart_rate_limits",
0x2a94_u32,
),
("org.bluetooth.characteristic.time_accuracy", 0x2a12_u32),
("org.bluetooth.characteristic.time_source", 0x2a13_u32),
("org.bluetooth.characteristic.time_update_control_point", 0x2a16_u32),
(
"org.bluetooth.characteristic.time_update_control_point",
0x2a16_u32,
),
("org.bluetooth.characteristic.time_update_state", 0x2a17_u32),
("org.bluetooth.characteristic.time_with_dst", 0x2a11_u32),
("org.bluetooth.characteristic.time_zone", 0x2a0e_u32),
("org.bluetooth.characteristic.true_wind_direction", 0x2a71_u32),
(
"org.bluetooth.characteristic.true_wind_direction",
0x2a71_u32,
),
("org.bluetooth.characteristic.true_wind_speed", 0x2a70_u32),
("org.bluetooth.characteristic.two_zone_heart_rate_limit", 0x2a95_u32),
(
"org.bluetooth.characteristic.two_zone_heart_rate_limit",
0x2a95_u32,
),
("org.bluetooth.characteristic.tx_power_level", 0x2a07_u32),
("org.bluetooth.characteristic.uncertainty", 0x2ab4_u32),
("org.bluetooth.characteristic.unread_alert_status", 0x2a45_u32),
(
"org.bluetooth.characteristic.unread_alert_status",
0x2a45_u32,
),
("org.bluetooth.characteristic.uri", 0x2ab6_u32),
("org.bluetooth.characteristic.user_control_point", 0x2a9f_u32),
(
"org.bluetooth.characteristic.user_control_point",
0x2a9f_u32,
),
("org.bluetooth.characteristic.user_index", 0x2a9a_u32),
("org.bluetooth.characteristic.uv_index", 0x2a76_u32),
("org.bluetooth.characteristic.vo2_max", 0x2a96_u32),
("org.bluetooth.characteristic.waist_circumference", 0x2a97_u32),
(
"org.bluetooth.characteristic.waist_circumference",
0x2a97_u32,
),
("org.bluetooth.characteristic.weight", 0x2a98_u32),
("org.bluetooth.characteristic.weight_measurement", 0x2a9d_u32),
("org.bluetooth.characteristic.weight_scale_feature", 0x2a9e_u32),
(
"org.bluetooth.characteristic.weight_measurement",
0x2a9d_u32,
),
(
"org.bluetooth.characteristic.weight_scale_feature",
0x2a9e_u32,
),
("org.bluetooth.characteristic.wind_chill", 0x2a79_u32),
];
//https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
const BLUETOOTH_ASSIGNED_DESCRIPTORS: &'static [(&'static str, u32)] = &[
("org.bluetooth.descriptor.gatt.characteristic_extended_properties", 0x2900_u32),
("org.bluetooth.descriptor.gatt.characteristic_user_description", 0x2901_u32),
("org.bluetooth.descriptor.gatt.client_characteristic_configuration", 0x2902_u32),
("org.bluetooth.descriptor.gatt.server_characteristic_configuration", 0x2903_u32),
("org.bluetooth.descriptor.gatt.characteristic_presentation_format", 0x2904_u32),
("org.bluetooth.descriptor.gatt.characteristic_aggregate_format", 0x2905_u32),
(
"org.bluetooth.descriptor.gatt.characteristic_extended_properties",
0x2900_u32,
),
(
"org.bluetooth.descriptor.gatt.characteristic_user_description",
0x2901_u32,
),
(
"org.bluetooth.descriptor.gatt.client_characteristic_configuration",
0x2902_u32,
),
(
"org.bluetooth.descriptor.gatt.server_characteristic_configuration",
0x2903_u32,
),
(
"org.bluetooth.descriptor.gatt.characteristic_presentation_format",
0x2904_u32,
),
(
"org.bluetooth.descriptor.gatt.characteristic_aggregate_format",
0x2905_u32,
),
("org.bluetooth.descriptor.valid_range", 0x2906_u32),
("org.bluetooth.descriptor.external_report_reference", 0x2907_u32),
(
"org.bluetooth.descriptor.external_report_reference",
0x2907_u32,
),
("org.bluetooth.descriptor.report_reference", 0x2908_u32),
("org.bluetooth.descriptor.number_of_digitals", 0x2909_u32),
("org.bluetooth.descriptor.value_trigger_setting", 0x290a_u32),
@ -268,18 +565,22 @@ const BASE_UUID: &'static str = "-0000-1000-8000-00805f9b34fb";
const SERVICE_PREFIX: &'static str = "org.bluetooth.service";
const CHARACTERISTIC_PREFIX: &'static str = "org.bluetooth.characteristic";
const DESCRIPTOR_PREFIX: &'static str = "org.bluetooth.descriptor";
const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
const VALID_UUID_REGEX: &'static str =
"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=314
const UUID_ERROR_MESSAGE: &'static str = "It must be a valid UUID alias (e.g. 0x1234), \
UUID (lowercase hex characters e.g. '00001234-0000-1000-8000-00805f9b34fb'),\nor recognized standard name from";
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=321
const SERVICES_ERROR_MESSAGE: &'static str = "https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx\
const SERVICES_ERROR_MESSAGE: &'static str =
"https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx\
\ne.g. 'alert_notification'.";
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=327
const CHARACTERISTIC_ERROR_MESSAGE: &'static str = "https://developer.bluetooth.org/gatt/characteristics/Pages/\
const CHARACTERISTIC_ERROR_MESSAGE: &'static str =
"https://developer.bluetooth.org/gatt/characteristics/Pages/\
CharacteristicsHome.aspx\ne.g. 'aerobic_heart_rate_lower_limit'.";
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=333
const DESCRIPTOR_ERROR_MESSAGE: &'static str = "https://developer.bluetooth.org/gatt/descriptors/Pages/\
const DESCRIPTOR_ERROR_MESSAGE: &'static str =
"https://developer.bluetooth.org/gatt/descriptors/Pages/\
DescriptorsHomePage.aspx\ne.g. 'gatt.characteristic_presentation_format'.";
impl BluetoothUUID {
@ -310,7 +611,11 @@ impl BluetoothUUID {
}
pub fn characteristic(name: BluetoothCharacteristicUUID) -> Fallible<UUID> {
resolve_uuid_name(name, BLUETOOTH_ASSIGNED_CHARCTERISTICS, CHARACTERISTIC_PREFIX)
resolve_uuid_name(
name,
BLUETOOTH_ASSIGNED_CHARCTERISTICS,
CHARACTERISTIC_PREFIX,
)
}
pub fn descriptor(name: BluetoothDescriptorUUID) -> Fallible<UUID> {
@ -335,13 +640,11 @@ fn canonical_uuid(alias: u32) -> UUID {
fn resolve_uuid_name(
name: StringOrUnsignedLong,
assigned_numbers_table: &'static [(&'static str, u32)],
prefix: &str)
-> Fallible<DOMString> {
prefix: &str,
) -> Fallible<DOMString> {
match name {
// Step 1.
StringOrUnsignedLong::UnsignedLong(unsigned32) => {
Ok(canonical_uuid(unsigned32))
},
StringOrUnsignedLong::UnsignedLong(unsigned32) => Ok(canonical_uuid(unsigned32)),
StringOrUnsignedLong::String(dstring) => {
// Step 2.
let regex = Regex::new(VALID_UUID_REGEX).unwrap();
@ -356,16 +659,17 @@ fn resolve_uuid_name(
None => {
let (attribute_type, error_url_message) = match prefix {
SERVICE_PREFIX => ("Service", SERVICES_ERROR_MESSAGE),
CHARACTERISTIC_PREFIX => ("Characteristic", CHARACTERISTIC_ERROR_MESSAGE),
CHARACTERISTIC_PREFIX => {
("Characteristic", CHARACTERISTIC_ERROR_MESSAGE)
},
DESCRIPTOR_PREFIX => ("Descriptor", DESCRIPTOR_ERROR_MESSAGE),
_ => unreachable!(),
};
// Step 4.
return Err(Type(format!("Invalid {} name : '{}'.\n{} {}",
attribute_type,
dstring,
UUID_ERROR_MESSAGE,
error_url_message)));
return Err(Type(format!(
"Invalid {} name : '{}'.\n{} {}",
attribute_type, dstring, UUID_ERROR_MESSAGE, error_url_message
)));
},
}
}

View file

@ -40,9 +40,11 @@ impl CanvasGradient {
}
pub fn new(global: &GlobalScope, style: CanvasGradientStyle) -> DomRoot<CanvasGradient> {
reflect_dom_object(Box::new(CanvasGradient::new_inherited(style)),
reflect_dom_object(
Box::new(CanvasGradient::new_inherited(style)),
global,
CanvasGradientBinding::Wrap)
CanvasGradientBinding::Wrap,
)
}
}
@ -60,10 +62,10 @@ impl CanvasGradientMethods for CanvasGradient {
match color {
Ok(CSSColor::RGBA(rgba)) => rgba,
Ok(CSSColor::CurrentColor) => RGBA::new(0, 0, 0, 255),
_ => return Err(Error::Syntax)
_ => return Err(Error::Syntax),
}
} else {
return Err(Error::Syntax)
return Err(Error::Syntax);
};
self.stops.borrow_mut().push(CanvasGradientStop {
@ -83,21 +85,25 @@ impl<'a> ToFillOrStrokeStyle for &'a CanvasGradient {
let gradient_stops = self.stops.borrow().clone();
match self.style {
CanvasGradientStyle::Linear(ref gradient) => {
FillOrStrokeStyle::LinearGradient(LinearGradientStyle::new(gradient.x0,
FillOrStrokeStyle::LinearGradient(LinearGradientStyle::new(
gradient.x0,
gradient.y0,
gradient.x1,
gradient.y1,
gradient_stops))
}
gradient_stops,
))
},
CanvasGradientStyle::Radial(ref gradient) => {
FillOrStrokeStyle::RadialGradient(RadialGradientStyle::new(gradient.x0,
FillOrStrokeStyle::RadialGradient(RadialGradientStyle::new(
gradient.x0,
gradient.y0,
gradient.r0,
gradient.x1,
gradient.y1,
gradient.r1,
gradient_stops))
}
gradient_stops,
))
},
}
}
}

View file

@ -23,11 +23,12 @@ pub struct CanvasPattern {
}
impl CanvasPattern {
fn new_inherited(surface_data: Vec<u8>,
fn new_inherited(
surface_data: Vec<u8>,
surface_size: Size2D<i32>,
repeat: RepetitionStyle,
origin_clean: bool)
-> CanvasPattern {
origin_clean: bool,
) -> CanvasPattern {
let (x, y) = match repeat {
RepetitionStyle::Repeat => (true, true),
RepetitionStyle::RepeatX => (true, false),
@ -44,18 +45,22 @@ impl CanvasPattern {
origin_clean: origin_clean,
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
surface_data: Vec<u8>,
surface_size: Size2D<i32>,
repeat: RepetitionStyle,
origin_clean: bool)
-> DomRoot<CanvasPattern> {
origin_clean: bool,
) -> DomRoot<CanvasPattern> {
reflect_dom_object(
Box::new(CanvasPattern::new_inherited(
surface_data, surface_size, repeat, origin_clean
surface_data,
surface_size,
repeat,
origin_clean,
)),
global,
CanvasPatternBinding::Wrap
CanvasPatternBinding::Wrap,
)
}
pub fn origin_is_clean(&self) -> bool {
@ -65,9 +70,11 @@ impl CanvasPattern {
impl<'a> ToFillOrStrokeStyle for &'a CanvasPattern {
fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
FillOrStrokeStyle::Surface(SurfaceStyle::new(self.surface_data.clone(),
FillOrStrokeStyle::Surface(SurfaceStyle::new(
self.surface_data.clone(),
self.surface_size,
self.repeat_x,
self.repeat_y))
self.repeat_y,
))
}
}

View file

@ -123,17 +123,21 @@ impl CanvasContextState {
}
impl CanvasRenderingContext2D {
pub fn new_inherited(global: &GlobalScope,
pub fn new_inherited(
global: &GlobalScope,
canvas: Option<&HTMLCanvasElement>,
image_cache: Arc<ImageCache>,
base_url: ServoUrl,
size: Size2D<i32>)
-> CanvasRenderingContext2D {
size: Size2D<i32>,
) -> CanvasRenderingContext2D {
debug!("Creating new canvas rendering context.");
let (sender, receiver) = profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap();
let (sender, receiver) =
profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap();
let script_to_constellation_chan = global.script_to_constellation_chan();
debug!("Asking constellation to create new canvas thread.");
script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap();
script_to_constellation_chan
.send(ScriptMsg::CreateCanvasPaintThread(size, sender))
.unwrap();
let (ipc_renderer, canvas_id) = receiver.recv().unwrap();
debug!("Done.");
CanvasRenderingContext2D {
@ -150,15 +154,20 @@ impl CanvasRenderingContext2D {
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
canvas: &HTMLCanvasElement,
size: Size2D<i32>)
-> DomRoot<CanvasRenderingContext2D> {
size: Size2D<i32>,
) -> DomRoot<CanvasRenderingContext2D> {
let window = window_from_node(canvas);
let image_cache = window.image_cache();
let base_url = window.get_url();
let boxed = Box::new(CanvasRenderingContext2D::new_inherited(
global, Some(canvas), image_cache, base_url, size
global,
Some(canvas),
image_cache,
base_url,
size,
));
reflect_dom_object(boxed, global, CanvasRenderingContext2DBinding::Wrap)
}
@ -191,7 +200,8 @@ impl CanvasRenderingContext2D {
// on the drawImage call arguments
// 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,
fn adjust_source_dest_rects(
&self,
image_size: Size2D<f64>,
sx: f64,
sy: f64,
@ -200,19 +210,25 @@ impl CanvasRenderingContext2D {
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));
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),
);
// The source rectangle is the rectangle whose corners are the four points (sx, sy),
// (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).
let source_rect = Rect::new(Point2D::new(sx.min(sx + sw), sy.min(sy + sh)),
Size2D::new(sw.abs(), sh.abs()));
let source_rect = Rect::new(
Point2D::new(sx.min(sx + sw), sy.min(sy + sh)),
Size2D::new(sw.abs(), sh.abs()),
);
// When the source rectangle is outside the source image,
// the source rectangle must be clipped to the source image
let source_rect_clipped = source_rect.intersection(&image_rect).unwrap_or(Rect::zero());
let source_rect_clipped = source_rect
.intersection(&image_rect)
.unwrap_or(Rect::zero());
// Width and height ratios between the non clipped and clipped source rectangles
let width_ratio: f64 = source_rect_clipped.size.width / source_rect.size.width;
@ -225,27 +241,29 @@ impl CanvasRenderingContext2D {
// The destination rectangle is the rectangle whose corners are the four points (dx, dy),
// (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh).
let dest_rect = Rect::new(Point2D::new(dx.min(dx + dest_rect_width_scaled),
dy.min(dy + dest_rect_height_scaled)),
Size2D::new(dest_rect_width_scaled.abs(),
dest_rect_height_scaled.abs()));
let dest_rect = Rect::new(
Point2D::new(
dx.min(dx + dest_rect_width_scaled),
dy.min(dy + dest_rect_height_scaled),
),
Size2D::new(dest_rect_width_scaled.abs(), dest_rect_height_scaled.abs()),
);
let source_rect = Rect::new(Point2D::new(source_rect_clipped.origin.x,
source_rect_clipped.origin.y),
Size2D::new(source_rect_clipped.size.width,
source_rect_clipped.size.height));
let source_rect = Rect::new(
Point2D::new(source_rect_clipped.origin.x, source_rect_clipped.origin.y),
Size2D::new(
source_rect_clipped.size.width,
source_rect_clipped.size.height,
),
);
(source_rect, dest_rect)
}
// https://html.spec.whatwg.org/multipage/#the-image-argument-is-not-origin-clean
fn is_origin_clean(&self,
image: CanvasImageSource)
-> bool {
fn is_origin_clean(&self, image: CanvasImageSource) -> bool {
match image {
CanvasImageSource::HTMLCanvasElement(canvas) => {
canvas.origin_is_clean()
}
CanvasImageSource::HTMLCanvasElement(canvas) => canvas.origin_is_clean(),
CanvasImageSource::HTMLImageElement(image) => {
image.same_origin(GlobalScope::entry().origin())
}
@ -274,7 +292,8 @@ 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,
fn draw_image(
&self,
image: CanvasImageSource,
sx: f64,
sy: f64,
@ -283,29 +302,25 @@ impl CanvasRenderingContext2D {
dx: f64,
dy: f64,
dw: Option<f64>,
dh: Option<f64>)
-> ErrorResult {
dh: Option<f64>,
) -> ErrorResult {
let result = match image {
CanvasImageSource::HTMLCanvasElement(ref canvas) => {
self.draw_html_canvas_element(&canvas,
sx, sy, sw, sh,
dx, dy, dw, dh)
}
self.draw_html_canvas_element(&canvas, sx, sy, sw, sh, dx, dy, dw, dh)
},
CanvasImageSource::HTMLImageElement(ref image) => {
// https://html.spec.whatwg.org/multipage/#img-error
// If the image argument is an HTMLImageElement object that is in the broken state,
// then throw an InvalidStateError exception
let url = image.get_url().ok_or(Error::InvalidState)?;
self.fetch_and_draw_image_data(url,
sx, sy, sw, sh,
dx, dy, dw, dh)
}
self.fetch_and_draw_image_data(url, sx, sy, sw, sh, dx, dy, dw, dh)
},
CanvasImageSource::CSSStyleValue(ref value) => {
let url = value.get_url(self.base_url.clone()).ok_or(Error::InvalidState)?;
self.fetch_and_draw_image_data(url,
sx, sy, sw, sh,
dx, dy, dw, dh)
}
let url = value
.get_url(self.base_url.clone())
.ok_or(Error::InvalidState)?;
self.fetch_and_draw_image_data(url, sx, sy, sw, sh, dx, dy, dw, dh)
},
};
if result.is_ok() && !self.is_origin_clean(image) {
@ -339,17 +354,8 @@ 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 Ok(());
@ -384,7 +390,8 @@ impl CanvasRenderingContext2D {
Ok(())
}
fn fetch_and_draw_image_data(&self,
fn fetch_and_draw_image_data(
&self,
url: ServoUrl,
sx: f64,
sy: f64,
@ -393,8 +400,8 @@ impl CanvasRenderingContext2D {
dx: f64,
dy: f64,
dw: Option<f64>,
dh: Option<f64>)
-> ErrorResult {
dh: Option<f64>,
) -> ErrorResult {
debug!("Fetching image {}.", url);
// https://html.spec.whatwg.org/multipage/#img-error
// If the image argument is an HTMLImageElement object that is in the broken state,
@ -413,13 +420,11 @@ impl CanvasRenderingContext2D {
let dh = dh.unwrap_or(image_size.height);
let sw = sw.unwrap_or(image_size.width);
let sh = sh.unwrap_or(image_size.height);
self.draw_image_data(image_data,
image_size,
sx, sy, sw, sh,
dx, dy, dw, dh)
self.draw_image_data(image_data, image_size, sx, sy, sw, sh, dx, dy, dw, dh)
}
fn draw_image_data(&self,
fn draw_image_data(
&self,
image_data: Vec<u8>,
image_size: Size2D<f64>,
sx: f64,
@ -429,18 +434,11 @@ impl CanvasRenderingContext2D {
dx: f64,
dy: f64,
dw: f64,
dh: f64)
-> ErrorResult {
dh: f64,
) -> ErrorResult {
// 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 Ok(());
@ -465,7 +463,7 @@ impl CanvasRenderingContext2D {
ImageResponse::None |
ImageResponse::MetadataLoaded(_) => {
return None;
}
},
};
let image_size = Size2D::new(img.width as i32, img.height as i32);
@ -481,15 +479,16 @@ impl CanvasRenderingContext2D {
#[inline]
fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse {
let response = self.image_cache
.find_image_or_metadata(url.clone(),
let response = self.image_cache.find_image_or_metadata(
url.clone(),
UsePlaceholder::No,
CanRequestImages::No);
CanRequestImages::No,
);
match response {
Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) =>
ImageResponse::Loaded(image, url),
Err(ImageState::Pending(_)) =>
ImageResponse::None,
Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => {
ImageResponse::Loaded(image, url)
},
Err(ImageState::Pending(_)) => ImageResponse::None,
_ => {
// Rather annoyingly, we get the same response back from
// A load which really failed and from a load which hasn't started yet.
@ -512,8 +511,10 @@ 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),
))
}
fn parse_color(&self, string: &str) -> Result<RGBA, ()> {
@ -540,11 +541,13 @@ impl CanvasRenderingContext2D {
let canvas_element = canvas.upcast::<Element>();
match canvas_element.style() {
Some(ref s) if canvas_element.has_css_layout_box() => Ok(s.get_color().color),
_ => Ok(RGBA::new(0, 0, 0, 255))
Some(ref s) if canvas_element.has_css_layout_box() => {
Ok(s.get_color().color)
},
_ => Ok(RGBA::new(0, 0, 0, 255)),
}
},
_ => Err(())
_ => Err(()),
}
} else {
Err(())
@ -556,7 +559,9 @@ impl CanvasRenderingContext2D {
}
pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) {
self.ipc_renderer.send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())).unwrap()
self.ipc_renderer
.send(CanvasMsg::Canvas2d(msg, self.get_canvas_id()))
.unwrap()
}
pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
@ -610,7 +615,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-save
fn Save(&self) {
self.saved_states.borrow_mut().push(self.state.borrow().clone());
self.saved_states
.borrow_mut()
.push(self.state.borrow().clone());
self.send_canvas_2d_msg(Canvas2dMsg::SaveContext);
}
@ -643,10 +650,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
let (sin, cos) = (angle.sin(), angle.cos());
let transform = self.state.borrow().transform;
self.state.borrow_mut().transform = transform.pre_mul(
&Transform2D::row_major(cos as f32, sin as f32,
-sin as f32, cos as f32,
0.0, 0.0));
self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major(
cos as f32,
sin as f32,
-sin as f32,
cos as f32,
0.0,
0.0,
));
self.update_transform()
}
@ -663,21 +674,32 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-transform
fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
if !(a.is_finite() && b.is_finite() && c.is_finite() &&
d.is_finite() && e.is_finite() && f.is_finite()) {
if !(a.is_finite() &&
b.is_finite() &&
c.is_finite() &&
d.is_finite() &&
e.is_finite() &&
f.is_finite())
{
return;
}
let transform = self.state.borrow().transform;
self.state.borrow_mut().transform = transform.pre_mul(
&Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32));
self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major(
a as f32, b as f32, c as f32, d as f32, e as f32, f as f32,
));
self.update_transform()
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform
fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
if !(a.is_finite() && b.is_finite() && c.is_finite() &&
d.is_finite() && e.is_finite() && f.is_finite()) {
if !(a.is_finite() &&
b.is_finite() &&
c.is_finite() &&
d.is_finite() &&
e.is_finite() &&
f.is_finite())
{
return;
}
@ -784,7 +806,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
CanvasFillRule::Nonzero => FillRule::Nonzero,
CanvasFillRule::Evenodd => FillRule::Evenodd,
};
let (sender, receiver) = profiled_ipc::channel::<bool>(self.global().time_profiler_chan().clone()).unwrap();
let (sender, receiver) =
profiled_ipc::channel::<bool>(self.global().time_profiler_chan().clone()).unwrap();
self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender));
receiver.recv().unwrap()
}
@ -797,11 +820,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage(&self,
image: CanvasImageSource,
dx: f64,
dy: f64)
-> ErrorResult {
fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
if !(dx.is_finite() && dy.is_finite()) {
return Ok(());
}
@ -810,13 +829,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage_(&self,
fn DrawImage_(
&self,
image: CanvasImageSource,
dx: f64,
dy: f64,
dw: f64,
dh: f64)
-> ErrorResult {
dh: f64,
) -> ErrorResult {
if !(dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) {
return Ok(());
}
@ -825,7 +845,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage__(&self,
fn DrawImage__(
&self,
image: CanvasImageSource,
sx: f64,
sy: f64,
@ -834,14 +855,22 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
dx: f64,
dy: f64,
dw: f64,
dh: f64)
-> ErrorResult {
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()) {
dh: f64,
) -> ErrorResult {
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,
self.draw_image(
image,
sx,
sy,
Some(sw),
@ -849,7 +878,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
dx,
dy,
Some(dw),
Some(dh))
Some(dh),
)
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto
@ -871,8 +901,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-rect
fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
if [x, y, width, height].iter().all(|val| val.is_finite()) {
let rect = Rect::new(Point2D::new(x as f32, y as f32),
Size2D::new(width as f32, height as f32));
let rect = Rect::new(
Point2D::new(x as f32, y as f32),
Size2D::new(width as f32, height as f32),
);
self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect));
}
}
@ -882,23 +914,28 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) {
return;
}
self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32,
cpy as f32),
Point2D::new(x as f32,
y as f32)));
self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo(
Point2D::new(cpx as f32, cpy as f32),
Point2D::new(x as f32, y as f32),
));
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto
fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
if !(cp1x.is_finite() && cp1y.is_finite() && cp2x.is_finite() && cp2y.is_finite() &&
x.is_finite() && y.is_finite()) {
if !(cp1x.is_finite() &&
cp1y.is_finite() &&
cp2x.is_finite() &&
cp2y.is_finite() &&
x.is_finite() &&
y.is_finite())
{
return;
}
self.send_canvas_2d_msg(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.send_canvas_2d_msg(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),
));
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-arc
@ -911,11 +948,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
return Err(Error::IndexSize);
}
self.send_canvas_2d_msg(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32),
self.send_canvas_2d_msg(Canvas2dMsg::Arc(
Point2D::new(x as f32, y as f32),
r as f32,
start as f32,
end as f32,
ccw));
ccw,
));
Ok(())
}
@ -928,28 +967,45 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
return Err(Error::IndexSize);
}
self.send_canvas_2d_msg(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32),
self.send_canvas_2d_msg(Canvas2dMsg::ArcTo(
Point2D::new(cp1x as f32, cp1y as f32),
Point2D::new(cp2x as f32, cp2y as f32),
r as f32));
r as f32,
));
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse
fn Ellipse(&self, x: f64, y: f64, rx: f64, ry: f64, rotation: f64, start: f64, end: f64, ccw: bool) -> ErrorResult {
if !([x, y, rx, ry, rotation, start, end].iter().all(|x| x.is_finite())) {
fn Ellipse(
&self,
x: f64,
y: f64,
rx: f64,
ry: f64,
rotation: f64,
start: f64,
end: f64,
ccw: bool,
) -> ErrorResult {
if !([x, y, rx, ry, rotation, start, end]
.iter()
.all(|x| x.is_finite()))
{
return Ok(());
}
if rx < 0.0 || ry < 0.0 {
return Err(Error::IndexSize);
}
self.send_canvas_2d_msg(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32),
self.send_canvas_2d_msg(Canvas2dMsg::Ellipse(
Point2D::new(x as f32, y as f32),
rx as f32,
ry as f32,
rotation as f32,
start as f32,
end as f32,
ccw));
ccw,
));
Ok(())
}
@ -977,7 +1033,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
},
CanvasFillOrStrokeStyle::Pattern(ref pattern) => {
StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern))
}
},
}
}
@ -987,23 +1043,28 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
StringOrCanvasGradientOrCanvasPattern::String(string) => {
if let Ok(rgba) = self.parse_color(&string) {
self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba);
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(
FillOrStrokeStyle::Color(rgba)));
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(FillOrStrokeStyle::Color(
rgba,
)));
}
},
StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => {
self.state.borrow_mut().stroke_style =
CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient));
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style()));
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(
gradient.to_fill_or_stroke_style(),
));
},
StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => {
self.state.borrow_mut().stroke_style =
CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern));
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style()));
self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(
pattern.to_fill_or_stroke_style(),
));
if !pattern.origin_is_clean() {
self.set_origin_unclean();
}
}
},
}
}
@ -1020,7 +1081,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
},
CanvasFillOrStrokeStyle::Pattern(ref pattern) => {
StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern))
}
},
}
}
@ -1030,23 +1091,28 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
StringOrCanvasGradientOrCanvasPattern::String(string) => {
if let Ok(rgba) = self.parse_color(&string) {
self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba);
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(
FillOrStrokeStyle::Color(rgba)))
}
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(FillOrStrokeStyle::Color(
rgba,
)))
}
},
StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => {
self.state.borrow_mut().fill_style =
CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient));
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style()));
}
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(
gradient.to_fill_or_stroke_style(),
));
},
StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => {
self.state.borrow_mut().fill_style =
CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern));
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style()));
self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(
pattern.to_fill_or_stroke_style(),
));
if !pattern.origin_is_clean() {
self.set_origin_unclean();
}
}
},
}
}
@ -1063,21 +1129,19 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible<DomRoot<ImageData>> {
ImageData::new(&self.global(),
imagedata.Width(),
imagedata.Height(),
None)
ImageData::new(&self.global(), imagedata.Width(), imagedata.Height(), None)
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata
fn GetImageData(&self,
fn GetImageData(
&self,
sx: Finite<f64>,
sy: Finite<f64>,
sw: Finite<f64>,
sh: Finite<f64>)
-> Fallible<DomRoot<ImageData>> {
sh: Finite<f64>,
) -> Fallible<DomRoot<ImageData>> {
if !self.origin_is_clean() {
return Err(Error::Security)
return Err(Error::Security);
}
let mut sx = *sx;
@ -1102,9 +1166,15 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
let sw = cmp::max(1, sw.to_u32().unwrap());
let (sender, receiver) = ipc::bytes_channel().unwrap();
let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()),
Size2D::new(sw as i32, sh as i32));
let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero());
let dest_rect = Rect::new(
Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()),
Size2D::new(sw as i32, sh as i32),
);
let canvas_size = self
.canvas
.as_ref()
.map(|c| c.get_size())
.unwrap_or(Size2D::zero());
let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender));
let mut data = receiver.recv().unwrap();
@ -1122,97 +1192,110 @@ 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,
self.PutImageData_(
imagedata,
dx,
dy,
Finite::wrap(0f64),
Finite::wrap(0f64),
Finite::wrap(imagedata.Width() as f64),
Finite::wrap(imagedata.Height() as f64))
Finite::wrap(imagedata.Height() as f64),
)
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
fn PutImageData_(&self,
fn PutImageData_(
&self,
imagedata: &ImageData,
dx: Finite<f64>,
dy: Finite<f64>,
dirty_x: Finite<f64>,
dirty_y: Finite<f64>,
dirty_width: Finite<f64>,
dirty_height: Finite<f64>) {
dirty_height: Finite<f64>,
) {
let data = imagedata.get_data_array();
let offset = Vector2D::new(*dx, *dy);
let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64);
let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y),
Size2D::new(*dirty_width, *dirty_height));
self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(data.into(),
let dirty_rect = Rect::new(
Point2D::new(*dirty_x, *dirty_y),
Size2D::new(*dirty_width, *dirty_height),
);
self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(
data.into(),
offset,
image_data_size,
dirty_rect));
dirty_rect,
));
self.mark_as_dirty();
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient
fn CreateLinearGradient(&self,
fn CreateLinearGradient(
&self,
x0: Finite<f64>,
y0: Finite<f64>,
x1: Finite<f64>,
y1: Finite<f64>)
-> DomRoot<CanvasGradient> {
CanvasGradient::new(&self.global(),
CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0,
*y0,
*x1,
*y1,
Vec::new())))
y1: Finite<f64>,
) -> DomRoot<CanvasGradient> {
CanvasGradient::new(
&self.global(),
CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new())),
)
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient
fn CreateRadialGradient(&self,
fn CreateRadialGradient(
&self,
x0: Finite<f64>,
y0: Finite<f64>,
r0: Finite<f64>,
x1: Finite<f64>,
y1: Finite<f64>,
r1: Finite<f64>)
-> Fallible<DomRoot<CanvasGradient>> {
r1: Finite<f64>,
) -> Fallible<DomRoot<CanvasGradient>> {
if *r0 < 0. || *r1 < 0. {
return Err(Error::IndexSize);
}
Ok(CanvasGradient::new(&self.global(),
CanvasGradientStyle::Radial(RadialGradientStyle::new(*x0,
Ok(CanvasGradient::new(
&self.global(),
CanvasGradientStyle::Radial(RadialGradientStyle::new(
*x0,
*y0,
*r0,
*x1,
*y1,
*r1,
Vec::new()))))
Vec::new(),
)),
))
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
fn CreatePattern(&self,
fn CreatePattern(
&self,
image: CanvasImageSource,
mut repetition: DOMString)
-> Fallible<DomRoot<CanvasPattern>> {
mut repetition: DOMString,
) -> Fallible<DomRoot<CanvasPattern>> {
let (image_data, image_size) = match image {
CanvasImageSource::HTMLImageElement(ref image) => {
// https://html.spec.whatwg.org/multipage/#img-error
// If the image argument is an HTMLImageElement object that is in the broken state,
// then throw an InvalidStateError exception
image.get_url()
image
.get_url()
.and_then(|url| self.fetch_image_data(url))
.ok_or(Error::InvalidState)?
},
CanvasImageSource::HTMLCanvasElement(ref canvas) => {
canvas.fetch_all_data().ok_or(Error::InvalidState)?
},
CanvasImageSource::CSSStyleValue(ref value) => {
value.get_url(self.base_url.clone())
CanvasImageSource::CSSStyleValue(ref value) => value
.get_url(self.base_url.clone())
.and_then(|url| self.fetch_image_data(url))
.ok_or(Error::InvalidState)?
}
.ok_or(Error::InvalidState)?,
};
if repetition.is_empty() {
@ -1220,11 +1303,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
}
if let Ok(rep) = RepetitionStyle::from_str(&repetition) {
Ok(CanvasPattern::new(&self.global(),
Ok(CanvasPattern::new(
&self.global(),
image_data,
image_size,
rep,
self.is_origin_clean(image)))
self.is_origin_clean(image),
))
} else {
Err(Error::Syntax)
}
@ -1362,7 +1447,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
impl Drop for CanvasRenderingContext2D {
fn drop(&mut self) {
if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close(self.get_canvas_id())) {
if let Err(err) = self
.ipc_renderer
.send(CanvasMsg::Close(self.get_canvas_id()))
{
warn!("Could not close canvas: {}", err)
}
}
@ -1391,22 +1479,32 @@ 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
where
W: fmt::Write,
{
let red = color.red;
let green = color.green;
let blue = color.blue;
if color.alpha == 255 {
write!(dest,
write!(
dest,
"#{:x}{:x}{:x}{:x}{:x}{:x}",
red >> 4,
red & 0xF,
green >> 4,
green & 0xF,
blue >> 4,
blue & 0xF)
blue & 0xF
)
} else {
write!(dest, "rgba({}, {}, {}, {})", red, green, blue, color.alpha_f32())
write!(
dest,
"rgba({}, {}, {}, {})",
red,
green,
blue,
color.alpha_f32()
)
}
}

View file

@ -26,16 +26,18 @@ impl ChannelMergerNode {
context: &BaseAudioContext,
options: &ChannelMergerOptions,
) -> Fallible<ChannelMergerNode> {
let node_options = options.parent
.unwrap_or(1, ChannelCountMode::Explicit,
ChannelInterpretation::Speakers);
let node_options = options.parent.unwrap_or(
1,
ChannelCountMode::Explicit,
ChannelInterpretation::Speakers,
);
if node_options.count != 1 || node_options.mode != ChannelCountMode::Explicit {
return Err(Error::InvalidState)
return Err(Error::InvalidState);
}
if options.numberOfInputs < 1 || options.numberOfInputs > MAX_CHANNEL_COUNT {
return Err(Error::IndexSize)
return Err(Error::IndexSize);
}
let node = AudioNode::new_inherited(
@ -45,9 +47,7 @@ impl ChannelMergerNode {
options.numberOfInputs, // inputs
1, // outputs
)?;
Ok(ChannelMergerNode {
node,
})
Ok(ChannelMergerNode { node })
}
#[allow(unrooted_must_root)]
@ -57,7 +57,11 @@ impl ChannelMergerNode {
options: &ChannelMergerOptions,
) -> Fallible<DomRoot<ChannelMergerNode>> {
let node = ChannelMergerNode::new_inherited(window, context, options)?;
Ok(reflect_dom_object(Box::new(node), window, ChannelMergerNodeBinding::Wrap))
Ok(reflect_dom_object(
Box::new(node),
window,
ChannelMergerNodeBinding::Wrap,
))
}
pub fn Constructor(

View file

@ -45,7 +45,7 @@ impl CharacterData {
match self.upcast::<Node>().type_id() {
NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => {
DomRoot::upcast(Comment::new(data, &document))
}
},
NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
let pi = self.downcast::<ProcessingInstruction>().unwrap();
DomRoot::upcast(ProcessingInstruction::new(pi.Target(), data, &document))
@ -107,7 +107,8 @@ impl CharacterDataMethods for CharacterData {
*self.data.borrow_mut() = data;
self.content_changed();
let node = self.upcast::<Node>();
node.ranges().replace_code_units(node, 0, old_length, new_length);
node.ranges()
.replace_code_units(node, 0, old_length, new_length);
}
// https://dom.spec.whatwg.org/#dom-characterdata-length
@ -130,7 +131,7 @@ impl CharacterDataMethods for CharacterData {
substring = substring + "\u{FFFD}";
}
remaining = s;
}
},
// Step 2.
Err(()) => return Err(Error::IndexSize),
}
@ -146,7 +147,7 @@ impl CharacterDataMethods for CharacterData {
if astral.is_some() {
substring = substring + "\u{FFFD}";
}
}
},
};
Ok(DOMString::from(substring))
}
@ -183,7 +184,7 @@ impl CharacterDataMethods for CharacterData {
// since our DOMString is currently strict UTF-8.
replacement_before = if astral.is_some() { "\u{FFFD}" } else { "" };
remaining = r;
}
},
// Step 2.
Err(()) => return Err(Error::IndexSize),
};
@ -194,14 +195,14 @@ impl CharacterDataMethods for CharacterData {
Err(()) => {
replacement_after = "";
suffix = "";
}
},
Ok((_, astral, s)) => {
// As if we had split the UTF-16 surrogate pair in half
// and then transcoded that to UTF-8 lossily,
// since our DOMString is currently strict UTF-8.
replacement_after = if astral.is_some() { "\u{FFFD}" } else { "" };
suffix = s;
}
},
};
// Step 4: Mutation observers.
self.queue_mutation_record();
@ -212,7 +213,8 @@ impl CharacterDataMethods for CharacterData {
replacement_before.len() +
arg.len() +
replacement_after.len() +
suffix.len());
suffix.len(),
);
new_data.push_str(prefix);
new_data.push_str(replacement_before);
new_data.push_str(&arg);
@ -223,8 +225,8 @@ impl CharacterDataMethods for CharacterData {
self.content_changed();
// Steps 8-11.
let node = self.upcast::<Node>();
node.ranges().replace_code_units(
node, offset, count, arg.encode_utf16().count() as u32);
node.ranges()
.replace_code_units(node, offset, count, arg.encode_utf16().count() as u32);
Ok(())
}
@ -251,12 +253,18 @@ impl CharacterDataMethods for CharacterData {
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
fn GetPreviousElementSibling(&self) -> Option<DomRoot<Element>> {
self.upcast::<Node>().preceding_siblings().filter_map(DomRoot::downcast).next()
self.upcast::<Node>()
.preceding_siblings()
.filter_map(DomRoot::downcast)
.next()
}
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
fn GetNextElementSibling(&self) -> Option<DomRoot<Element>> {
self.upcast::<Node>().following_siblings().filter_map(DomRoot::downcast).next()
self.upcast::<Node>()
.following_siblings()
.filter_map(DomRoot::downcast)
.next()
}
}
@ -305,13 +313,15 @@ fn split_at_utf16_code_unit_offset(s: &str, offset: u32) -> Result<(&str, Option
if code_units == offset {
if opts::get().replace_surrogates {
debug_assert_eq!(c.len_utf8(), 4);
return Ok((&s[..i], Some(c), &s[i + c.len_utf8()..]))
return Ok((&s[..i], Some(c), &s[i + c.len_utf8()..]));
}
panic!("\n\n\
panic!(
"\n\n\
Would split a surrogate pair in CharacterData API.\n\
If you see this in real content, please comment with the URL\n\
on https://github.com/servo/servo/issues/6873\n\
\n");
\n"
);
}
code_units += 1;
}

View file

@ -21,7 +21,7 @@ pub struct Client {
url: ServoUrl,
frame_type: FrameType,
#[ignore_malloc_size_of = "Defined in uuid"]
id: Uuid
id: Uuid,
}
impl Client {
@ -31,14 +31,16 @@ impl Client {
active_worker: Default::default(),
url: url,
frame_type: FrameType::None,
id: Uuid::new_v4()
id: Uuid::new_v4(),
}
}
pub fn new(window: &Window) -> DomRoot<Client> {
reflect_dom_object(Box::new(Client::new_inherited(window.get_url())),
reflect_dom_object(
Box::new(Client::new_inherited(window.get_url())),
window,
Wrap)
Wrap,
)
}
pub fn creation_url(&self) -> ServoUrl {

View file

@ -34,45 +34,48 @@ impl CloseEvent {
}
pub fn new_uninitialized(global: &GlobalScope) -> DomRoot<CloseEvent> {
reflect_dom_object(Box::new(CloseEvent::new_inherited(false, 0, DOMString::new())),
reflect_dom_object(
Box::new(CloseEvent::new_inherited(false, 0, DOMString::new())),
global,
CloseEventBinding::Wrap)
CloseEventBinding::Wrap,
)
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
type_: Atom,
bubbles: EventBubbles,
cancelable: EventCancelable,
wasClean: bool,
code: u16,
reason: DOMString)
-> DomRoot<CloseEvent> {
reason: DOMString,
) -> DomRoot<CloseEvent> {
let event = Box::new(CloseEvent::new_inherited(wasClean, code, reason));
let ev = reflect_dom_object(event, global, CloseEventBinding::Wrap);
{
let event = ev.upcast::<Event>();
event.init_event(type_,
bool::from(bubbles),
bool::from(cancelable));
event.init_event(type_, bool::from(bubbles), bool::from(cancelable));
}
ev
}
pub fn Constructor(global: &GlobalScope,
pub fn Constructor(
global: &GlobalScope,
type_: DOMString,
init: &CloseEventBinding::CloseEventInit)
-> Fallible<DomRoot<CloseEvent>> {
init: &CloseEventBinding::CloseEventInit,
) -> Fallible<DomRoot<CloseEvent>> {
let bubbles = EventBubbles::from(init.parent.bubbles);
let cancelable = EventCancelable::from(init.parent.cancelable);
Ok(CloseEvent::new(global,
Ok(CloseEvent::new(
global,
Atom::from(type_),
bubbles,
cancelable,
init.wasClean,
init.code,
init.reason.clone()))
init.reason.clone(),
))
}
}
impl CloseEventMethods for CloseEvent {

View file

@ -27,9 +27,11 @@ impl Comment {
}
pub fn new(text: DOMString, document: &Document) -> DomRoot<Comment> {
Node::reflect_node(Box::new(Comment::new_inherited(text, document)),
Node::reflect_node(
Box::new(Comment::new_inherited(text, document)),
document,
CommentBinding::Wrap)
CommentBinding::Wrap,
)
}
pub fn Constructor(window: &Window, data: DOMString) -> Fallible<DomRoot<Comment>> {

View file

@ -19,34 +19,42 @@ pub struct CompositionEvent {
}
impl CompositionEvent {
pub fn new(window: &Window,
pub fn new(
window: &Window,
type_: DOMString,
can_bubble: bool,
cancelable: bool,
view: Option<&Window>,
detail: i32,
data: DOMString) -> DomRoot<CompositionEvent> {
let ev = reflect_dom_object(Box::new(CompositionEvent {
data: DOMString,
) -> DomRoot<CompositionEvent> {
let ev = reflect_dom_object(
Box::new(CompositionEvent {
uievent: UIEvent::new_inherited(),
data: data,
}),
window,
CompositionEventBinding::Wrap);
ev.uievent.InitUIEvent(type_, can_bubble, cancelable, view, detail);
CompositionEventBinding::Wrap,
);
ev.uievent
.InitUIEvent(type_, can_bubble, cancelable, view, detail);
ev
}
pub fn Constructor(window: &Window,
pub fn Constructor(
window: &Window,
type_: DOMString,
init: &CompositionEventBinding::CompositionEventInit)
-> Fallible<DomRoot<CompositionEvent>> {
let event = CompositionEvent::new(window,
init: &CompositionEventBinding::CompositionEventInit,
) -> Fallible<DomRoot<CompositionEvent>> {
let event = CompositionEvent::new(
window,
type_,
init.parent.parent.bubbles,
init.parent.parent.cancelable,
init.parent.view.r(),
init.parent.detail,
init.data.clone());
init.data.clone(),
);
Ok(event)
}
}

View file

@ -16,13 +16,14 @@ impl Console {
fn send_to_devtools(global: &GlobalScope, level: LogLevel, message: DOMString) {
if let Some(chan) = global.devtools_chan() {
let console_message = prepare_message(level, message);
let worker_id = global.downcast::<WorkerGlobalScope>().map(|worker| {
worker.get_worker_id()
});
let worker_id = global
.downcast::<WorkerGlobalScope>()
.map(|worker| worker.get_worker_id());
let devtools_message = ScriptToDevtoolsControlMsg::ConsoleAPI(
global.pipeline_id(),
console_message,
worker_id);
worker_id,
);
chan.send(devtools_message).unwrap();
}
}
@ -33,7 +34,10 @@ impl Console {
// we're finished with stdout. Since the stderr lock is reentrant, there is
// no risk of deadlock if the callback ends up trying to write to stderr for
// any reason.
fn with_stderr_lock<F>(f: F) where F: FnOnce() {
fn with_stderr_lock<F>(f: F)
where
F: FnOnce(),
{
let stderr = io::stderr();
let _handle = stderr.lock();
f()
@ -116,9 +120,7 @@ impl Console {
pub fn TimeEnd(global: &GlobalScope, label: DOMString) {
with_stderr_lock(move || {
if let Ok(delta) = global.time_end(&label) {
let message = DOMString::from(
format!("{}: {}ms", label, delta)
);
let message = DOMString::from(format!("{}: {}ms", label, delta));
println!("{}", message);
Self::send_to_devtools(global, LogLevel::Log, message);
};

View file

@ -84,10 +84,11 @@ use js::jsapi::JSAutoCompartment;
use script_thread::ScriptThread;
use servo_config::prefs::PREFS;
fn create_svg_element(name: QualName,
fn create_svg_element(
name: QualName,
prefix: Option<Prefix>,
document: &Document)
-> DomRoot<Element> {
document: &Document,
) -> DomRoot<Element> {
assert_eq!(name.ns, ns!(svg));
macro_rules! make(
@ -113,13 +114,14 @@ fn create_svg_element(name: QualName,
// https://dom.spec.whatwg.org/#concept-create-element
#[allow(unsafe_code)]
fn create_html_element(name: QualName,
fn create_html_element(
name: QualName,
prefix: Option<Prefix>,
is: Option<LocalName>,
document: &Document,
creator: ElementCreator,
mode: CustomElementCreationMode)
-> DomRoot<Element> {
mode: CustomElementCreationMode,
) -> DomRoot<Element> {
assert_eq!(name.ns, ns!(html));
// Step 4
@ -129,8 +131,11 @@ fn create_html_element(name: QualName,
if definition.is_autonomous() {
match mode {
CustomElementCreationMode::Asynchronous => {
let result = DomRoot::upcast::<Element>(
HTMLElement::new(name.local.clone(), prefix.clone(), document));
let result = DomRoot::upcast::<Element>(HTMLElement::new(
name.local.clone(),
prefix.clone(),
document,
));
result.set_custom_element_state(CustomElementState::Undefined);
ScriptThread::enqueue_upgrade_reaction(&*result, definition);
return result;
@ -144,19 +149,24 @@ fn create_html_element(name: QualName,
},
Err(error) => {
// Step 6. Recovering from exception.
let global = GlobalScope::current().unwrap_or_else(|| document.global());
let global =
GlobalScope::current().unwrap_or_else(|| document.global());
let cx = global.get_cx();
// Step 6.1.1
unsafe {
let _ac = JSAutoCompartment::new(cx, global.reflector().get_jsobject().get());
let _ac = JSAutoCompartment::new(
cx,
global.reflector().get_jsobject().get(),
);
throw_dom_exception(cx, &global, error);
report_pending_exception(cx, true);
}
// Step 6.1.2
let element = DomRoot::upcast::<Element>(
HTMLUnknownElement::new(local_name, prefix, document));
let element = DomRoot::upcast::<Element>(HTMLUnknownElement::new(
local_name, prefix, document,
));
element.set_custom_element_state(CustomElementState::Failed);
element
},
@ -170,11 +180,11 @@ fn create_html_element(name: QualName,
element.set_custom_element_state(CustomElementState::Undefined);
match mode {
// Step 5.3
CustomElementCreationMode::Synchronous =>
upgrade_element(definition, &*element),
CustomElementCreationMode::Synchronous => upgrade_element(definition, &*element),
// Step 5.4
CustomElementCreationMode::Asynchronous =>
ScriptThread::enqueue_upgrade_reaction(&*element, definition),
CustomElementCreationMode::Asynchronous => {
ScriptThread::enqueue_upgrade_reaction(&*element, definition)
},
}
return element;
}
@ -360,16 +370,17 @@ pub fn create_native_html_element(
}
}
pub fn create_element(name: QualName,
pub fn create_element(
name: QualName,
is: Option<LocalName>,
document: &Document,
creator: ElementCreator,
mode: CustomElementCreationMode)
-> DomRoot<Element> {
mode: CustomElementCreationMode,
) -> DomRoot<Element> {
let prefix = name.prefix.clone();
match name.ns {
ns!(html) => create_html_element(name, prefix, is, document, creator, mode),
ns!(svg) => create_svg_element(name, prefix, document),
_ => Element::new(name.local, name.ns, prefix, document)
_ => Element::new(name.local, name.ns, prefix, document),
}
}

View file

@ -36,17 +36,22 @@ impl Crypto {
}
pub fn new(global: &GlobalScope) -> DomRoot<Crypto> {
reflect_dom_object(Box::new(Crypto::new_inherited()), global, CryptoBinding::Wrap)
reflect_dom_object(
Box::new(Crypto::new_inherited()),
global,
CryptoBinding::Wrap,
)
}
}
impl CryptoMethods for Crypto {
#[allow(unsafe_code)]
// https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#Crypto-method-getRandomValues
unsafe fn GetRandomValues(&self,
unsafe fn GetRandomValues(
&self,
_cx: *mut JSContext,
mut input: CustomAutoRooterGuard<ArrayBufferView>)
-> Fallible<NonNull<JSObject>> {
mut input: CustomAutoRooterGuard<ArrayBufferView>,
) -> Fallible<NonNull<JSObject>> {
let array_type = input.get_array_type();
if !is_integer_buffer(array_type) {

View file

@ -20,8 +20,10 @@ pub struct CSSConditionRule {
}
impl CSSConditionRule {
pub fn new_inherited(parent_stylesheet: &CSSStyleSheet,
rules: Arc<Locked<StyleCssRules>>) -> CSSConditionRule {
pub fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
rules: Arc<Locked<StyleCssRules>>,
) -> CSSConditionRule {
CSSConditionRule {
cssgroupingrule: CSSGroupingRule::new_inherited(parent_stylesheet, rules),
}

View file

@ -22,8 +22,10 @@ pub struct CSSFontFaceRule {
}
impl CSSFontFaceRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet, fontfacerule: Arc<Locked<FontFaceRule>>)
-> CSSFontFaceRule {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
fontfacerule: Arc<Locked<FontFaceRule>>,
) -> CSSFontFaceRule {
CSSFontFaceRule {
cssrule: CSSRule::new_inherited(parent_stylesheet),
fontfacerule: fontfacerule,
@ -31,11 +33,19 @@ impl CSSFontFaceRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
fontfacerule: Arc<Locked<FontFaceRule>>) -> DomRoot<CSSFontFaceRule> {
reflect_dom_object(Box::new(CSSFontFaceRule::new_inherited(parent_stylesheet, fontfacerule)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
fontfacerule: Arc<Locked<FontFaceRule>>,
) -> DomRoot<CSSFontFaceRule> {
reflect_dom_object(
Box::new(CSSFontFaceRule::new_inherited(
parent_stylesheet,
fontfacerule,
)),
window,
CSSFontFaceRuleBinding::Wrap)
CSSFontFaceRuleBinding::Wrap,
)
}
}
@ -47,6 +57,9 @@ impl SpecificCSSRule for CSSFontFaceRule {
fn get_css(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.fontfacerule.read_with(&guard).to_css_string(&guard).into()
self.fontfacerule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
}

View file

@ -25,8 +25,10 @@ pub struct CSSGroupingRule {
}
impl CSSGroupingRule {
pub fn new_inherited(parent_stylesheet: &CSSStyleSheet,
rules: Arc<Locked<StyleCssRules>>) -> CSSGroupingRule {
pub fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
rules: Arc<Locked<StyleCssRules>>,
) -> CSSGroupingRule {
CSSGroupingRule {
cssrule: CSSRule::new_inherited(parent_stylesheet),
rules: rules,
@ -36,9 +38,13 @@ impl CSSGroupingRule {
fn rulelist(&self) -> DomRoot<CSSRuleList> {
let parent_stylesheet = self.upcast::<CSSRule>().parent_stylesheet();
self.rulelist.or_init(|| CSSRuleList::new(self.global().as_window(),
self.rulelist.or_init(|| {
CSSRuleList::new(
self.global().as_window(),
parent_stylesheet,
RulesSource::Rules(self.rules.clone())))
RulesSource::Rules(self.rules.clone()),
)
})
}
pub fn parent_stylesheet(&self) -> &CSSStyleSheet {

View file

@ -22,9 +22,10 @@ pub struct CSSImportRule {
}
impl CSSImportRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet,
import_rule: Arc<Locked<ImportRule>>)
-> Self {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
import_rule: Arc<Locked<ImportRule>>,
) -> Self {
CSSImportRule {
cssrule: CSSRule::new_inherited(parent_stylesheet),
import_rule: import_rule,
@ -32,12 +33,16 @@ impl CSSImportRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window,
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
import_rule: Arc<Locked<ImportRule>>) -> DomRoot<Self> {
reflect_dom_object(Box::new(Self::new_inherited(parent_stylesheet, import_rule)),
import_rule: Arc<Locked<ImportRule>>,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(Self::new_inherited(parent_stylesheet, import_rule)),
window,
CSSImportRuleBinding::Wrap)
CSSImportRuleBinding::Wrap,
)
}
}
@ -49,6 +54,9 @@ impl SpecificCSSRule for CSSImportRule {
fn get_css(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.import_rule.read_with(&guard).to_css_string(&guard).into()
self.import_rule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
}

View file

@ -25,8 +25,10 @@ pub struct CSSKeyframeRule {
}
impl CSSKeyframeRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet, keyframerule: Arc<Locked<Keyframe>>)
-> CSSKeyframeRule {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
keyframerule: Arc<Locked<Keyframe>>,
) -> CSSKeyframeRule {
CSSKeyframeRule {
cssrule: CSSRule::new_inherited(parent_stylesheet),
keyframerule: keyframerule,
@ -35,11 +37,19 @@ impl CSSKeyframeRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
keyframerule: Arc<Locked<Keyframe>>) -> DomRoot<CSSKeyframeRule> {
reflect_dom_object(Box::new(CSSKeyframeRule::new_inherited(parent_stylesheet, keyframerule)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
keyframerule: Arc<Locked<Keyframe>>,
) -> DomRoot<CSSKeyframeRule> {
reflect_dom_object(
Box::new(CSSKeyframeRule::new_inherited(
parent_stylesheet,
keyframerule,
)),
window,
CSSKeyframeRuleBinding::Wrap)
CSSKeyframeRuleBinding::Wrap,
)
}
}
@ -69,6 +79,9 @@ impl SpecificCSSRule for CSSKeyframeRule {
fn get_css(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.keyframerule.read_with(&guard).to_css_string(&guard).into()
self.keyframerule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
}

View file

@ -30,8 +30,10 @@ pub struct CSSKeyframesRule {
}
impl CSSKeyframesRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet, keyframesrule: Arc<Locked<KeyframesRule>>)
-> CSSKeyframesRule {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
keyframesrule: Arc<Locked<KeyframesRule>>,
) -> CSSKeyframesRule {
CSSKeyframesRule {
cssrule: CSSRule::new_inherited(parent_stylesheet),
keyframesrule: keyframesrule,
@ -40,19 +42,29 @@ impl CSSKeyframesRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
keyframesrule: Arc<Locked<KeyframesRule>>) -> DomRoot<CSSKeyframesRule> {
reflect_dom_object(Box::new(CSSKeyframesRule::new_inherited(parent_stylesheet, keyframesrule)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
keyframesrule: Arc<Locked<KeyframesRule>>,
) -> DomRoot<CSSKeyframesRule> {
reflect_dom_object(
Box::new(CSSKeyframesRule::new_inherited(
parent_stylesheet,
keyframesrule,
)),
window,
CSSKeyframesRuleBinding::Wrap)
CSSKeyframesRuleBinding::Wrap,
)
}
fn rulelist(&self) -> DomRoot<CSSRuleList> {
self.rulelist.or_init(|| {
let parent_stylesheet = &self.upcast::<CSSRule>().parent_stylesheet();
CSSRuleList::new(self.global().as_window(),
CSSRuleList::new(
self.global().as_window(),
parent_stylesheet,
RulesSource::Keyframes(self.keyframesrule.clone()))
RulesSource::Keyframes(self.keyframesrule.clone()),
)
})
}
@ -64,10 +76,11 @@ impl CSSKeyframesRule {
let guard = self.cssrule.shared_lock().read();
// This finds the *last* element matching a selector
// because that's the rule that applies. Thus, rposition
self.keyframesrule.read_with(&guard)
.keyframes.iter().rposition(|frame| {
frame.read_with(&guard).selector == sel
})
self.keyframesrule
.read_with(&guard)
.keyframes
.iter()
.rposition(|frame| frame.read_with(&guard).selector == sel)
} else {
None
}
@ -86,12 +99,15 @@ impl CSSKeyframesRuleMethods for CSSKeyframesRule {
let rule = Keyframe::parse(
&rule,
&style_stylesheet.contents,
&style_stylesheet.shared_lock
&style_stylesheet.shared_lock,
);
if let Ok(rule) = rule {
let mut guard = self.cssrule.shared_lock().write();
self.keyframesrule.write_with(&mut guard).keyframes.push(rule);
self.keyframesrule
.write_with(&mut guard)
.keyframes
.push(rule);
self.rulelist().append_lazy_dom_rule();
}
}
@ -105,9 +121,9 @@ impl CSSKeyframesRuleMethods for CSSKeyframesRule {
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-findrule
fn FindRule(&self, selector: DOMString) -> Option<DomRoot<CSSKeyframeRule>> {
self.find_rule(&selector).and_then(|idx| {
self.rulelist().item(idx as u32)
}).and_then(DomRoot::downcast)
self.find_rule(&selector)
.and_then(|idx| self.rulelist().item(idx as u32))
.and_then(DomRoot::downcast)
}
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
@ -136,7 +152,10 @@ impl SpecificCSSRule for CSSKeyframesRule {
fn get_css(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.keyframesrule.read_with(&guard).to_css_string(&guard).into()
self.keyframesrule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
fn deparent_children(&self) {

View file

@ -31,8 +31,10 @@ pub struct CSSMediaRule {
}
impl CSSMediaRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet, mediarule: Arc<Locked<MediaRule>>)
-> CSSMediaRule {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
mediarule: Arc<Locked<MediaRule>>,
) -> CSSMediaRule {
let guard = parent_stylesheet.shared_lock().read();
let list = mediarule.read_with(&guard).rules.clone();
CSSMediaRule {
@ -43,19 +45,26 @@ impl CSSMediaRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
mediarule: Arc<Locked<MediaRule>>) -> DomRoot<CSSMediaRule> {
reflect_dom_object(Box::new(CSSMediaRule::new_inherited(parent_stylesheet, mediarule)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
mediarule: Arc<Locked<MediaRule>>,
) -> DomRoot<CSSMediaRule> {
reflect_dom_object(
Box::new(CSSMediaRule::new_inherited(parent_stylesheet, mediarule)),
window,
CSSMediaRuleBinding::Wrap)
CSSMediaRuleBinding::Wrap,
)
}
fn medialist(&self) -> DomRoot<MediaList> {
self.medialist.or_init(|| {
let guard = self.cssconditionrule.shared_lock().read();
MediaList::new(self.global().as_window(),
MediaList::new(
self.global().as_window(),
self.cssconditionrule.parent_stylesheet(),
self.mediarule.read_with(&guard).media_queries.clone())
self.mediarule.read_with(&guard).media_queries.clone(),
)
})
}
@ -106,7 +115,10 @@ impl SpecificCSSRule for CSSMediaRule {
fn get_css(&self) -> DOMString {
let guard = self.cssconditionrule.shared_lock().read();
self.mediarule.read_with(&guard).to_css_string(&guard).into()
self.mediarule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
}

View file

@ -23,8 +23,10 @@ pub struct CSSNamespaceRule {
}
impl CSSNamespaceRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet, namespacerule: Arc<Locked<NamespaceRule>>)
-> CSSNamespaceRule {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
namespacerule: Arc<Locked<NamespaceRule>>,
) -> CSSNamespaceRule {
CSSNamespaceRule {
cssrule: CSSRule::new_inherited(parent_stylesheet),
namespacerule: namespacerule,
@ -32,11 +34,19 @@ impl CSSNamespaceRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
namespacerule: Arc<Locked<NamespaceRule>>) -> DomRoot<CSSNamespaceRule> {
reflect_dom_object(Box::new(CSSNamespaceRule::new_inherited(parent_stylesheet, namespacerule)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
namespacerule: Arc<Locked<NamespaceRule>>,
) -> DomRoot<CSSNamespaceRule> {
reflect_dom_object(
Box::new(CSSNamespaceRule::new_inherited(
parent_stylesheet,
namespacerule,
)),
window,
CSSNamespaceRuleBinding::Wrap)
CSSNamespaceRuleBinding::Wrap,
)
}
}
@ -44,8 +54,11 @@ impl CSSNamespaceRuleMethods for CSSNamespaceRule {
// https://drafts.csswg.org/cssom/#dom-cssnamespacerule-prefix
fn Prefix(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.namespacerule.read_with(&guard).prefix
.as_ref().map(|s| s.to_string().into())
self.namespacerule
.read_with(&guard)
.prefix
.as_ref()
.map(|s| s.to_string().into())
.unwrap_or(DOMString::new())
}
@ -64,6 +77,9 @@ impl SpecificCSSRule for CSSNamespaceRule {
fn get_css(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.namespacerule.read_with(&guard).to_css_string(&guard).into()
self.namespacerule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
}

View file

@ -23,7 +23,6 @@ use std::cell::Cell;
use style::shared_lock::SharedRwLock;
use style::stylesheets::CssRule as StyleCssRule;
#[dom_struct]
pub struct CSSRule {
reflector_: Reflector,
@ -71,20 +70,39 @@ impl CSSRule {
// Given a StyleCssRule, create a new instance of a derived class of
// CSSRule based on which rule it is
pub fn new_specific(window: &Window, parent_stylesheet: &CSSStyleSheet,
rule: StyleCssRule) -> DomRoot<CSSRule> {
pub fn new_specific(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
rule: StyleCssRule,
) -> DomRoot<CSSRule> {
// be sure to update the match in as_specific when this is updated
match rule {
StyleCssRule::Import(s) => DomRoot::upcast(CSSImportRule::new(window, parent_stylesheet, s)),
StyleCssRule::Style(s) => DomRoot::upcast(CSSStyleRule::new(window, parent_stylesheet, s)),
StyleCssRule::FontFace(s) => DomRoot::upcast(CSSFontFaceRule::new(window, parent_stylesheet, s)),
StyleCssRule::Import(s) => {
DomRoot::upcast(CSSImportRule::new(window, parent_stylesheet, s))
},
StyleCssRule::Style(s) => {
DomRoot::upcast(CSSStyleRule::new(window, parent_stylesheet, s))
},
StyleCssRule::FontFace(s) => {
DomRoot::upcast(CSSFontFaceRule::new(window, parent_stylesheet, s))
},
StyleCssRule::FontFeatureValues(_) => unimplemented!(),
StyleCssRule::CounterStyle(_) => unimplemented!(),
StyleCssRule::Keyframes(s) => DomRoot::upcast(CSSKeyframesRule::new(window, parent_stylesheet, s)),
StyleCssRule::Media(s) => DomRoot::upcast(CSSMediaRule::new(window, parent_stylesheet, s)),
StyleCssRule::Namespace(s) => DomRoot::upcast(CSSNamespaceRule::new(window, parent_stylesheet, s)),
StyleCssRule::Viewport(s) => DomRoot::upcast(CSSViewportRule::new(window, parent_stylesheet, s)),
StyleCssRule::Supports(s) => DomRoot::upcast(CSSSupportsRule::new(window, parent_stylesheet, s)),
StyleCssRule::Keyframes(s) => {
DomRoot::upcast(CSSKeyframesRule::new(window, parent_stylesheet, s))
},
StyleCssRule::Media(s) => {
DomRoot::upcast(CSSMediaRule::new(window, parent_stylesheet, s))
},
StyleCssRule::Namespace(s) => {
DomRoot::upcast(CSSNamespaceRule::new(window, parent_stylesheet, s))
},
StyleCssRule::Viewport(s) => {
DomRoot::upcast(CSSViewportRule::new(window, parent_stylesheet, s))
},
StyleCssRule::Supports(s) => {
DomRoot::upcast(CSSSupportsRule::new(window, parent_stylesheet, s))
},
StyleCssRule::Page(_) => unreachable!(),
StyleCssRule::Document(_) => unimplemented!(), // TODO
}

View file

@ -39,7 +39,7 @@ pub struct CSSRuleList {
parent_stylesheet: Dom<CSSStyleSheet>,
#[ignore_malloc_size_of = "Arc"]
rules: RulesSource,
dom_rules: DomRefCell<Vec<MutNullableDom<CSSRule>>>
dom_rules: DomRefCell<Vec<MutNullableDom<CSSRule>>>,
}
pub enum RulesSource {
@ -52,12 +52,18 @@ impl CSSRuleList {
pub fn new_inherited(parent_stylesheet: &CSSStyleSheet, rules: RulesSource) -> CSSRuleList {
let guard = parent_stylesheet.shared_lock().read();
let dom_rules = match rules {
RulesSource::Rules(ref rules) => {
rules.read_with(&guard).0.iter().map(|_| MutNullableDom::new(None)).collect()
}
RulesSource::Keyframes(ref rules) => {
rules.read_with(&guard).keyframes.iter().map(|_| MutNullableDom::new(None)).collect()
}
RulesSource::Rules(ref rules) => rules
.read_with(&guard)
.0
.iter()
.map(|_| MutNullableDom::new(None))
.collect(),
RulesSource::Keyframes(ref rules) => rules
.read_with(&guard)
.keyframes
.iter()
.map(|_| MutNullableDom::new(None))
.collect(),
};
CSSRuleList {
@ -69,11 +75,16 @@ impl CSSRuleList {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
rules: RulesSource) -> DomRoot<CSSRuleList> {
reflect_dom_object(Box::new(CSSRuleList::new_inherited(parent_stylesheet, rules)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
rules: RulesSource,
) -> DomRoot<CSSRuleList> {
reflect_dom_object(
Box::new(CSSRuleList::new_inherited(parent_stylesheet, rules)),
window,
CSSRuleListBinding::Wrap)
CSSRuleListBinding::Wrap,
)
}
/// Should only be called for CssRules-backed rules. Use append_lazy_rule
@ -91,18 +102,21 @@ impl CSSRuleList {
let parent_stylesheet = self.parent_stylesheet.style_stylesheet();
let new_rule = css_rules.with_raw_offset_arc(|arc| {
arc.insert_rule(&parent_stylesheet.shared_lock,
arc.insert_rule(
&parent_stylesheet.shared_lock,
rule,
&parent_stylesheet.contents,
index,
nested,
None)
None,
)
})?;
let parent_stylesheet = &*self.parent_stylesheet;
let dom_rule = CSSRule::new_specific(&window, parent_stylesheet, new_rule);
self.dom_rules.borrow_mut().insert(index, MutNullableDom::new(Some(&*dom_rule)));
self.dom_rules
.borrow_mut()
.insert(index, MutNullableDom::new(Some(&*dom_rule)));
Ok(idx)
}
@ -118,7 +132,7 @@ impl CSSRuleList {
dom_rules[index].get().map(|r| r.detach());
dom_rules.remove(index);
Ok(())
}
},
RulesSource::Keyframes(ref kf) => {
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-deleterule
let mut dom_rules = self.dom_rules.borrow_mut();
@ -126,7 +140,7 @@ impl CSSRuleList {
dom_rules.remove(index);
kf.write_with(&mut guard).keyframes.remove(index);
Ok(())
}
},
}
}
@ -143,20 +157,17 @@ impl CSSRuleList {
let parent_stylesheet = &self.parent_stylesheet;
let guard = parent_stylesheet.shared_lock().read();
match self.rules {
RulesSource::Rules(ref rules) => {
CSSRule::new_specific(self.global().as_window(),
RulesSource::Rules(ref rules) => CSSRule::new_specific(
self.global().as_window(),
parent_stylesheet,
rules.read_with(&guard).0[idx as usize].clone())
}
RulesSource::Keyframes(ref rules) => {
DomRoot::upcast(CSSKeyframeRule::new(self.global().as_window(),
rules.read_with(&guard).0[idx as usize].clone(),
),
RulesSource::Keyframes(ref rules) => DomRoot::upcast(CSSKeyframeRule::new(
self.global().as_window(),
parent_stylesheet,
rules.read_with(&guard)
.keyframes[idx as usize]
.clone()))
rules.read_with(&guard).keyframes[idx as usize].clone(),
)),
}
}
})
})
}
@ -190,4 +201,3 @@ impl CSSRuleListMethods for CSSRuleList {
self.Item(index)
}
}

View file

@ -36,16 +36,18 @@ pub struct CSSStyleDeclaration {
#[must_root]
pub enum CSSStyleOwner {
Element(Dom<Element>),
CSSRule(Dom<CSSRule>,
#[ignore_malloc_size_of = "Arc"]
Arc<Locked<PropertyDeclarationBlock>>),
CSSRule(
Dom<CSSRule>,
#[ignore_malloc_size_of = "Arc"] Arc<Locked<PropertyDeclarationBlock>>,
),
}
impl CSSStyleOwner {
// Mutate the declaration block associated to this style owner, and
// optionally indicate if it has changed (assumed to be true).
fn mutate_associated_block<F, R>(&self, f: F) -> R
where F: FnOnce(&mut PropertyDeclarationBlock, &mut bool) -> R,
where
F: FnOnce(&mut PropertyDeclarationBlock, &mut bool) -> R,
{
// TODO(emilio): This has some duplication just to avoid dummy clones.
//
@ -87,9 +89,10 @@ impl CSSStyleOwner {
let guard = shared_lock.read();
let mut serialization = String::new();
pdb.read_with(&guard).to_css(&mut serialization).unwrap();
el.set_attribute(&local_name!("style"),
AttrValue::Declaration(serialization,
pdb));
el.set_attribute(
&local_name!("style"),
AttrValue::Declaration(serialization, pdb),
);
}
} else {
// Remember to put it back.
@ -97,7 +100,7 @@ impl CSSStyleOwner {
}
result
}
},
CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
let result = {
let mut guard = rule.shared_lock().write();
@ -106,34 +109,36 @@ impl CSSStyleOwner {
if changed {
// If this is changed, see also
// CSSStyleRule::SetSelectorText, which does the same thing.
rule.global().as_window().Document().invalidate_stylesheets();
rule.global()
.as_window()
.Document()
.invalidate_stylesheets();
}
result
}
},
}
}
fn with_block<F, R>(&self, f: F) -> R
where F: FnOnce(&PropertyDeclarationBlock) -> R,
where
F: FnOnce(&PropertyDeclarationBlock) -> R,
{
match *self {
CSSStyleOwner::Element(ref el) => {
match *el.style_attribute().borrow() {
CSSStyleOwner::Element(ref el) => match *el.style_attribute().borrow() {
Some(ref pdb) => {
let document = document_from_node(&**el);
let guard = document.style_shared_lock().read();
f(pdb.read_with(&guard))
}
},
None => {
let pdb = PropertyDeclarationBlock::new();
f(&pdb)
}
}
}
},
},
CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
let guard = rule.shared_lock().read();
f(pdb.read_with(&guard))
}
},
}
}
@ -147,9 +152,12 @@ impl CSSStyleOwner {
fn base_url(&self) -> ServoUrl {
match *self {
CSSStyleOwner::Element(ref el) => window_from_node(&**el).Document().base_url(),
CSSStyleOwner::CSSRule(ref rule, _) => {
(*rule.parent_stylesheet().style_stylesheet().contents.url_data.read()).clone()
}
CSSStyleOwner::CSSRule(ref rule, _) => (*rule
.parent_stylesheet()
.style_stylesheet()
.contents
.url_data
.read()).clone(),
}
}
}
@ -181,10 +189,7 @@ macro_rules! css_properties(
);
);
fn remove_property(
decls: &mut PropertyDeclarationBlock,
id: &PropertyId,
) -> bool {
fn remove_property(decls: &mut PropertyDeclarationBlock, id: &PropertyId) -> bool {
let first_declaration = decls.first_declaration_to_remove(id);
let first_declaration = match first_declaration {
Some(i) => i,
@ -196,10 +201,11 @@ fn remove_property(
impl CSSStyleDeclaration {
#[allow(unrooted_must_root)]
pub fn new_inherited(owner: CSSStyleOwner,
pub fn new_inherited(
owner: CSSStyleOwner,
pseudo: Option<PseudoElement>,
modification_access: CSSModificationAccess)
-> CSSStyleDeclaration {
modification_access: CSSModificationAccess,
) -> CSSStyleDeclaration {
CSSStyleDeclaration {
reflector_: Reflector::new(),
owner: owner,
@ -209,22 +215,28 @@ impl CSSStyleDeclaration {
}
#[allow(unrooted_must_root)]
pub fn new(global: &Window,
pub fn new(
global: &Window,
owner: CSSStyleOwner,
pseudo: Option<PseudoElement>,
modification_access: CSSModificationAccess)
-> DomRoot<CSSStyleDeclaration> {
modification_access: CSSModificationAccess,
) -> DomRoot<CSSStyleDeclaration> {
reflect_dom_object(
Box::new(CSSStyleDeclaration::new_inherited(owner, pseudo, modification_access)),
Box::new(CSSStyleDeclaration::new_inherited(
owner,
pseudo,
modification_access,
)),
global,
CSSStyleDeclarationBinding::Wrap
CSSStyleDeclarationBinding::Wrap,
)
}
fn get_computed_style(&self, property: PropertyId) -> DOMString {
match self.owner {
CSSStyleOwner::CSSRule(..) =>
panic!("get_computed_style called on CSSStyleDeclaration with a CSSRule owner"),
CSSStyleOwner::CSSRule(..) => {
panic!("get_computed_style called on CSSStyleDeclaration with a CSSRule owner")
},
CSSStyleOwner::Element(ref el) => {
let node = el.upcast::<Node>();
if !node.is_in_doc() {
@ -234,7 +246,7 @@ impl CSSStyleDeclaration {
}
let addr = node.to_trusted_node_address();
window_from_node(node).resolved_style_query(addr, self.pseudo.clone(), property)
}
},
}
}
@ -277,7 +289,7 @@ impl CSSStyleDeclaration {
_ => {
*changed = false;
return Ok(());
}
},
};
// Step 5
@ -300,12 +312,11 @@ impl CSSStyleDeclaration {
Err(_) => {
*changed = false;
return Ok(());
}
},
}
let mut updates = Default::default();
*changed =
pdb.prepare_for_update(&declarations, importance, &mut updates);
*changed = pdb.prepare_for_update(&declarations, importance, &mut updates);
if !*changed {
return Ok(());
@ -323,9 +334,7 @@ impl CSSStyleDeclaration {
impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length
fn Length(&self) -> u32 {
self.owner.with_block(|pdb| {
pdb.declarations().len() as u32
})
self.owner.with_block(|pdb| pdb.declarations().len() as u32)
}
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item
@ -360,11 +369,12 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
}
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty
fn SetProperty(&self,
fn SetProperty(
&self,
property: DOMString,
value: DOMString,
priority: DOMString)
-> ErrorResult {
priority: DOMString,
) -> ErrorResult {
// Step 3
let id = match PropertyId::parse_enabled_for_all_content(&property) {
Ok(id) => id,
@ -444,10 +454,12 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
let quirks_mode = window.Document().quirks_mode();
self.owner.mutate_associated_block(|pdb, _changed| {
// Step 3
*pdb = parse_style_attribute(&value,
*pdb = parse_style_attribute(
&value,
&self.owner.base_url(),
window.css_error_reporter(),
quirks_mode);
quirks_mode,
);
});
Ok(())

View file

@ -31,8 +31,10 @@ pub struct CSSStyleRule {
}
impl CSSStyleRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet, stylerule: Arc<Locked<StyleRule>>)
-> CSSStyleRule {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
stylerule: Arc<Locked<StyleRule>>,
) -> CSSStyleRule {
CSSStyleRule {
cssrule: CSSRule::new_inherited(parent_stylesheet),
stylerule: stylerule,
@ -41,11 +43,16 @@ impl CSSStyleRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
stylerule: Arc<Locked<StyleRule>>) -> DomRoot<CSSStyleRule> {
reflect_dom_object(Box::new(CSSStyleRule::new_inherited(parent_stylesheet, stylerule)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
stylerule: Arc<Locked<StyleRule>>,
) -> DomRoot<CSSStyleRule> {
reflect_dom_object(
Box::new(CSSStyleRule::new_inherited(parent_stylesheet, stylerule)),
window,
CSSStyleRuleBinding::Wrap)
CSSStyleRuleBinding::Wrap,
)
}
}
@ -57,7 +64,10 @@ impl SpecificCSSRule for CSSStyleRule {
fn get_css(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.stylerule.read_with(&guard).to_css_string(&guard).into()
self.stylerule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
}
@ -70,10 +80,10 @@ impl CSSStyleRuleMethods for CSSStyleRule {
self.global().as_window(),
CSSStyleOwner::CSSRule(
Dom::from_ref(self.upcast()),
self.stylerule.read_with(&guard).block.clone()
self.stylerule.read_with(&guard).block.clone(),
),
None,
CSSModificationAccess::ReadWrite
CSSModificationAccess::ReadWrite,
)
})
}
@ -89,7 +99,13 @@ impl CSSStyleRuleMethods for CSSStyleRule {
fn SetSelectorText(&self, value: DOMString) {
// It's not clear from the spec if we should use the stylesheet's namespaces.
// https://github.com/w3c/csswg-drafts/issues/1511
let namespaces = self.cssrule.parent_stylesheet().style_stylesheet().contents.namespaces.read();
let namespaces = self
.cssrule
.parent_stylesheet()
.style_stylesheet()
.contents
.namespaces
.read();
let parser = SelectorParser {
stylesheet_origin: Origin::Author,
namespaces: &namespaces,
@ -104,7 +120,10 @@ impl CSSStyleRuleMethods for CSSStyleRule {
mem::swap(&mut stylerule.selectors, &mut s);
// It seems like we will want to avoid having to invalidate all
// stylesheets eventually!
self.global().as_window().Document().invalidate_stylesheets();
self.global()
.as_window()
.Document()
.invalidate_stylesheets();
}
}
}

View file

@ -30,11 +30,13 @@ pub struct CSSStyleSheet {
}
impl CSSStyleSheet {
fn new_inherited(owner: &Element,
fn new_inherited(
owner: &Element,
type_: DOMString,
href: Option<DOMString>,
title: Option<DOMString>,
stylesheet: Arc<StyleStyleSheet>) -> CSSStyleSheet {
stylesheet: Arc<StyleStyleSheet>,
) -> CSSStyleSheet {
CSSStyleSheet {
stylesheet: StyleSheet::new_inherited(type_, href, title),
owner: Dom::from_ref(owner),
@ -45,25 +47,27 @@ impl CSSStyleSheet {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window,
pub fn new(
window: &Window,
owner: &Element,
type_: DOMString,
href: Option<DOMString>,
title: Option<DOMString>,
stylesheet: Arc<StyleStyleSheet>) -> DomRoot<CSSStyleSheet> {
reflect_dom_object(Box::new(CSSStyleSheet::new_inherited(owner, type_, href, title, stylesheet)),
stylesheet: Arc<StyleStyleSheet>,
) -> DomRoot<CSSStyleSheet> {
reflect_dom_object(
Box::new(CSSStyleSheet::new_inherited(
owner, type_, href, title, stylesheet,
)),
window,
CSSStyleSheetBinding::Wrap)
CSSStyleSheetBinding::Wrap,
)
}
fn rulelist(&self) -> DomRoot<CSSRuleList> {
self.rulelist.or_init(|| {
let rules = self.style_stylesheet.contents.rules.clone();
CSSRuleList::new(
self.global().as_window(),
self,
RulesSource::Rules(rules)
)
CSSRuleList::new(self.global().as_window(), self, RulesSource::Rules(rules))
})
}
@ -73,7 +77,10 @@ impl CSSStyleSheet {
pub fn set_disabled(&self, disabled: bool) {
if self.style_stylesheet.set_disabled(disabled) {
self.global().as_window().Document().invalidate_stylesheets();
self.global()
.as_window()
.Document()
.invalidate_stylesheets();
}
}
@ -104,7 +111,8 @@ impl CSSStyleSheetMethods for CSSStyleSheet {
if !self.origin_clean.get() {
return Err(Error::Security);
}
self.rulelist().insert_rule(&rule, index, /* nested */ false)
self.rulelist()
.insert_rule(&rule, index, /* nested */ false)
}
// https://drafts.csswg.org/cssom/#dom-cssstylesheet-deleterule
@ -115,4 +123,3 @@ impl CSSStyleSheetMethods for CSSStyleSheet {
self.rulelist().remove_rule(index)
}
}

View file

@ -48,7 +48,9 @@ impl CSSStyleValue {
pub fn get_url(&self, base_url: ServoUrl) -> Option<ServoUrl> {
let mut input = ParserInput::new(&*self.value);
let mut parser = Parser::new(&mut input);
parser.expect_url().ok()
parser
.expect_url()
.ok()
.and_then(|string| base_url.join(&*string).ok())
}
}

View file

@ -28,8 +28,10 @@ pub struct CSSSupportsRule {
}
impl CSSSupportsRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet, supportsrule: Arc<Locked<SupportsRule>>)
-> CSSSupportsRule {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
supportsrule: Arc<Locked<SupportsRule>>,
) -> CSSSupportsRule {
let guard = parent_stylesheet.shared_lock().read();
let list = supportsrule.read_with(&guard).rules.clone();
CSSSupportsRule {
@ -39,11 +41,19 @@ impl CSSSupportsRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
supportsrule: Arc<Locked<SupportsRule>>) -> DomRoot<CSSSupportsRule> {
reflect_dom_object(Box::new(CSSSupportsRule::new_inherited(parent_stylesheet, supportsrule)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
supportsrule: Arc<Locked<SupportsRule>>,
) -> DomRoot<CSSSupportsRule> {
reflect_dom_object(
Box::new(CSSSupportsRule::new_inherited(
parent_stylesheet,
supportsrule,
)),
window,
CSSSupportsRuleBinding::Wrap)
CSSSupportsRuleBinding::Wrap,
)
}
/// <https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface>
@ -88,6 +98,9 @@ impl SpecificCSSRule for CSSSupportsRule {
fn get_css(&self) -> DOMString {
let guard = self.cssconditionrule.shared_lock().read();
self.supportsrule.read_with(&guard).to_css_string(&guard).into()
self.supportsrule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
}

View file

@ -22,7 +22,10 @@ pub struct CSSViewportRule {
}
impl CSSViewportRule {
fn new_inherited(parent_stylesheet: &CSSStyleSheet, viewportrule: Arc<Locked<ViewportRule>>) -> CSSViewportRule {
fn new_inherited(
parent_stylesheet: &CSSStyleSheet,
viewportrule: Arc<Locked<ViewportRule>>,
) -> CSSViewportRule {
CSSViewportRule {
cssrule: CSSRule::new_inherited(parent_stylesheet),
viewportrule: viewportrule,
@ -30,11 +33,19 @@ impl CSSViewportRule {
}
#[allow(unrooted_must_root)]
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
viewportrule: Arc<Locked<ViewportRule>>) -> DomRoot<CSSViewportRule> {
reflect_dom_object(Box::new(CSSViewportRule::new_inherited(parent_stylesheet, viewportrule)),
pub fn new(
window: &Window,
parent_stylesheet: &CSSStyleSheet,
viewportrule: Arc<Locked<ViewportRule>>,
) -> DomRoot<CSSViewportRule> {
reflect_dom_object(
Box::new(CSSViewportRule::new_inherited(
parent_stylesheet,
viewportrule,
)),
window,
CSSViewportRuleBinding::Wrap)
CSSViewportRuleBinding::Wrap,
)
}
}
@ -46,6 +57,9 @@ impl SpecificCSSRule for CSSViewportRule {
fn get_css(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.viewportrule.read_with(&guard).to_css_string(&guard).into()
self.viewportrule
.read_with(&guard)
.to_css_string(&guard)
.into()
}
}

View file

@ -71,9 +71,11 @@ impl CustomElementRegistry {
}
pub fn new(window: &Window) -> DomRoot<CustomElementRegistry> {
reflect_dom_object(Box::new(CustomElementRegistry::new_inherited(window)),
reflect_dom_object(
Box::new(CustomElementRegistry::new_inherited(window)),
window,
CustomElementRegistryBinding::Wrap)
CustomElementRegistryBinding::Wrap,
)
}
/// Cleans up any active promises
@ -83,40 +85,57 @@ impl CustomElementRegistry {
}
/// <https://html.spec.whatwg.org/multipage/#look-up-a-custom-element-definition>
pub fn lookup_definition(&self,
pub fn lookup_definition(
&self,
local_name: &LocalName,
is: Option<&LocalName>)
-> Option<Rc<CustomElementDefinition>> {
self.definitions.borrow().values().find(|definition| {
is: Option<&LocalName>,
) -> Option<Rc<CustomElementDefinition>> {
self.definitions
.borrow()
.values()
.find(|definition| {
// Step 4-5
definition.local_name == *local_name &&
(definition.name == *local_name || Some(&definition.name) == is)
}).cloned()
}
pub fn lookup_definition_by_constructor(&self, constructor: HandleObject) -> Option<Rc<CustomElementDefinition>> {
self.definitions.borrow().values().find(|definition| {
definition.constructor.callback() == constructor.get()
}).cloned()
pub fn lookup_definition_by_constructor(
&self,
constructor: HandleObject,
) -> Option<Rc<CustomElementDefinition>> {
self.definitions
.borrow()
.values()
.find(|definition| definition.constructor.callback() == constructor.get())
.cloned()
}
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define>
/// Steps 10.1, 10.2
#[allow(unsafe_code)]
fn check_prototype(&self, constructor: HandleObject, prototype: MutableHandleValue) -> ErrorResult {
fn check_prototype(
&self,
constructor: HandleObject,
prototype: MutableHandleValue,
) -> ErrorResult {
let global_scope = self.window.upcast::<GlobalScope>();
unsafe {
// Step 10.1
if !JS_GetProperty(global_scope.get_cx(),
if !JS_GetProperty(
global_scope.get_cx(),
constructor,
b"prototype\0".as_ptr() as *const _,
prototype) {
prototype,
) {
return Err(Error::JSFailed);
}
// Step 10.2
if !prototype.is_object() {
return Err(Error::Type("constructor.prototype is not an object".to_owned()));
return Err(Error::Type(
"constructor.prototype is not an object".to_owned(),
));
}
}
Ok(())
@ -143,10 +162,14 @@ impl CustomElementRegistry {
fn get_observed_attributes(&self, constructor: HandleObject) -> Fallible<Vec<DOMString>> {
let cx = self.window.get_cx();
rooted!(in(cx) let mut observed_attributes = UndefinedValue());
if unsafe { !JS_GetProperty(cx,
if unsafe {
!JS_GetProperty(
cx,
constructor,
b"observedAttributes\0".as_ptr() as *const _,
observed_attributes.handle_mut()) } {
observed_attributes.handle_mut(),
)
} {
return Err(Error::JSFailed);
}
@ -155,7 +178,11 @@ impl CustomElementRegistry {
}
let conversion = unsafe {
FromJSValConvertible::from_jsval(cx, observed_attributes.handle(), StringificationBehavior::Default)
FromJSValConvertible::from_jsval(
cx,
observed_attributes.handle(),
StringificationBehavior::Default,
)
};
match conversion {
Ok(ConversionResult::Success(attributes)) => Ok(attributes),
@ -176,7 +203,12 @@ unsafe fn get_callback(
rooted!(in(cx) let mut callback = UndefinedValue());
// Step 10.4.1
if !JS_GetProperty(cx, prototype, name.as_ptr() as *const _, callback.handle_mut()) {
if !JS_GetProperty(
cx,
prototype,
name.as_ptr() as *const _,
callback.handle_mut(),
) {
return Err(Error::JSFailed);
}
@ -195,9 +227,10 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
#[allow(unsafe_code, unrooted_must_root)]
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define>
fn Define(
&self, name: DOMString,
&self,
name: DOMString,
constructor_: Rc<CustomElementConstructor>,
options: &ElementDefinitionOptions
options: &ElementDefinitionOptions,
) -> ErrorResult {
let cx = self.window.get_cx();
rooted!(in(cx) let constructor = constructor_.callback());
@ -213,12 +246,14 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
}
if unsafe { !IsConstructor(unwrapped_constructor.get()) } {
return Err(Error::Type("Second argument of CustomElementRegistry.define is not a constructor".to_owned()));
return Err(Error::Type(
"Second argument of CustomElementRegistry.define is not a constructor".to_owned(),
));
}
// Step 2
if !is_valid_custom_element_name(&name) {
return Err(Error::Syntax)
return Err(Error::Syntax);
}
// Step 3
@ -227,7 +262,12 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
}
// Step 4
if self.definitions.borrow().iter().any(|(_, ref def)| def.constructor == constructor_) {
if self
.definitions
.borrow()
.iter()
.any(|(_, ref def)| def.constructor == constructor_)
{
return Err(Error::NotSupported);
}
@ -238,12 +278,12 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
let local_name = if let Some(ref extended_name) = *extends {
// Step 7.1
if is_valid_custom_element_name(extended_name) {
return Err(Error::NotSupported)
return Err(Error::NotSupported);
}
// Step 7.2
if !is_extendable_element_interface(extended_name) {
return Err(Error::NotSupported)
return Err(Error::NotSupported);
}
LocalName::from(&**extended_name)
@ -300,20 +340,28 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
self.element_definition_is_running.set(false);
// Step 11
let definition = Rc::new(CustomElementDefinition::new(name.clone(),
let definition = Rc::new(CustomElementDefinition::new(
name.clone(),
local_name.clone(),
constructor_,
observed_attributes,
callbacks));
callbacks,
));
// Step 12
self.definitions.borrow_mut().insert(name.clone(), definition.clone());
self.definitions
.borrow_mut()
.insert(name.clone(), definition.clone());
// Step 13
let document = self.window.Document();
// Steps 14-15
for candidate in document.upcast::<Node>().traverse_preorder().filter_map(DomRoot::downcast::<Element>) {
for candidate in document
.upcast::<Node>()
.traverse_preorder()
.filter_map(DomRoot::downcast::<Element>)
{
let is = candidate.get_is();
if *candidate.local_name() == local_name &&
*candidate.namespace() == ns!(html) &&
@ -336,7 +384,9 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
match self.definitions.borrow().get(&LocalName::from(&*name)) {
Some(definition) => {
rooted!(in(cx) let mut constructor = UndefinedValue());
definition.constructor.to_jsval(cx, constructor.handle_mut());
definition
.constructor
.to_jsval(cx, constructor.handle_mut());
constructor.get()
},
None => UndefinedValue(),
@ -353,14 +403,14 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
if !is_valid_custom_element_name(&name) {
let promise = Promise::new(global_scope);
promise.reject_native(&DOMException::new(global_scope, DOMErrorName::SyntaxError));
return promise
return promise;
}
// Step 2
if self.definitions.borrow().contains_key(&name) {
let promise = Promise::new(global_scope);
promise.resolve_native(&UndefinedValue());
return promise
return promise;
}
// Step 3
@ -417,12 +467,13 @@ pub struct CustomElementDefinition {
}
impl CustomElementDefinition {
fn new(name: LocalName,
fn new(
name: LocalName,
local_name: LocalName,
constructor: Rc<CustomElementConstructor>,
observed_attributes: Vec<DOMString>,
callbacks: LifecycleCallbacks)
-> CustomElementDefinition {
callbacks: LifecycleCallbacks,
) -> CustomElementDefinition {
CustomElementDefinition {
name: name,
local_name: local_name,
@ -440,7 +491,11 @@ impl CustomElementDefinition {
/// https://dom.spec.whatwg.org/#concept-create-element Step 6.1
#[allow(unsafe_code)]
pub fn create_element(&self, document: &Document, prefix: Option<Prefix>) -> Fallible<DomRoot<Element>> {
pub fn create_element(
&self,
document: &Document,
prefix: Option<Prefix>,
) -> Fallible<DomRoot<Element>> {
let window = document.window();
let cx = window.get_cx();
// Step 2
@ -456,16 +511,22 @@ impl CustomElementDefinition {
}
rooted!(in(cx) let element_val = ObjectValue(element.get()));
let element: DomRoot<Element> = match unsafe { DomRoot::from_jsval(cx, element_val.handle(), ()) } {
let element: DomRoot<Element> =
match unsafe { DomRoot::from_jsval(cx, element_val.handle(), ()) } {
Ok(ConversionResult::Success(element)) => element,
Ok(ConversionResult::Failure(..)) =>
return Err(Error::Type("Constructor did not return a DOM node".to_owned())),
Ok(ConversionResult::Failure(..)) => {
return Err(Error::Type(
"Constructor did not return a DOM node".to_owned(),
))
},
_ => return Err(Error::JSFailed),
};
// Step 3
if !element.is::<HTMLElement>() {
return Err(Error::Type("Constructor did not return a DOM node".to_owned()));
return Err(Error::Type(
"Constructor did not return a DOM node".to_owned(),
));
}
// Steps 4-9
@ -503,17 +564,27 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
let local_name = attr.local_name().clone();
let value = DOMString::from(&**attr.value());
let namespace = attr.namespace().clone();
ScriptThread::enqueue_callback_reaction(element,
CallbackReaction::AttributeChanged(local_name, None, Some(value), namespace), Some(definition.clone()));
ScriptThread::enqueue_callback_reaction(
element,
CallbackReaction::AttributeChanged(local_name, None, Some(value), namespace),
Some(definition.clone()),
);
}
// Step 4
if element.is_connected() {
ScriptThread::enqueue_callback_reaction(element, CallbackReaction::Connected, Some(definition.clone()));
ScriptThread::enqueue_callback_reaction(
element,
CallbackReaction::Connected,
Some(definition.clone()),
);
}
// Step 5
definition.construction_stack.borrow_mut().push(ConstructionStackEntry::Element(DomRoot::from_ref(element)));
definition
.construction_stack
.borrow_mut()
.push(ConstructionStackEntry::Element(DomRoot::from_ref(element)));
// Step 7
let result = run_upgrade_constructor(&definition.constructor, element);
@ -548,25 +619,44 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
/// <https://html.spec.whatwg.org/multipage/#concept-upgrade-an-element>
/// Steps 7.1-7.2
#[allow(unsafe_code)]
fn run_upgrade_constructor(constructor: &Rc<CustomElementConstructor>, element: &Element) -> ErrorResult {
fn run_upgrade_constructor(
constructor: &Rc<CustomElementConstructor>,
element: &Element,
) -> ErrorResult {
let window = window_from_node(element);
let cx = window.get_cx();
rooted!(in(cx) let constructor_val = ObjectValue(constructor.callback()));
rooted!(in(cx) let mut element_val = UndefinedValue());
unsafe { element.to_jsval(cx, element_val.handle_mut()); }
unsafe {
element.to_jsval(cx, element_val.handle_mut());
}
rooted!(in(cx) let mut construct_result = ptr::null_mut::<JSObject>());
{
// Go into the constructor's compartment
let _ac = JSAutoCompartment::new(cx, constructor.callback());
let args = HandleValueArray::new();
// Step 7.1
if unsafe { !Construct1(cx, constructor_val.handle(), &args, construct_result.handle_mut()) } {
if unsafe {
!Construct1(
cx,
constructor_val.handle(),
&args,
construct_result.handle_mut(),
)
} {
return Err(Error::JSFailed);
}
// Step 7.2
let mut same = false;
rooted!(in(cx) let construct_result_val = ObjectValue(construct_result.get()));
if unsafe { !JS_SameValue(cx, construct_result_val.handle(), element_val.handle(), &mut same) } {
if unsafe {
!JS_SameValue(
cx,
construct_result_val.handle(),
element_val.handle(),
&mut same,
)
} {
return Err(Error::JSFailed);
}
if !same {
@ -583,7 +673,9 @@ pub fn try_upgrade_element(element: &Element) {
let namespace = element.namespace();
let local_name = element.local_name();
let is = element.get_is();
if let Some(definition) = document.lookup_custom_element_definition(namespace, local_name, is.as_ref()) {
if let Some(definition) =
document.lookup_custom_element_definition(namespace, local_name, is.as_ref())
{
// Step 2
ScriptThread::enqueue_upgrade_reaction(element, definition);
}
@ -592,14 +684,10 @@ pub fn try_upgrade_element(element: &Element) {
#[derive(JSTraceable, MallocSizeOf)]
#[must_root]
pub enum CustomElementReaction {
Upgrade(
#[ignore_malloc_size_of = "Rc"]
Rc<CustomElementDefinition>
),
Upgrade(#[ignore_malloc_size_of = "Rc"] Rc<CustomElementDefinition>),
Callback(
#[ignore_malloc_size_of = "Rc"]
Rc<Function>,
Box<[Heap<JSVal>]>
#[ignore_malloc_size_of = "Rc"] Rc<Function>,
Box<[Heap<JSVal>]>,
),
}
@ -609,12 +697,17 @@ impl CustomElementReaction {
pub fn invoke(&self, element: &Element) {
// Step 2.1
match *self {
CustomElementReaction::Upgrade(ref definition) => upgrade_element(definition.clone(), element),
CustomElementReaction::Upgrade(ref definition) => {
upgrade_element(definition.clone(), element)
},
CustomElementReaction::Callback(ref callback, ref arguments) => {
// We're rooted, so it's safe to hand out a handle to objects in Heap
let arguments = arguments.iter().map(|arg| unsafe { HandleValue::from_raw(arg.handle()) }).collect();
let arguments = arguments
.iter()
.map(|arg| unsafe { HandleValue::from_raw(arg.handle()) })
.collect();
let _ = callback.Call_(&*element, arguments, ExceptionHandling::Report);
}
},
}
}
}
@ -675,7 +768,8 @@ impl CustomElementReactionStack {
self.backup_queue.invoke_reactions();
// Step 4.2
self.processing_backup_element_queue.set(BackupElementQueueFlag::NotProcessing);
self.processing_backup_element_queue
.set(BackupElementQueueFlag::NotProcessing);
}
/// <https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue>
@ -693,7 +787,8 @@ impl CustomElementReactionStack {
}
// Step 1.3
self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing);
self.processing_backup_element_queue
.set(BackupElementQueueFlag::Processing);
// Step 4
ScriptThread::enqueue_microtask(Microtask::CustomElementReaction);
@ -702,10 +797,12 @@ impl CustomElementReactionStack {
/// <https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction>
#[allow(unsafe_code)]
pub fn enqueue_callback_reaction(&self,
pub fn enqueue_callback_reaction(
&self,
element: &Element,
reaction: CallbackReaction,
definition: Option<Rc<CustomElementDefinition>>) {
definition: Option<Rc<CustomElementDefinition>>,
) {
// Step 1
let definition = match definition.or_else(|| element.get_custom_element_definition()) {
Some(definition) => definition,
@ -714,8 +811,13 @@ impl CustomElementReactionStack {
// Step 2
let (callback, args) = match reaction {
CallbackReaction::Connected => (definition.callbacks.connected_callback.clone(), Vec::new()),
CallbackReaction::Disconnected => (definition.callbacks.disconnected_callback.clone(), Vec::new()),
CallbackReaction::Connected => {
(definition.callbacks.connected_callback.clone(), Vec::new())
},
CallbackReaction::Disconnected => (
definition.callbacks.disconnected_callback.clone(),
Vec::new(),
),
CallbackReaction::Adopted(ref old_doc, ref new_doc) => {
let args = vec![Heap::default(), Heap::default()];
args[0].set(ObjectValue(old_doc.reflector().get_jsobject().get()));
@ -724,7 +826,11 @@ impl CustomElementReactionStack {
},
CallbackReaction::AttributeChanged(local_name, old_val, val, namespace) => {
// Step 4
if !definition.observed_attributes.iter().any(|attr| *attr == *local_name) {
if !definition
.observed_attributes
.iter()
.any(|attr| *attr == *local_name)
{
return;
}
@ -732,31 +838,47 @@ impl CustomElementReactionStack {
let local_name = DOMString::from(&*local_name);
rooted!(in(cx) let mut name_value = UndefinedValue());
unsafe { local_name.to_jsval(cx, name_value.handle_mut()); }
unsafe {
local_name.to_jsval(cx, name_value.handle_mut());
}
rooted!(in(cx) let mut old_value = NullValue());
if let Some(old_val) = old_val {
unsafe { old_val.to_jsval(cx, old_value.handle_mut()); }
unsafe {
old_val.to_jsval(cx, old_value.handle_mut());
}
}
rooted!(in(cx) let mut value = NullValue());
if let Some(val) = val {
unsafe { val.to_jsval(cx, value.handle_mut()); }
unsafe {
val.to_jsval(cx, value.handle_mut());
}
}
rooted!(in(cx) let mut namespace_value = NullValue());
if namespace != ns!() {
let namespace = DOMString::from(&*namespace);
unsafe { namespace.to_jsval(cx, namespace_value.handle_mut()); }
unsafe {
namespace.to_jsval(cx, namespace_value.handle_mut());
}
}
let args = vec![Heap::default(), Heap::default(), Heap::default(), Heap::default()];
let args = vec![
Heap::default(),
Heap::default(),
Heap::default(),
Heap::default(),
];
args[0].set(name_value.get());
args[1].set(old_value.get());
args[2].set(value.get());
args[3].set(namespace_value.get());
(definition.callbacks.attribute_changed_callback.clone(), args)
(
definition.callbacks.attribute_changed_callback.clone(),
args,
)
},
};
@ -774,7 +896,11 @@ impl CustomElementReactionStack {
}
/// <https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-upgrade-reaction>
pub fn enqueue_upgrade_reaction(&self, element: &Element, definition: Rc<CustomElementDefinition>) {
pub fn enqueue_upgrade_reaction(
&self,
element: &Element,
definition: Rc<CustomElementDefinition>,
) {
// Step 1
element.push_upgrade_reaction(definition);
// Step 2
@ -806,7 +932,12 @@ impl ElementQueue {
}
fn next_element(&self) -> Option<DomRoot<Element>> {
self.queue.borrow_mut().pop_front().as_ref().map(Dom::deref).map(DomRoot::from_ref)
self.queue
.borrow_mut()
.pop_front()
.as_ref()
.map(Dom::deref)
.map(DomRoot::from_ref)
}
fn append_element(&self, element: &Element) {
@ -859,7 +990,10 @@ pub fn is_valid_custom_element_name(name: &str) -> bool {
/// Check if this character is a PCENChar
/// <https://html.spec.whatwg.org/multipage/#prod-pcenchar>
fn is_potential_custom_element_char(c: char) -> bool {
c == '-' || c == '.' || c == '_' || c == '\u{B7}' ||
c == '-' ||
c == '.' ||
c == '_' ||
c == '\u{B7}' ||
(c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= '\u{C0}' && c <= '\u{D6}') ||

View file

@ -36,38 +36,46 @@ impl CustomEvent {
}
pub fn new_uninitialized(global: &GlobalScope) -> DomRoot<CustomEvent> {
reflect_dom_object(Box::new(CustomEvent::new_inherited()),
reflect_dom_object(
Box::new(CustomEvent::new_inherited()),
global,
CustomEventBinding::Wrap)
CustomEventBinding::Wrap,
)
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
type_: Atom,
bubbles: bool,
cancelable: bool,
detail: HandleValue)
-> DomRoot<CustomEvent> {
detail: HandleValue,
) -> DomRoot<CustomEvent> {
let ev = CustomEvent::new_uninitialized(global);
ev.init_custom_event(type_, bubbles, cancelable, detail);
ev
}
#[allow(unsafe_code)]
pub fn Constructor(global: &GlobalScope,
pub fn Constructor(
global: &GlobalScope,
type_: DOMString,
init: RootedTraceableBox<CustomEventBinding::CustomEventInit>)
-> Fallible<DomRoot<CustomEvent>> {
Ok(CustomEvent::new(global,
init: RootedTraceableBox<CustomEventBinding::CustomEventInit>,
) -> Fallible<DomRoot<CustomEvent>> {
Ok(CustomEvent::new(
global,
Atom::from(type_),
init.parent.bubbles,
init.parent.cancelable,
init.detail.handle()))
init.detail.handle(),
))
}
fn init_custom_event(&self,
fn init_custom_event(
&self,
type_: Atom,
can_bubble: bool,
cancelable: bool,
detail: HandleValue) {
detail: HandleValue,
) {
let event = self.upcast::<Event>();
if event.dispatching() {
return;
@ -87,12 +95,14 @@ impl CustomEventMethods for CustomEvent {
#[allow(unsafe_code)]
// https://dom.spec.whatwg.org/#dom-customevent-initcustomevent
unsafe fn InitCustomEvent(&self,
unsafe fn InitCustomEvent(
&self,
_cx: *mut JSContext,
type_: DOMString,
can_bubble: bool,
cancelable: bool,
detail: HandleValue) {
detail: HandleValue,
) {
self.init_custom_event(Atom::from(type_), can_bubble, cancelable, detail)
}

View file

@ -57,9 +57,10 @@ pub 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)),
@ -83,7 +84,7 @@ pub enum DedicatedWorkerScriptMsg {
pub enum MixedMessage {
FromWorker(DedicatedWorkerScriptMsg),
FromScheduler((TrustedWorkerAddress, TimerEvent)),
FromDevtools(DevtoolScriptControlMsg)
FromDevtools(DevtoolScriptControlMsg),
}
impl QueuedTaskConversion for DedicatedWorkerScriptMsg {
@ -97,14 +98,18 @@ impl QueuedTaskConversion for DedicatedWorkerScriptMsg {
_ => return None,
};
match script_msg {
CommonScriptMsg::Task(_category, _boxed, _pipeline_id, source_name) => Some(&source_name),
CommonScriptMsg::Task(_category, _boxed, _pipeline_id, source_name) => {
Some(&source_name)
},
_ => return None,
}
}
fn into_queued_task(self) -> Option<QueuedTask> {
let (worker, common_worker_msg) = match self {
DedicatedWorkerScriptMsg::CommonWorker(worker, common_worker_msg) => (worker, common_worker_msg),
DedicatedWorkerScriptMsg::CommonWorker(worker, common_worker_msg) => {
(worker, common_worker_msg)
},
_ => return None,
};
let script_msg = match common_worker_msg {
@ -112,8 +117,9 @@ impl QueuedTaskConversion for DedicatedWorkerScriptMsg {
_ => return None,
};
let (category, boxed, pipeline_id, task_source) = match script_msg {
CommonScriptMsg::Task(category, boxed, pipeline_id, task_source) =>
(category, boxed, pipeline_id, task_source),
CommonScriptMsg::Task(category, boxed, pipeline_id, task_source) => {
(category, boxed, pipeline_id, task_source)
},
_ => return None,
};
Some((Some(worker), category, boxed, pipeline_id, task_source))
@ -121,12 +127,7 @@ impl QueuedTaskConversion for DedicatedWorkerScriptMsg {
fn from_queued_task(queued_task: QueuedTask) -> Self {
let (worker, category, boxed, pipeline_id, task_source) = queued_task;
let script_msg = CommonScriptMsg::Task(
category,
boxed,
pipeline_id,
task_source
);
let script_msg = CommonScriptMsg::Task(category, boxed, pipeline_id, task_source);
DedicatedWorkerScriptMsg::CommonWorker(worker.unwrap(), WorkerScriptMsg::Common(script_msg))
}
@ -197,7 +198,8 @@ impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope {
}
impl DedicatedWorkerGlobalScope {
fn new_inherited(init: WorkerGlobalScopeInit,
fn new_inherited(
init: WorkerGlobalScopeInit,
worker_url: ServoUrl,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
runtime: Runtime,
@ -206,15 +208,17 @@ impl DedicatedWorkerGlobalScope {
receiver: Receiver<DedicatedWorkerScriptMsg>,
timer_event_chan: IpcSender<TimerEvent>,
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>,
closing: Arc<AtomicBool>)
-> DedicatedWorkerGlobalScope {
closing: Arc<AtomicBool>,
) -> DedicatedWorkerGlobalScope {
DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited(init,
workerglobalscope: WorkerGlobalScope::new_inherited(
init,
worker_url,
runtime,
from_devtools_receiver,
timer_event_chan,
Some(closing)),
Some(closing),
),
task_queue: TaskQueue::new(receiver, own_sender.clone()),
own_sender: own_sender,
timer_event_port: timer_event_port,
@ -224,7 +228,8 @@ impl DedicatedWorkerGlobalScope {
}
#[allow(unsafe_code)]
pub fn new(init: WorkerGlobalScopeInit,
pub fn new(
init: WorkerGlobalScopeInit,
worker_url: ServoUrl,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
runtime: Runtime,
@ -233,8 +238,8 @@ impl DedicatedWorkerGlobalScope {
receiver: Receiver<DedicatedWorkerScriptMsg>,
timer_event_chan: IpcSender<TimerEvent>,
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>,
closing: Arc<AtomicBool>)
-> DomRoot<DedicatedWorkerGlobalScope> {
closing: Arc<AtomicBool>,
) -> DomRoot<DedicatedWorkerGlobalScope> {
let cx = runtime.cx();
let scope = Box::new(DedicatedWorkerGlobalScope::new_inherited(
init,
@ -246,16 +251,15 @@ impl DedicatedWorkerGlobalScope {
receiver,
timer_event_chan,
timer_event_port,
closing
closing,
));
unsafe {
DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope)
}
unsafe { DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope) }
}
#[allow(unsafe_code)]
// https://html.spec.whatwg.org/multipage/#run-a-worker
pub fn run_worker_scope(init: WorkerGlobalScopeInit,
pub fn run_worker_scope(
init: WorkerGlobalScopeInit,
worker_url: ServoUrl,
from_devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
worker: TrustedWorkerAddress,
@ -263,13 +267,20 @@ impl DedicatedWorkerGlobalScope {
own_sender: Sender<DedicatedWorkerScriptMsg>,
receiver: Receiver<DedicatedWorkerScriptMsg>,
worker_load_origin: WorkerScriptLoadOrigin,
closing: Arc<AtomicBool>) {
closing: Arc<AtomicBool>,
) {
let serialized_worker_url = worker_url.to_string();
let name = format!("WebWorker for {}", serialized_worker_url);
let top_level_browsing_context_id = TopLevelBrowsingContextId::installed();
let origin = GlobalScope::current().expect("No current global object").origin().immutable().clone();
let origin = GlobalScope::current()
.expect("No current global object")
.origin()
.immutable()
.clone();
thread::Builder::new().name(name).spawn(move || {
thread::Builder::new()
.name(name)
.spawn(move || {
thread_state::initialize(ThreadState::SCRIPT | ThreadState::IN_WORKER);
if let Some(top_level_browsing_context_id) = top_level_browsing_context_id {
@ -279,7 +290,11 @@ impl DedicatedWorkerGlobalScope {
let roots = RootCollection::new();
let _stack_roots = ThreadLocalStackRoots::new(&roots);
let WorkerScriptLoadOrigin { referrer_url, referrer_policy, pipeline_id } = worker_load_origin;
let WorkerScriptLoadOrigin {
referrer_url,
referrer_policy,
pipeline_id,
} = worker_load_origin;
let request = RequestInit {
url: worker_url.clone(),
@ -290,22 +305,23 @@ impl DedicatedWorkerGlobalScope {
referrer_url: referrer_url,
referrer_policy: referrer_policy,
origin,
.. RequestInit::default()
..RequestInit::default()
};
let (metadata, bytes) = match load_whole_resource(request,
&init.resource_threads.sender()) {
let (metadata, bytes) =
match load_whole_resource(request, &init.resource_threads.sender()) {
Err(_) => {
println!("error loading script {}", serialized_worker_url);
parent_sender.send(CommonScriptMsg::Task(
parent_sender
.send(CommonScriptMsg::Task(
WorkerEvent,
Box::new(SimpleWorkerErrorHandler::new(worker)),
pipeline_id,
TaskSourceName::DOMManipulation,
)).unwrap();
return;
}
Ok((metadata, bytes)) => (metadata, bytes)
},
Ok((metadata, bytes)) => (metadata, bytes),
};
let url = metadata.final_url;
let source = String::from_utf8_lossy(&bytes);
@ -318,15 +334,26 @@ impl DedicatedWorkerGlobalScope {
let (timer_tx, timer_rx) = channel();
let (timer_ipc_chan, timer_ipc_port) = ipc::channel().unwrap();
let worker_for_route = worker.clone();
ROUTER.add_route(timer_ipc_port.to_opaque(), Box::new(move |message| {
ROUTER.add_route(
timer_ipc_port.to_opaque(),
Box::new(move |message| {
let event = message.to().unwrap();
timer_tx.send((worker_for_route.clone(), event)).unwrap();
}));
}),
);
let global = DedicatedWorkerGlobalScope::new(
init, url, devtools_mpsc_port, runtime,
parent_sender.clone(), own_sender, receiver,
timer_ipc_chan, timer_rx, closing);
init,
url,
devtools_mpsc_port,
runtime,
parent_sender.clone(),
own_sender,
receiver,
timer_ipc_chan,
timer_rx,
closing,
);
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
// registration (#6631), so we instead use a random number and cross our fingers.
let scope = global.upcast::<WorkerGlobalScope>();
@ -346,14 +373,24 @@ impl DedicatedWorkerGlobalScope {
}
let reporter_name = format!("dedicated-worker-reporter-{}", random::<u64>());
scope.upcast::<GlobalScope>().mem_profiler_chan().run_with_memory_reporting(|| {
// Step 29, Run the responsible event loop specified by inside settings until it is destroyed.
// The worker processing model remains on this step until the event loop is destroyed,
scope
.upcast::<GlobalScope>()
.mem_profiler_chan()
.run_with_memory_reporting(
|| {
// Step 29, Run the responsible event loop specified
// by inside settings until it is destroyed.
// The worker processing model remains on this step
// until the event loop is destroyed,
// which happens after the closing flag is set to true.
while !scope.is_closing() {
run_worker_event_loop(&*global, Some(&worker));
}
}, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
},
reporter_name,
parent_sender,
CommonScriptMsg::CollectReports,
);
}).expect("Thread spawning failed");
}
@ -378,8 +415,8 @@ impl DedicatedWorkerGlobalScope {
WorkerScriptMsg::DOMMessage(data) => {
let scope = self.upcast::<WorkerGlobalScope>();
let target = self.upcast();
let _ac = JSAutoCompartment::new(scope.get_cx(),
scope.reflector().get_jsobject().get());
let _ac =
JSAutoCompartment::new(scope.get_cx(), scope.reflector().get_jsobject().get());
rooted!(in(scope.get_cx()) let mut message = UndefinedValue());
data.read(scope.upcast(), message.handle_mut());
MessageEvent::dispatch_jsval(target, scope.upcast(), message.handle(), None);
@ -392,33 +429,33 @@ impl DedicatedWorkerGlobalScope {
fn handle_mixed_message(&self, msg: MixedMessage) {
match msg {
MixedMessage::FromDevtools(msg) => {
match msg {
DevtoolScriptControlMsg::EvaluateJS(_pipe_id, string, sender) =>
devtools::handle_evaluate_js(self.upcast(), string, sender),
DevtoolScriptControlMsg::GetCachedMessages(pipe_id, message_types, sender) =>
devtools::handle_get_cached_messages(pipe_id, message_types, sender),
DevtoolScriptControlMsg::WantsLiveNotifications(_pipe_id, bool_val) =>
devtools::handle_wants_live_notifications(self.upcast(), bool_val),
_ => debug!("got an unusable devtools control message inside the worker!"),
}
MixedMessage::FromDevtools(msg) => match msg {
DevtoolScriptControlMsg::EvaluateJS(_pipe_id, string, sender) => {
devtools::handle_evaluate_js(self.upcast(), string, sender)
},
MixedMessage::FromScheduler((linked_worker, timer_event)) => {
match timer_event {
DevtoolScriptControlMsg::GetCachedMessages(pipe_id, message_types, sender) => {
devtools::handle_get_cached_messages(pipe_id, message_types, sender)
},
DevtoolScriptControlMsg::WantsLiveNotifications(_pipe_id, bool_val) => {
devtools::handle_wants_live_notifications(self.upcast(), bool_val)
},
_ => debug!("got an unusable devtools control message inside the worker!"),
},
MixedMessage::FromScheduler((linked_worker, timer_event)) => match timer_event {
TimerEvent(TimerSource::FromWorker, id) => {
let _ar = AutoWorkerReset::new(self, linked_worker);
let scope = self.upcast::<WorkerGlobalScope>();
scope.handle_fire_timer(id);
},
TimerEvent(_, _) => {
panic!("A worker received a TimerEvent from a window.")
}
}
}
MixedMessage::FromWorker(DedicatedWorkerScriptMsg::CommonWorker(linked_worker, msg)) => {
TimerEvent(_, _) => panic!("A worker received a TimerEvent from a window."),
},
MixedMessage::FromWorker(DedicatedWorkerScriptMsg::CommonWorker(
linked_worker,
msg,
)) => {
let _ar = AutoWorkerReset::new(self, linked_worker);
self.handle_script_event(msg);
}
},
MixedMessage::FromWorker(DedicatedWorkerScriptMsg::WakeUp) => {},
}
}
@ -452,7 +489,8 @@ impl DedicatedWorkerGlobalScope {
global.report_an_error(error_info, HandleValue::null());
}
}));
self.parent_sender.send(CommonScriptMsg::Task(
self.parent_sender
.send(CommonScriptMsg::Task(
WorkerEvent,
task,
Some(pipeline_id),
@ -463,8 +501,7 @@ impl DedicatedWorkerGlobalScope {
#[allow(unsafe_code)]
unsafe extern "C" fn interrupt_callback(cx: *mut JSContext) -> bool {
let worker =
DomRoot::downcast::<WorkerGlobalScope>(GlobalScope::from_context(cx))
let worker = DomRoot::downcast::<WorkerGlobalScope>(GlobalScope::from_context(cx))
.expect("global is not a worker scope");
assert!(worker.is::<DedicatedWorkerGlobalScope>());
@ -483,7 +520,8 @@ impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
Worker::handle_message(worker, data);
}));
// TODO: Change this task source to a new `unshipped-port-message-queue` task source
self.parent_sender.send(CommonScriptMsg::Task(
self.parent_sender
.send(CommonScriptMsg::Task(
WorkerEvent,
task,
Some(pipeline_id),

View file

@ -40,9 +40,11 @@ impl DissimilarOriginLocation {
}
pub fn new(window: &DissimilarOriginWindow) -> DomRoot<DissimilarOriginLocation> {
reflect_dom_object(Box::new(DissimilarOriginLocation::new_inherited(window)),
reflect_dom_object(
Box::new(DissimilarOriginLocation::new_inherited(window)),
window,
DissimilarOriginLocationBinding::Wrap)
DissimilarOriginLocationBinding::Wrap,
)
}
#[allow(dead_code)]

View file

@ -46,10 +46,7 @@ pub struct DissimilarOriginWindow {
impl DissimilarOriginWindow {
#[allow(unsafe_code)]
pub fn new(
global_to_clone_from: &GlobalScope,
window_proxy: &WindowProxy,
) -> DomRoot<Self> {
pub fn new(global_to_clone_from: &GlobalScope, window_proxy: &WindowProxy) -> DomRoot<Self> {
let cx = global_to_clone_from.get_cx();
// Any timer events fired on this window are ignored.
let (timer_event_chan, _) = ipc::channel().unwrap();
@ -142,7 +139,12 @@ impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
#[allow(unsafe_code)]
// https://html.spec.whatwg.org/multipage/#dom-window-postmessage
unsafe fn PostMessage(&self, cx: *mut JSContext, message: HandleValue, origin: DOMString) -> ErrorResult {
unsafe fn PostMessage(
&self,
cx: *mut JSContext,
message: HandleValue,
origin: DOMString,
) -> ErrorResult {
// Step 3-5.
let origin = match &origin[..] {
"*" => None,
@ -153,7 +155,7 @@ impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
url => match ServoUrl::parse(&url) {
Ok(url) => Some(url.origin()),
Err(_) => return Err(Error::Syntax),
}
},
};
// Step 1-2, 6-8.
@ -190,7 +192,8 @@ impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
// https://html.spec.whatwg.org/multipage/#dom-location
fn Location(&self) -> DomRoot<DissimilarOriginLocation> {
self.location.or_init(|| DissimilarOriginLocation::new(self))
self.location
.or_init(|| DissimilarOriginLocation::new(self))
}
}
@ -200,9 +203,11 @@ impl DissimilarOriginWindow {
None => return warn!("postMessage called with no incumbent global"),
Some(incumbent) => incumbent,
};
let msg = ScriptMsg::PostMessage(self.window_proxy.browsing_context_id(),
let msg = ScriptMsg::PostMessage(
self.window_proxy.browsing_context_id(),
origin,
data.move_to_arraybuffer());
data.move_to_arraybuffer(),
);
let _ = incumbent.script_to_constellation_chan().send(msg);
}
}

File diff suppressed because it is too large Load diff

View file

@ -34,9 +34,11 @@ impl DocumentFragment {
}
pub fn new(document: &Document) -> DomRoot<DocumentFragment> {
Node::reflect_node(Box::new(DocumentFragment::new_inherited(document)),
Node::reflect_node(
Box::new(DocumentFragment::new_inherited(document)),
document,
DocumentFragmentBinding::Wrap)
DocumentFragmentBinding::Wrap,
)
}
pub fn Constructor(window: &Window) -> Fallible<DomRoot<DocumentFragment>> {
@ -57,12 +59,14 @@ impl DocumentFragmentMethods for DocumentFragment {
fn GetElementById(&self, id: DOMString) -> Option<DomRoot<Element>> {
let node = self.upcast::<Node>();
let id = Atom::from(id);
node.traverse_preorder().filter_map(DomRoot::downcast::<Element>).find(|descendant| {
match descendant.get_attribute(&ns!(), &local_name!("id")) {
node.traverse_preorder()
.filter_map(DomRoot::downcast::<Element>)
.find(
|descendant| match descendant.get_attribute(&ns!(), &local_name!("id")) {
None => false,
Some(attr) => *attr.value().as_atom() == id,
}
})
},
)
}
// https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild
@ -72,7 +76,10 @@ impl DocumentFragmentMethods for DocumentFragment {
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
fn GetLastElementChild(&self) -> Option<DomRoot<Element>> {
self.upcast::<Node>().rev_children().filter_map(DomRoot::downcast::<Element>).next()
self.upcast::<Node>()
.rev_children()
.filter_map(DomRoot::downcast::<Element>)
.next()
}
// https://dom.spec.whatwg.org/#dom-parentnode-childelementcount

View file

@ -24,11 +24,12 @@ pub struct DocumentType {
}
impl DocumentType {
fn new_inherited(name: DOMString,
fn new_inherited(
name: DOMString,
public_id: Option<DOMString>,
system_id: Option<DOMString>,
document: &Document)
-> DocumentType {
document: &Document,
) -> DocumentType {
DocumentType {
node: Node::new_inherited(document),
name: name,
@ -37,14 +38,19 @@ impl DocumentType {
}
}
#[allow(unrooted_must_root)]
pub fn new(name: DOMString,
pub fn new(
name: DOMString,
public_id: Option<DOMString>,
system_id: Option<DOMString>,
document: &Document)
-> DomRoot<DocumentType> {
Node::reflect_node(Box::new(DocumentType::new_inherited(name, public_id, system_id, document)),
document: &Document,
) -> DomRoot<DocumentType> {
Node::reflect_node(
Box::new(DocumentType::new_inherited(
name, public_id, system_id, document,
)),
document,
DocumentTypeBinding::Wrap)
DocumentTypeBinding::Wrap,
)
}
#[inline]

View file

@ -53,9 +53,11 @@ impl DOMException {
}
pub fn new(global: &GlobalScope, code: DOMErrorName) -> DomRoot<DOMException> {
reflect_dom_object(Box::new(DOMException::new_inherited(code)),
reflect_dom_object(
Box::new(DOMException::new_inherited(code)),
global,
DOMExceptionBinding::Wrap)
DOMExceptionBinding::Wrap,
)
}
}
@ -74,7 +76,9 @@ impl DOMExceptionMethods for DOMException {
fn Message(&self) -> DOMString {
let message = match self.code {
DOMErrorName::IndexSizeError => "The index is not in the allowed range.",
DOMErrorName::HierarchyRequestError => "The operation would yield an incorrect node tree.",
DOMErrorName::HierarchyRequestError => {
"The operation would yield an incorrect node tree."
},
DOMErrorName::WrongDocumentError => "The object is in the wrong document.",
DOMErrorName::InvalidCharacterError => "The string contains invalid characters.",
DOMErrorName::NoModificationAllowedError => "The object can not be modified.",
@ -85,17 +89,20 @@ impl DOMExceptionMethods for DOMException {
DOMErrorName::SyntaxError => "The string did not match the expected pattern.",
DOMErrorName::InvalidModificationError => "The object can not be modified in this way.",
DOMErrorName::NamespaceError => "The operation is not allowed by Namespaces in XML.",
DOMErrorName::InvalidAccessError => "The object does not support the operation or argument.",
DOMErrorName::InvalidAccessError => {
"The object does not support the operation or argument."
},
DOMErrorName::SecurityError => "The operation is insecure.",
DOMErrorName::NetworkError => "A network error occurred.",
DOMErrorName::AbortError => "The operation was aborted.",
DOMErrorName::TypeMismatchError => "The given type does not match any expected type.",
DOMErrorName::QuotaExceededError => "The quota has been exceeded.",
DOMErrorName::TimeoutError => "The operation timed out.",
DOMErrorName::InvalidNodeTypeError =>
"The supplied node is incorrect or has an incorrect ancestor for this operation.",
DOMErrorName::InvalidNodeTypeError => {
"The supplied node is incorrect or has an incorrect ancestor for this operation."
},
DOMErrorName::DataCloneError => "The object can not be cloned.",
DOMErrorName::NotReadableError => "The I/O read operation failed."
DOMErrorName::NotReadableError => "The I/O read operation failed.",
};
DOMString::from(message)

View file

@ -44,42 +44,60 @@ impl DOMImplementation {
pub fn new(document: &Document) -> DomRoot<DOMImplementation> {
let window = document.window();
reflect_dom_object(Box::new(DOMImplementation::new_inherited(document)),
reflect_dom_object(
Box::new(DOMImplementation::new_inherited(document)),
window,
DOMImplementationBinding::Wrap)
DOMImplementationBinding::Wrap,
)
}
}
// https://dom.spec.whatwg.org/#domimplementation
impl DOMImplementationMethods for DOMImplementation {
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
fn CreateDocumentType(&self,
fn CreateDocumentType(
&self,
qualified_name: DOMString,
pubid: DOMString,
sysid: DOMString)
-> Fallible<DomRoot<DocumentType>> {
sysid: DOMString,
) -> Fallible<DomRoot<DocumentType>> {
validate_qualified_name(&qualified_name)?;
Ok(DocumentType::new(qualified_name, Some(pubid), Some(sysid), &self.document))
Ok(DocumentType::new(
qualified_name,
Some(pubid),
Some(sysid),
&self.document,
))
}
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocument
fn CreateDocument(&self,
fn CreateDocument(
&self,
maybe_namespace: Option<DOMString>,
qname: DOMString,
maybe_doctype: Option<&DocumentType>)
-> Fallible<DomRoot<XMLDocument>> {
maybe_doctype: Option<&DocumentType>,
) -> Fallible<DomRoot<XMLDocument>> {
let win = self.document.window();
let loader = DocumentLoader::new(&self.document.loader());
let namespace = namespace_from_domstring(maybe_namespace.to_owned());
let content_type = match namespace {
ns!(html) => Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_string()), vec![]),
ns!(svg) => Mime(TopLevel::Image, SubLevel::Ext("svg+xml".to_string()), vec![]),
_ => Mime(TopLevel::Application, SubLevel::Xml, vec![])
ns!(html) => Mime(
TopLevel::Application,
SubLevel::Ext("xhtml+xml".to_string()),
vec![],
),
ns!(svg) => Mime(
TopLevel::Image,
SubLevel::Ext("svg+xml".to_string()),
vec![],
),
_ => Mime(TopLevel::Application, SubLevel::Xml, vec![]),
};
// Step 1.
let doc = XMLDocument::new(win,
let doc = XMLDocument::new(
win,
HasBrowsingContext::No,
None,
self.document.origin().clone(),
@ -88,13 +106,17 @@ impl DOMImplementationMethods for DOMImplementation {
None,
DocumentActivity::Inactive,
DocumentSource::NotFromParser,
loader);
loader,
);
// Step 2-3.
let maybe_elem = if qname.is_empty() {
None
} else {
let options = ElementCreationOptions { is: None };
match doc.upcast::<Document>().CreateElementNS(maybe_namespace, qname, &options) {
match doc
.upcast::<Document>()
.CreateElementNS(maybe_namespace, qname, &options)
{
Err(error) => return Err(error),
Ok(elem) => Some(elem),
}
@ -127,7 +149,8 @@ impl DOMImplementationMethods for DOMImplementation {
let loader = DocumentLoader::new(&self.document.loader());
// Step 1-2.
let doc = Document::new(win,
let doc = Document::new(
win,
HasBrowsingContext::No,
None,
self.document.origin().clone(),
@ -139,7 +162,8 @@ impl DOMImplementationMethods for DOMImplementation {
loader,
None,
None,
Default::default());
Default::default(),
);
{
// Step 3.
@ -151,25 +175,24 @@ impl DOMImplementationMethods for DOMImplementation {
{
// Step 4.
let doc_node = doc.upcast::<Node>();
let doc_html = DomRoot::upcast::<Node>(HTMLHtmlElement::new(local_name!("html"),
None,
&doc));
let doc_html =
DomRoot::upcast::<Node>(HTMLHtmlElement::new(local_name!("html"), None, &doc));
doc_node.AppendChild(&doc_html).expect("Appending failed");
{
// Step 5.
let doc_head = DomRoot::upcast::<Node>(HTMLHeadElement::new(local_name!("head"),
None,
&doc));
let doc_head =
DomRoot::upcast::<Node>(HTMLHeadElement::new(local_name!("head"), None, &doc));
doc_html.AppendChild(&doc_head).unwrap();
// Step 6.
if let Some(title_str) = title {
// Step 6.1.
let doc_title =
DomRoot::upcast::<Node>(HTMLTitleElement::new(local_name!("title"),
let doc_title = DomRoot::upcast::<Node>(HTMLTitleElement::new(
local_name!("title"),
None,
&doc));
&doc,
));
doc_head.AppendChild(&doc_title).unwrap();
// Step 6.2.

View file

@ -17,7 +17,7 @@ use js::typedarray::{Float32Array, Float64Array};
#[dom_struct]
pub struct DOMMatrix {
parent: DOMMatrixReadOnly
parent: DOMMatrixReadOnly,
}
impl DOMMatrix {
@ -29,7 +29,7 @@ impl DOMMatrix {
pub fn new_inherited(is2D: bool, matrix: Transform3D<f64>) -> Self {
DOMMatrix {
parent: DOMMatrixReadOnly::new_inherited(is2D, matrix)
parent: DOMMatrixReadOnly::new_inherited(is2D, matrix),
}
}
@ -40,18 +40,12 @@ impl DOMMatrix {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-dommatrix-numbersequence
pub fn Constructor_(global: &GlobalScope, entries: Vec<f64>) -> Fallible<DomRoot<Self>> {
entries_to_matrix(&entries[..])
.map(|(is2D, matrix)| {
Self::new(global, is2D, matrix)
})
entries_to_matrix(&entries[..]).map(|(is2D, matrix)| Self::new(global, is2D, matrix))
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-frommatrix
pub fn FromMatrix(global: &GlobalScope, other: &DOMMatrixInit) -> Fallible<DomRoot<Self>> {
dommatrixinit_to_matrix(&other)
.map(|(is2D, matrix)| {
Self::new(global, is2D, matrix)
})
dommatrixinit_to_matrix(&other).map(|(is2D, matrix)| Self::new(global, is2D, matrix))
}
pub fn from_readonly(global: &GlobalScope, ro: &DOMMatrixReadOnly) -> DomRoot<Self> {
@ -299,7 +293,7 @@ impl DOMMatrixMethods for DOMMatrix {
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-multiplyself
fn MultiplySelf(&self, other:&DOMMatrixInit) -> Fallible<DomRoot<DOMMatrix>> {
fn MultiplySelf(&self, other: &DOMMatrixInit) -> Fallible<DomRoot<DOMMatrix>> {
// Steps 1-3.
self.upcast::<DOMMatrixReadOnly>().multiply_self(other)
// Step 4.
@ -307,7 +301,7 @@ impl DOMMatrixMethods for DOMMatrix {
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-premultiplyself
fn PreMultiplySelf(&self, other:&DOMMatrixInit) -> Fallible<DomRoot<DOMMatrix>> {
fn PreMultiplySelf(&self, other: &DOMMatrixInit) -> Fallible<DomRoot<DOMMatrix>> {
// Steps 1-3.
self.upcast::<DOMMatrixReadOnly>().pre_multiply_self(other)
// Step 4.
@ -317,24 +311,40 @@ impl DOMMatrixMethods for DOMMatrix {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-translateself
fn TranslateSelf(&self, tx: f64, ty: f64, tz: f64) -> DomRoot<DOMMatrix> {
// Steps 1-2.
self.upcast::<DOMMatrixReadOnly>().translate_self(tx, ty, tz);
self.upcast::<DOMMatrixReadOnly>()
.translate_self(tx, ty, tz);
// Step 3.
DomRoot::from_ref(&self)
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-scaleself
fn ScaleSelf(&self, scaleX: f64, scaleY: Option<f64>, scaleZ: f64,
originX: f64, originY: f64, originZ: f64) -> DomRoot<DOMMatrix> {
fn ScaleSelf(
&self,
scaleX: f64,
scaleY: Option<f64>,
scaleZ: f64,
originX: f64,
originY: f64,
originZ: f64,
) -> DomRoot<DOMMatrix> {
// Steps 1-6.
self.upcast::<DOMMatrixReadOnly>().scale_self(scaleX, scaleY, scaleZ, originX, originY, originZ);
self.upcast::<DOMMatrixReadOnly>()
.scale_self(scaleX, scaleY, scaleZ, originX, originY, originZ);
// Step 7.
DomRoot::from_ref(&self)
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-scale3dself
fn Scale3dSelf(&self, scale: f64, originX: f64, originY: f64, originZ: f64) -> DomRoot<DOMMatrix> {
fn Scale3dSelf(
&self,
scale: f64,
originX: f64,
originY: f64,
originZ: f64,
) -> DomRoot<DOMMatrix> {
// Steps 1-4.
self.upcast::<DOMMatrixReadOnly>().scale_3d_self(scale, originX, originY, originZ);
self.upcast::<DOMMatrixReadOnly>()
.scale_3d_self(scale, originX, originY, originZ);
// Step 5.
DomRoot::from_ref(&self)
}
@ -342,7 +352,8 @@ impl DOMMatrixMethods for DOMMatrix {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-rotateself
fn RotateSelf(&self, rotX: f64, rotY: Option<f64>, rotZ: Option<f64>) -> DomRoot<DOMMatrix> {
// Steps 1-7.
self.upcast::<DOMMatrixReadOnly>().rotate_self(rotX, rotY, rotZ);
self.upcast::<DOMMatrixReadOnly>()
.rotate_self(rotX, rotY, rotZ);
// Step 8.
DomRoot::from_ref(&self)
}
@ -350,7 +361,8 @@ impl DOMMatrixMethods for DOMMatrix {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-rotatefromvectorself
fn RotateFromVectorSelf(&self, x: f64, y: f64) -> DomRoot<DOMMatrix> {
// Step 1.
self.upcast::<DOMMatrixReadOnly>().rotate_from_vector_self(x, y);
self.upcast::<DOMMatrixReadOnly>()
.rotate_from_vector_self(x, y);
// Step 2.
DomRoot::from_ref(&self)
}
@ -358,7 +370,8 @@ impl DOMMatrixMethods for DOMMatrix {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-rotateaxisangleself
fn RotateAxisAngleSelf(&self, x: f64, y: f64, z: f64, angle: f64) -> DomRoot<DOMMatrix> {
// Steps 1-2.
self.upcast::<DOMMatrixReadOnly>().rotate_axis_angle_self(x, y, z, angle);
self.upcast::<DOMMatrixReadOnly>()
.rotate_axis_angle_self(x, y, z, angle);
// Step 3.
DomRoot::from_ref(&self)
}

View file

@ -53,18 +53,12 @@ impl DOMMatrixReadOnly {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly-numbersequence
pub fn Constructor_(global: &GlobalScope, entries: Vec<f64>) -> Fallible<DomRoot<Self>> {
entries_to_matrix(&entries[..])
.map(|(is2D, matrix)| {
Self::new(global, is2D, matrix)
})
entries_to_matrix(&entries[..]).map(|(is2D, matrix)| Self::new(global, is2D, matrix))
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-frommatrix
pub fn FromMatrix(global: &GlobalScope, other: &DOMMatrixInit) -> Fallible<DomRoot<Self>> {
dommatrixinit_to_matrix(&other)
.map(|(is2D, matrix)| {
Self::new(global, is2D, matrix)
})
dommatrixinit_to_matrix(&other).map(|(is2D, matrix)| Self::new(global, is2D, matrix))
}
pub fn matrix(&self) -> Ref<Transform3D<f64>> {
@ -155,7 +149,6 @@ impl DOMMatrixReadOnly {
self.matrix.borrow_mut().m44 = value;
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-multiplyself
pub fn multiply_self(&self, other: &DOMMatrixInit) -> Fallible<()> {
// Step 1.
@ -200,8 +193,15 @@ impl DOMMatrixReadOnly {
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrix-scaleself
pub fn scale_self(&self, scaleX: f64, scaleY: Option<f64>, scaleZ: f64,
mut originX: f64, mut originY: f64, mut originZ: f64) {
pub fn scale_self(
&self,
scaleX: f64,
scaleY: Option<f64>,
scaleZ: f64,
mut originX: f64,
mut originY: f64,
mut originZ: f64,
) {
// Step 1.
self.translate_self(originX, originY, originZ);
// Step 2.
@ -262,19 +262,22 @@ impl DOMMatrixReadOnly {
}
if rotZ != 0.0 {
// Step 5.
let rotation = Transform3D::create_rotation(0.0, 0.0, 1.0, Angle::radians(rotZ.to_radians()));
let rotation =
Transform3D::create_rotation(0.0, 0.0, 1.0, Angle::radians(rotZ.to_radians()));
let mut matrix = self.matrix.borrow_mut();
*matrix = rotation.post_mul(&matrix);
}
if rotY != 0.0 {
// Step 6.
let rotation = Transform3D::create_rotation(0.0, 1.0, 0.0, Angle::radians(rotY.to_radians()));
let rotation =
Transform3D::create_rotation(0.0, 1.0, 0.0, Angle::radians(rotY.to_radians()));
let mut matrix = self.matrix.borrow_mut();
*matrix = rotation.post_mul(&matrix);
}
if rotX != 0.0 {
// Step 7.
let rotation = Transform3D::create_rotation(1.0, 0.0, 0.0, Angle::radians(rotX.to_radians()));
let rotation =
Transform3D::create_rotation(1.0, 0.0, 0.0, Angle::radians(rotX.to_radians()));
let mut matrix = self.matrix.borrow_mut();
*matrix = rotation.post_mul(&matrix);
}
@ -298,7 +301,12 @@ impl DOMMatrixReadOnly {
pub fn rotate_axis_angle_self(&self, x: f64, y: f64, z: f64, angle: f64) {
// Step 1.
let (norm_x, norm_y, norm_z) = normalize_point(x, y, z);
let rotation = Transform3D::create_rotation(norm_x, norm_y, norm_z, Angle::radians(angle.to_radians()));
let rotation = Transform3D::create_rotation(
norm_x,
norm_y,
norm_z,
Angle::radians(angle.to_radians()),
);
let mut matrix = self.matrix.borrow_mut();
*matrix = rotation.post_mul(&matrix);
// Step 2.
@ -333,10 +341,24 @@ impl DOMMatrixReadOnly {
*matrix = matrix.inverse().unwrap_or_else(|| {
// Step 2.
self.is2D.set(false);
Transform3D::row_major(f64::NAN, f64::NAN, f64::NAN, f64::NAN,
f64::NAN, f64::NAN, f64::NAN, f64::NAN,
f64::NAN, f64::NAN, f64::NAN, f64::NAN,
f64::NAN, f64::NAN, f64::NAN, f64::NAN)
Transform3D::row_major(
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
f64::NAN,
)
})
// Step 3 in DOMMatrix.InvertSelf
}
@ -362,7 +384,6 @@ impl DOMMatrixReadOnly {
}
}
impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m11
fn M11(&self) -> f64 {
@ -482,10 +503,22 @@ impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-isidentity
fn IsIdentity(&self) -> bool {
let matrix = self.matrix.borrow();
matrix.m12 == 0.0 && matrix.m13 == 0.0 && matrix.m14 == 0.0 && matrix.m21 == 0.0 &&
matrix.m23 == 0.0 && matrix.m24 == 0.0 && matrix.m31 == 0.0 && matrix.m32 == 0.0 &&
matrix.m34 == 0.0 && matrix.m41 == 0.0 && matrix.m42 == 0.0 && matrix.m43 == 0.0 &&
matrix.m11 == 1.0 && matrix.m22 == 1.0 && matrix.m33 == 1.0 && matrix.m44 == 1.0
matrix.m12 == 0.0 &&
matrix.m13 == 0.0 &&
matrix.m14 == 0.0 &&
matrix.m21 == 0.0 &&
matrix.m23 == 0.0 &&
matrix.m24 == 0.0 &&
matrix.m31 == 0.0 &&
matrix.m32 == 0.0 &&
matrix.m34 == 0.0 &&
matrix.m41 == 0.0 &&
matrix.m42 == 0.0 &&
matrix.m43 == 0.0 &&
matrix.m11 == 1.0 &&
matrix.m22 == 1.0 &&
matrix.m33 == 1.0 &&
matrix.m44 == 1.0
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-translate
@ -494,16 +527,22 @@ impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly {
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-scale
fn Scale(&self, scaleX: f64, scaleY: Option<f64>, scaleZ: f64,
originX: f64, originY: f64, originZ: f64) -> DomRoot<DOMMatrix> {
fn Scale(
&self,
scaleX: f64,
scaleY: Option<f64>,
scaleZ: f64,
originX: f64,
originY: f64,
originZ: f64,
) -> DomRoot<DOMMatrix> {
DOMMatrix::from_readonly(&self.global(), self)
.ScaleSelf(scaleX, scaleY, scaleZ, originX, originY, originZ)
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-scale3d
fn Scale3d(&self, scale: f64, originX: f64, originY: f64, originZ: f64) -> DomRoot<DOMMatrix> {
DOMMatrix::from_readonly(&self.global(), self)
.Scale3dSelf(scale, originX, originY, originZ)
DOMMatrix::from_readonly(&self.global(), self).Scale3dSelf(scale, originX, originY, originZ)
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-rotate
@ -539,10 +578,9 @@ impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-flipx
fn FlipX(&self) -> DomRoot<DOMMatrix> {
let is2D = self.is2D.get();
let flip = Transform3D::row_major(-1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
let flip = Transform3D::row_major(
-1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
);
let matrix = flip.post_mul(&self.matrix.borrow());
DOMMatrix::new(&self.global(), is2D, matrix)
}
@ -550,10 +588,9 @@ impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-flipy
fn FlipY(&self) -> DomRoot<DOMMatrix> {
let is2D = self.is2D.get();
let flip = Transform3D::row_major(1.0, 0.0, 0.0, 0.0,
0.0, -1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
let flip = Transform3D::row_major(
1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
);
let matrix = flip.post_mul(&self.matrix.borrow());
DOMMatrix::new(&self.global(), is2D, matrix)
}
@ -583,11 +620,15 @@ impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly {
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-tofloat32array
#[allow(unsafe_code)]
unsafe fn ToFloat32Array(&self, cx: *mut JSContext) -> NonNull<JSObject> {
let vec: Vec<f32> = self.matrix
.borrow().to_row_major_array().iter().map(|&x| x as f32).collect();
let vec: Vec<f32> = self
.matrix
.borrow()
.to_row_major_array()
.iter()
.map(|&x| x as f32)
.collect();
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
let _ = Float32Array::create(cx, CreateWith::Slice(&vec), array.handle_mut())
.unwrap();
let _ = Float32Array::create(cx, CreateWith::Slice(&vec), array.handle_mut()).unwrap();
NonNull::new_unchecked(array.get())
}
@ -596,28 +637,39 @@ impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly {
unsafe fn ToFloat64Array(&self, cx: *mut JSContext) -> NonNull<JSObject> {
let arr = self.matrix.borrow().to_row_major_array();
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
let _ = Float64Array::create(cx, CreateWith::Slice(&arr), array.handle_mut())
.unwrap();
let _ = Float64Array::create(cx, CreateWith::Slice(&arr), array.handle_mut()).unwrap();
NonNull::new_unchecked(array.get())
}
}
// https://drafts.fxtf.org/geometry-1/#create-a-2d-matrix
fn create_2d_matrix(entries: &[f64]) -> Transform3D<f64> {
Transform3D::row_major(entries[0], entries[1], 0.0, 0.0,
entries[2], entries[3], 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
entries[4], entries[5], 0.0, 1.0)
Transform3D::row_major(
entries[0], entries[1], 0.0, 0.0, entries[2], entries[3], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
entries[4], entries[5], 0.0, 1.0,
)
}
// https://drafts.fxtf.org/geometry-1/#create-a-3d-matrix
fn create_3d_matrix(entries: &[f64]) -> Transform3D<f64> {
Transform3D::row_major(entries[0], entries[1], entries[2], entries[3],
entries[4], entries[5], entries[6], entries[7],
entries[8], entries[9], entries[10], entries[11],
entries[12], entries[13], entries[14], entries[15])
Transform3D::row_major(
entries[0],
entries[1],
entries[2],
entries[3],
entries[4],
entries[5],
entries[6],
entries[7],
entries[8],
entries[9],
entries[10],
entries[11],
entries[12],
entries[13],
entries[14],
entries[15],
)
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly-numbersequence
@ -632,7 +684,6 @@ pub fn entries_to_matrix(entries: &[f64]) -> Fallible<(bool, Transform3D<f64>)>
}
}
// https://drafts.fxtf.org/geometry-1/#validate-and-fixup
pub fn dommatrixinit_to_matrix(dict: &DOMMatrixInit) -> Fallible<(bool, Transform3D<f64>)> {
// Step 1.
@ -642,10 +693,19 @@ pub fn dommatrixinit_to_matrix(dict: &DOMMatrixInit) -> Fallible<(bool, Transfor
dict.d.is_some() && dict.m22.is_some() && dict.d.unwrap() != dict.m22.unwrap() ||
dict.e.is_some() && dict.m41.is_some() && dict.e.unwrap() != dict.m41.unwrap() ||
dict.f.is_some() && dict.m42.is_some() && dict.f.unwrap() != dict.m42.unwrap() ||
dict.is2D.is_some() && dict.is2D.unwrap() &&
(dict.m31 != 0.0 || dict.m32 != 0.0 || dict.m13 != 0.0 || dict.m23 != 0.0 ||
dict.m43 != 0.0 || dict.m14 != 0.0 || dict.m24 != 0.0 || dict.m34 != 0.0 ||
dict.m33 != 1.0 || dict.m44 != 1.0) {
dict.is2D.is_some() &&
dict.is2D.unwrap() &&
(dict.m31 != 0.0 ||
dict.m32 != 0.0 ||
dict.m13 != 0.0 ||
dict.m23 != 0.0 ||
dict.m43 != 0.0 ||
dict.m14 != 0.0 ||
dict.m24 != 0.0 ||
dict.m34 != 0.0 ||
dict.m33 != 1.0 ||
dict.m44 != 1.0)
{
Err(error::Error::Type("Invalid matrix initializer.".to_owned()))
} else {
let mut is2D = dict.is2D;
@ -663,25 +723,31 @@ pub fn dommatrixinit_to_matrix(dict: &DOMMatrixInit) -> Fallible<(bool, Transfor
let m42 = dict.m42.unwrap_or(dict.f.unwrap_or(0.0));
// Step 8.
if is2D.is_none() &&
(dict.m31 != 0.0 || dict.m32 != 0.0 || dict.m13 != 0.0 ||
dict.m23 != 0.0 || dict.m43 != 0.0 || dict.m14 != 0.0 ||
dict.m24 != 0.0 || dict.m34 != 0.0 ||
dict.m33 != 1.0 || dict.m44 != 1.0) {
(dict.m31 != 0.0 ||
dict.m32 != 0.0 ||
dict.m13 != 0.0 ||
dict.m23 != 0.0 ||
dict.m43 != 0.0 ||
dict.m14 != 0.0 ||
dict.m24 != 0.0 ||
dict.m34 != 0.0 ||
dict.m33 != 1.0 ||
dict.m44 != 1.0)
{
is2D = Some(false);
}
// Step 9.
if is2D.is_none() {
is2D = Some(true);
}
let matrix = Transform3D::row_major(m11, m12, dict.m13, dict.m14,
m21, m22, dict.m23, dict.m24,
dict.m31, dict.m32, dict.m33, dict.m34,
m41, m42, dict.m43, dict.m44);
let matrix = Transform3D::row_major(
m11, m12, dict.m13, dict.m14, m21, m22, dict.m23, dict.m24, dict.m31, dict.m32,
dict.m33, dict.m34, m41, m42, dict.m43, dict.m44,
);
Ok((is2D.unwrap(), matrix))
}
}
#[inline]
fn normalize_point(x: f64, y: f64, z: f64) -> (f64, f64, f64) {
let len = (x * x + y * y + z * z).sqrt();

View file

@ -37,9 +37,11 @@ impl DOMParser {
}
pub fn new(window: &Window) -> DomRoot<DOMParser> {
reflect_dom_object(Box::new(DOMParser::new_inherited(window)),
reflect_dom_object(
Box::new(DOMParser::new_inherited(window)),
window,
DOMParserBinding::Wrap)
DOMParserBinding::Wrap,
)
}
pub fn Constructor(window: &Window) -> Fallible<DomRoot<DOMParser>> {
@ -49,17 +51,22 @@ impl DOMParser {
impl DOMParserMethods for DOMParser {
// https://w3c.github.io/DOM-Parsing/#the-domparser-interface
fn ParseFromString(&self,
fn ParseFromString(
&self,
s: DOMString,
ty: DOMParserBinding::SupportedType)
-> Fallible<DomRoot<Document>> {
ty: DOMParserBinding::SupportedType,
) -> Fallible<DomRoot<Document>> {
let url = self.window.get_url();
let content_type = ty.as_str().parse().expect("Supported type is not a MIME type");
let content_type = ty
.as_str()
.parse()
.expect("Supported type is not a MIME type");
let doc = self.window.Document();
let loader = DocumentLoader::new(&*doc.loader());
match ty {
Text_html => {
let document = Document::new(&self.window,
let document = Document::new(
&self.window,
HasBrowsingContext::No,
Some(url.clone()),
doc.origin().clone(),
@ -71,13 +78,15 @@ impl DOMParserMethods for DOMParser {
loader,
None,
None,
Default::default());
Default::default(),
);
ServoParser::parse_html_document(&document, s, url);
document.set_ready_state(DocumentReadyState::Complete);
Ok(document)
}
},
Text_xml | Application_xml | Application_xhtml_xml => {
let document = Document::new(&self.window,
let document = Document::new(
&self.window,
HasBrowsingContext::No,
Some(url.clone()),
doc.origin().clone(),
@ -89,11 +98,12 @@ impl DOMParserMethods for DOMParser {
loader,
None,
None,
Default::default());
Default::default(),
);
ServoParser::parse_xml_document(&document, s, url);
document.set_ready_state(DocumentReadyState::Complete);
Ok(document)
}
},
}
}
}

View file

@ -28,12 +28,13 @@ impl DOMPoint {
reflect_dom_object(Box::new(DOMPoint::new_inherited(x, y, z, w)), global, Wrap)
}
pub fn Constructor(global: &GlobalScope,
pub fn Constructor(
global: &GlobalScope,
x: f64,
y: f64,
z: f64,
w: f64)
-> Fallible<DomRoot<DOMPoint>> {
w: f64,
) -> Fallible<DomRoot<DOMPoint>> {
Ok(DOMPoint::new(global, x, y, z, w))
}

View file

@ -32,17 +32,20 @@ impl DOMPointReadOnly {
}
pub fn new(global: &GlobalScope, x: f64, y: f64, z: f64, w: f64) -> DomRoot<DOMPointReadOnly> {
reflect_dom_object(Box::new(DOMPointReadOnly::new_inherited(x, y, z, w)),
reflect_dom_object(
Box::new(DOMPointReadOnly::new_inherited(x, y, z, w)),
global,
Wrap)
Wrap,
)
}
pub fn Constructor(global: &GlobalScope,
pub fn Constructor(
global: &GlobalScope,
x: f64,
y: f64,
z: f64,
w: f64)
-> Fallible<DomRoot<DOMPointReadOnly>> {
w: f64,
) -> Fallible<DomRoot<DOMPointReadOnly>> {
Ok(DOMPointReadOnly::new(global, x, y, z, w))
}
}

View file

@ -24,11 +24,7 @@ pub struct DOMQuad {
}
impl DOMQuad {
fn new_inherited(p1: &DOMPoint,
p2: &DOMPoint,
p3: &DOMPoint,
p4: &DOMPoint)
-> DOMQuad {
fn new_inherited(p1: &DOMPoint, p2: &DOMPoint, p3: &DOMPoint, p4: &DOMPoint) -> DOMQuad {
DOMQuad {
reflector_: Reflector::new(),
p1: Dom::from_ref(p1),
@ -38,45 +34,62 @@ impl DOMQuad {
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
p1: &DOMPoint,
p2: &DOMPoint,
p3: &DOMPoint,
p4: &DOMPoint) -> DomRoot<DOMQuad> {
reflect_dom_object(Box::new(DOMQuad::new_inherited(p1, p2, p3, p4)),
p4: &DOMPoint,
) -> DomRoot<DOMQuad> {
reflect_dom_object(
Box::new(DOMQuad::new_inherited(p1, p2, p3, p4)),
global,
Wrap)
Wrap,
)
}
pub fn Constructor(global: &GlobalScope,
pub fn Constructor(
global: &GlobalScope,
p1: &DOMPointInit,
p2: &DOMPointInit,
p3: &DOMPointInit,
p4: &DOMPointInit)
-> Fallible<DomRoot<DOMQuad>> {
Ok(DOMQuad::new(global,
p4: &DOMPointInit,
) -> Fallible<DomRoot<DOMQuad>> {
Ok(DOMQuad::new(
global,
&*DOMPoint::new_from_init(global, p1),
&*DOMPoint::new_from_init(global, p2),
&*DOMPoint::new_from_init(global, p3),
&*DOMPoint::new_from_init(global, p4)))
&*DOMPoint::new_from_init(global, p4),
))
}
// https://drafts.fxtf.org/geometry/#dom-domquad-fromrect
pub fn FromRect(global: &GlobalScope, other: &DOMRectInit) -> DomRoot<DOMQuad> {
DOMQuad::new(global,
DOMQuad::new(
global,
&*DOMPoint::new(global, other.x, other.y, 0f64, 1f64),
&*DOMPoint::new(global, other.x + other.width, other.y, 0f64, 1f64),
&*DOMPoint::new(global, other.x + other.width, other.y + other.height, 0f64, 1f64),
&*DOMPoint::new(global, other.x, other.y + other.height, 0f64, 1f64))
&*DOMPoint::new(
global,
other.x + other.width,
other.y + other.height,
0f64,
1f64,
),
&*DOMPoint::new(global, other.x, other.y + other.height, 0f64, 1f64),
)
}
// https://drafts.fxtf.org/geometry/#dom-domquad-fromquad
pub fn FromQuad(global: &GlobalScope, other: &DOMQuadInit) -> DomRoot<DOMQuad> {
DOMQuad::new(global,
DOMQuad::new(
global,
&DOMPoint::new_from_init(global, &other.p1),
&DOMPoint::new_from_init(global, &other.p2),
&DOMPoint::new_from_init(global, &other.p3),
&DOMPoint::new_from_init(global, &other.p4))
&DOMPoint::new_from_init(global, &other.p4),
)
}
}
@ -103,15 +116,31 @@ impl DOMQuadMethods for DOMQuad {
// https://drafts.fxtf.org/geometry/#dom-domquad-getbounds
fn GetBounds(&self) -> DomRoot<DOMRect> {
let left = self.p1.X().min(self.p2.X()).min(self.p3.X()).min(self.p4.X());
let top = self.p1.Y().min(self.p2.Y()).min(self.p3.Y()).min(self.p4.Y());
let right = self.p1.X().max(self.p2.X()).max(self.p3.X()).max(self.p4.X());
let bottom = self.p1.Y().max(self.p2.Y()).max(self.p3.Y()).max(self.p4.Y());
let left = self
.p1
.X()
.min(self.p2.X())
.min(self.p3.X())
.min(self.p4.X());
let top = self
.p1
.Y()
.min(self.p2.Y())
.min(self.p3.Y())
.min(self.p4.Y());
let right = self
.p1
.X()
.max(self.p2.X())
.max(self.p3.X())
.max(self.p4.X());
let bottom = self
.p1
.Y()
.max(self.p2.Y())
.max(self.p3.Y())
.max(self.p4.Y());
DOMRect::new(&self.global(),
left,
top,
right - left,
bottom - top)
DOMRect::new(&self.global(), left, top, right - left, bottom - top)
}
}

View file

@ -25,17 +25,20 @@ impl DOMRect {
}
pub fn new(global: &GlobalScope, x: f64, y: f64, width: f64, height: f64) -> DomRoot<DOMRect> {
reflect_dom_object(Box::new(DOMRect::new_inherited(x, y, width, height)),
reflect_dom_object(
Box::new(DOMRect::new_inherited(x, y, width, height)),
global,
DOMRectBinding::Wrap)
DOMRectBinding::Wrap,
)
}
pub fn Constructor(global: &GlobalScope,
pub fn Constructor(
global: &GlobalScope,
x: f64,
y: f64,
width: f64,
height: f64)
-> Fallible<DomRoot<DOMRect>> {
height: f64,
) -> Fallible<DomRoot<DOMRect>> {
Ok(DOMRect::new(global, x, y, width, height))
}
}

View file

@ -30,23 +30,27 @@ impl DOMRectReadOnly {
}
}
pub fn new(global: &GlobalScope,
pub fn new(
global: &GlobalScope,
x: f64,
y: f64,
width: f64,
height: f64)
-> DomRoot<DOMRectReadOnly> {
reflect_dom_object(Box::new(DOMRectReadOnly::new_inherited(x, y, width, height)),
height: f64,
) -> DomRoot<DOMRectReadOnly> {
reflect_dom_object(
Box::new(DOMRectReadOnly::new_inherited(x, y, width, height)),
global,
Wrap)
Wrap,
)
}
pub fn Constructor(global: &GlobalScope,
pub fn Constructor(
global: &GlobalScope,
x: f64,
y: f64,
width: f64,
height: f64)
-> Fallible<DomRoot<DOMRectReadOnly>> {
height: f64,
) -> Fallible<DomRoot<DOMRectReadOnly>> {
Ok(DOMRectReadOnly::new(global, x, y, width, height))
}

View file

@ -28,9 +28,11 @@ impl DOMStringMap {
pub fn new(element: &HTMLElement) -> DomRoot<DOMStringMap> {
let window = window_from_node(element);
reflect_dom_object(Box::new(DOMStringMap::new_inherited(element)),
reflect_dom_object(
Box::new(DOMStringMap::new_inherited(element)),
&*window,
DOMStringMapBinding::Wrap)
DOMStringMapBinding::Wrap,
)
}
}
@ -53,6 +55,10 @@ impl DOMStringMapMethods for DOMStringMap {
// https://html.spec.whatwg.org/multipage/#the-domstringmap-interface:supported-property-names
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
self.element.supported_prop_names_custom_attr().iter().cloned().collect()
self.element
.supported_prop_names_custom_attr()
.iter()
.cloned()
.collect()
}
}

View file

@ -34,9 +34,11 @@ impl DOMTokenList {
pub fn new(element: &Element, local_name: &LocalName) -> DomRoot<DOMTokenList> {
let window = window_from_node(element);
reflect_dom_object(Box::new(DOMTokenList::new_inherited(element, local_name.clone())),
reflect_dom_object(
Box::new(DOMTokenList::new_inherited(element, local_name.clone())),
&*window,
DOMTokenListBinding::Wrap)
DOMTokenListBinding::Wrap,
)
}
fn attribute(&self) -> Option<DomRoot<Attr>> {
@ -56,16 +58,18 @@ impl DOMTokenList {
impl DOMTokenListMethods for DOMTokenList {
// https://dom.spec.whatwg.org/#dom-domtokenlist-length
fn Length(&self) -> u32 {
self.attribute().map_or(0, |attr| {
attr.value().as_tokens().len()
}) as u32
self.attribute()
.map_or(0, |attr| attr.value().as_tokens().len()) as u32
}
// https://dom.spec.whatwg.org/#dom-domtokenlist-item
fn Item(&self, index: u32) -> Option<DOMString> {
self.attribute().and_then(|attr| {
// FIXME(ajeffrey): Convert directly from Atom to DOMString
attr.value().as_tokens().get(index as usize).map(|token| DOMString::from(&**token))
attr.value()
.as_tokens()
.get(index as usize)
.map(|token| DOMString::from(&**token))
})
}
@ -89,7 +93,8 @@ impl DOMTokenListMethods for DOMTokenList {
atoms.push(token);
}
}
self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms);
self.element
.set_atomic_tokenlist_attribute(&self.local_name, atoms);
Ok(())
}
@ -98,9 +103,13 @@ impl DOMTokenListMethods for DOMTokenList {
let mut atoms = self.element.get_tokenlist_attribute(&self.local_name);
for token in &tokens {
let token = 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);
self.element
.set_atomic_tokenlist_attribute(&self.local_name, atoms);
Ok(())
}
@ -113,17 +122,19 @@ impl DOMTokenListMethods for DOMTokenList {
Some(true) => Ok(true),
_ => {
atoms.remove(index);
self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms);
self.element
.set_atomic_tokenlist_attribute(&self.local_name, atoms);
Ok(false)
}
},
},
None => match force {
Some(false) => Ok(false),
_ => {
atoms.push(token);
self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms);
self.element
.set_atomic_tokenlist_attribute(&self.local_name, atoms);
Ok(true)
}
},
},
}
}
@ -135,7 +146,8 @@ impl DOMTokenListMethods for DOMTokenList {
// https://dom.spec.whatwg.org/#dom-domtokenlist-value
fn SetValue(&self, value: DOMString) {
self.element.set_tokenlist_attribute(&self.local_name, value);
self.element
.set_tokenlist_attribute(&self.local_name, value);
}
// https://dom.spec.whatwg.org/#dom-domtokenlist-replace
@ -159,7 +171,8 @@ impl DOMTokenListMethods for DOMTokenList {
atoms.remove(pos);
}
// Step 5.
self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms);
self.element
.set_atomic_tokenlist_attribute(&self.local_name, atoms);
}
Ok(())
}

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more