mirror of
https://github.com/servo/servo.git
synced 2025-06-08 16:43:28 +00:00
http://www.robohornet.org gives a score of 101.36 on master, and 102.68 with this PR. The latter is slightly better, but probably within noise level. So it looks like this PR does not affect DOM performance. This is expected since `Box::new` is defined as: ```rust impl<T> Box<T> { #[inline(always)] pub fn new(x: T) -> Box<T> { box x } } ``` With inlining, it should compile to the same as box syntax.
277 lines
9 KiB
Rust
277 lines
9 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
use dom::bindings::cell::DomRefCell;
|
|
use dom::bindings::codegen::Bindings::URLBinding::{self, URLMethods};
|
|
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
|
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
|
use dom::bindings::root::{DomRoot, MutNullableDom};
|
|
use dom::bindings::str::{DOMString, USVString};
|
|
use dom::blob::Blob;
|
|
use dom::globalscope::GlobalScope;
|
|
use dom::urlhelper::UrlHelper;
|
|
use dom::urlsearchparams::URLSearchParams;
|
|
use dom_struct::dom_struct;
|
|
use ipc_channel::ipc;
|
|
use net_traits::{CoreResourceMsg, IpcSend};
|
|
use net_traits::blob_url_store::{get_blob_origin, parse_blob_url};
|
|
use net_traits::filemanager_thread::FileManagerThreadMsg;
|
|
use servo_url::ServoUrl;
|
|
use std::default::Default;
|
|
use uuid::Uuid;
|
|
|
|
// https://url.spec.whatwg.org/#url
|
|
#[dom_struct]
|
|
pub struct URL {
|
|
reflector_: Reflector,
|
|
|
|
// https://url.spec.whatwg.org/#concept-url-url
|
|
url: DomRefCell<ServoUrl>,
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-searchparams
|
|
search_params: MutNullableDom<URLSearchParams>,
|
|
}
|
|
|
|
impl URL {
|
|
fn new_inherited(url: ServoUrl) -> URL {
|
|
URL {
|
|
reflector_: Reflector::new(),
|
|
url: DomRefCell::new(url),
|
|
search_params: Default::default(),
|
|
}
|
|
}
|
|
|
|
pub fn new(global: &GlobalScope, url: ServoUrl) -> DomRoot<URL> {
|
|
reflect_dom_object(Box::new(URL::new_inherited(url)),
|
|
global, URLBinding::Wrap)
|
|
}
|
|
|
|
pub fn query_pairs(&self) -> Vec<(String, String)> {
|
|
self.url.borrow().as_url().query_pairs().into_owned().collect()
|
|
}
|
|
|
|
pub fn set_query_pairs(&self, pairs: &[(String, String)]) {
|
|
let mut url = self.url.borrow_mut();
|
|
url.as_mut_url().query_pairs_mut().clear().extend_pairs(pairs);
|
|
}
|
|
}
|
|
|
|
impl URL {
|
|
// https://url.spec.whatwg.org/#constructors
|
|
pub fn Constructor(global: &GlobalScope, url: USVString,
|
|
base: Option<USVString>)
|
|
-> Fallible<DomRoot<URL>> {
|
|
let parsed_base = match base {
|
|
None => {
|
|
// Step 1.
|
|
None
|
|
},
|
|
Some(base) =>
|
|
// Step 2.1.
|
|
match ServoUrl::parse(&base.0) {
|
|
Ok(base) => Some(base),
|
|
Err(error) => {
|
|
// Step 2.2.
|
|
return Err(Error::Type(format!("could not parse base: {}", error)));
|
|
}
|
|
}
|
|
};
|
|
// Step 3.
|
|
let parsed_url = match ServoUrl::parse_with_base(parsed_base.as_ref(), &url.0) {
|
|
Ok(url) => url,
|
|
Err(error) => {
|
|
// Step 4.
|
|
return Err(Error::Type(format!("could not parse URL: {}", error)));
|
|
}
|
|
};
|
|
// Step 5: Skip (see step 8 below).
|
|
// Steps 6-7.
|
|
let result = URL::new(global, parsed_url);
|
|
// Step 8: Instead of construcing a new `URLSearchParams` object here, construct it
|
|
// on-demand inside `URL::SearchParams`.
|
|
// Step 9.
|
|
Ok(result)
|
|
}
|
|
|
|
// https://w3c.github.io/FileAPI/#dfn-createObjectURL
|
|
pub fn CreateObjectURL(global: &GlobalScope, blob: &Blob) -> DOMString {
|
|
// XXX: Second field is an unicode-serialized Origin, it is a temporary workaround
|
|
// and should not be trusted. See issue https://github.com/servo/servo/issues/11722
|
|
let origin = get_blob_origin(&global.get_url());
|
|
|
|
let id = blob.get_blob_url_id();
|
|
|
|
DOMString::from(URL::unicode_serialization_blob_url(&origin, &id))
|
|
}
|
|
|
|
// https://w3c.github.io/FileAPI/#dfn-revokeObjectURL
|
|
pub fn RevokeObjectURL(global: &GlobalScope, url: DOMString) {
|
|
/*
|
|
If the value provided for the url argument is not a Blob URL OR
|
|
if the value provided for the url argument does not have an entry in the Blob URL Store,
|
|
|
|
this method call does nothing. User agents may display a message on the error console.
|
|
*/
|
|
let origin = get_blob_origin(&global.get_url());
|
|
|
|
if let Ok(url) = ServoUrl::parse(&url) {
|
|
if let Ok((id, _)) = parse_blob_url(&url) {
|
|
let resource_threads = global.resource_threads();
|
|
let (tx, rx) = ipc::channel().unwrap();
|
|
let msg = FileManagerThreadMsg::RevokeBlobURL(id, origin, tx);
|
|
let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg));
|
|
|
|
let _ = rx.recv().unwrap();
|
|
}
|
|
}
|
|
}
|
|
|
|
// https://w3c.github.io/FileAPI/#unicodeSerializationOfBlobURL
|
|
fn unicode_serialization_blob_url(origin: &str, id: &Uuid) -> String {
|
|
// Step 1, 2
|
|
let mut result = "blob:".to_string();
|
|
|
|
// Step 3
|
|
result.push_str(origin);
|
|
|
|
// Step 4
|
|
result.push('/');
|
|
|
|
// Step 5
|
|
result.push_str(&id.simple().to_string());
|
|
|
|
result
|
|
}
|
|
}
|
|
|
|
impl URLMethods for URL {
|
|
// https://url.spec.whatwg.org/#dom-url-hash
|
|
fn Hash(&self) -> USVString {
|
|
UrlHelper::Hash(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-hash
|
|
fn SetHash(&self, value: USVString) {
|
|
UrlHelper::SetHash(&mut self.url.borrow_mut(), value);
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-host
|
|
fn Host(&self) -> USVString {
|
|
UrlHelper::Host(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-host
|
|
fn SetHost(&self, value: USVString) {
|
|
UrlHelper::SetHost(&mut self.url.borrow_mut(), value);
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-hostname
|
|
fn Hostname(&self) -> USVString {
|
|
UrlHelper::Hostname(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-hostname
|
|
fn SetHostname(&self, value: USVString) {
|
|
UrlHelper::SetHostname(&mut self.url.borrow_mut(), value);
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-href
|
|
fn Href(&self) -> USVString {
|
|
UrlHelper::Href(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-href
|
|
fn SetHref(&self, value: USVString) -> ErrorResult {
|
|
match ServoUrl::parse(&value.0) {
|
|
Ok(url) => {
|
|
*self.url.borrow_mut() = url;
|
|
self.search_params.set(None); // To be re-initialized in the SearchParams getter.
|
|
Ok(())
|
|
},
|
|
Err(error) => {
|
|
Err(Error::Type(format!("could not parse URL: {}", error)))
|
|
},
|
|
}
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-password
|
|
fn Password(&self) -> USVString {
|
|
UrlHelper::Password(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-password
|
|
fn SetPassword(&self, value: USVString) {
|
|
UrlHelper::SetPassword(&mut self.url.borrow_mut(), value);
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-pathname
|
|
fn Pathname(&self) -> USVString {
|
|
UrlHelper::Pathname(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-pathname
|
|
fn SetPathname(&self, value: USVString) {
|
|
UrlHelper::SetPathname(&mut self.url.borrow_mut(), value);
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-port
|
|
fn Port(&self) -> USVString {
|
|
UrlHelper::Port(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-port
|
|
fn SetPort(&self, value: USVString) {
|
|
UrlHelper::SetPort(&mut self.url.borrow_mut(), value);
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-protocol
|
|
fn Protocol(&self) -> USVString {
|
|
UrlHelper::Protocol(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-protocol
|
|
fn SetProtocol(&self, value: USVString) {
|
|
UrlHelper::SetProtocol(&mut self.url.borrow_mut(), value);
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-origin
|
|
fn Origin(&self) -> USVString {
|
|
UrlHelper::Origin(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-search
|
|
fn Search(&self) -> USVString {
|
|
UrlHelper::Search(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-search
|
|
fn SetSearch(&self, value: USVString) {
|
|
UrlHelper::SetSearch(&mut self.url.borrow_mut(), value);
|
|
if let Some(search_params) = self.search_params.get() {
|
|
search_params.set_list(self.query_pairs());
|
|
}
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-searchparams
|
|
fn SearchParams(&self) -> DomRoot<URLSearchParams> {
|
|
self.search_params.or_init(|| {
|
|
URLSearchParams::new(&self.global(), Some(self))
|
|
})
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-href
|
|
fn Stringifier(&self) -> DOMString {
|
|
DOMString::from(self.Href().0)
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-username
|
|
fn Username(&self) -> USVString {
|
|
UrlHelper::Username(&self.url.borrow())
|
|
}
|
|
|
|
// https://url.spec.whatwg.org/#dom-url-username
|
|
fn SetUsername(&self, value: USVString) {
|
|
UrlHelper::SetUsername(&mut self.url.borrow_mut(), value);
|
|
}
|
|
}
|