Files
tubestation/servo/components/script/dom/urlsearchparams.rs
Michael Wu ae3ff6be00 servo: Merge #6150 - Upgrade to Spidermonkey 39 (from servo:smupgrade3); r=mbrubeck
> Here it is.
>
> ~~There's two major things that are unfinished here:~~
> - ~~Dealing with the unroot_must_root lint. I'm not sure about the value of this lint with the new rooting API.~~ Done.
> - ~~Updating the Cargo.locks to point to the new SM and SM binding.~~ Done.
>
> I also included my fixes for the rust update, but these will disappear in a rebase. A rust update is necessary to support calling `Drop` on `Heap<T>` correctly when `Heap<T>` is inside a `Rc<T>`. Otherwise `&self` points to the wrong location.
>
> Incremental GC is disabled here. I'm not sure how to deal with the incremental barriers so that's left for later.
>
> Generational GC works. SM doesn't work without it.
>
> The biggest change here is to the rooting API. `Root` was made movable, and `Temporary` and `JSRef` was removed. Movable `Root`s means there's no need for `Temporary`, and `JSRef`s aren't needed generally since it can be assumed that being able to obtain a reference to a dom object means it's already rooted. References have their lifetime bound to the Roots that provided them. DOM objects that haven't passed through `reflect_dom_object` don't need to be rooted, and DOM objects that have passed through `reflect_dom_object` can't be obtained without being rooted through `native_from_reflector_jsmanaged` or `JS::<T>::root()`.
>
> Support for `Heap<T>` ended up messier than I expected. It's split into two commits, but only because it's a bit difficult to fold them together. Supporting `Heap<T>` properly requires that that `Heap::<T>::set()` be called on something that won't move. I removed the Copy and Clone trait from `Heap<T>` so `Cell` can't hold `Heap<T>` - only `UnsafeCell` can hold it.
>
> `CallbackObject` is a bit tricky - I moved all callbacks into `Rc<T>` in order to make sure that the pointer inside to a `*mut JSObject` doesn't move. This is necessary for supporting `Heap<T>`.
>
> `RootedCollectionSet` is very general purpose now. Anything with `JSTraceable` can be rooted by `RootedCollectionSet`/`RootedTraceable`. Right now, `RootedTraceable` is only used to hold down dom objects before they're fully attached to their reflector. I had to make a custom mechanism to dispatch the trace call - couldn't figure out how to get trait objects working for this case.
>
> This has been tested with the following zeal settings:
>
> GC after every allocation
> JS_GC_ZEAL=2,1
>
> GC after every 100 allocations (important for catching use-after-free bugs)
> JS_GC_ZEAL=2,100
>
> Verify pre barriers
> JS_GC_ZEAL=4,1
>
> Verify post barriers
> JS_GC_ZEAL=11,1

Source-Repo: https://github.com/servo/servo
Source-Revision: e7808c526c348fea5e3b48af70b7f1a066652097
2015-06-19 16:46:55 -06:00

152 lines
4.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::URLSearchParamsBinding;
use dom::bindings::codegen::Bindings::URLSearchParamsBinding::URLSearchParamsMethods;
use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams;
use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams::{eURLSearchParams, eString};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, reflect_dom_object};
use encoding::types::EncodingRef;
use url::form_urlencoded::{parse, serialize_with_encoding};
use util::str::DOMString;
// https://url.spec.whatwg.org/#interface-urlsearchparams
#[dom_struct]
pub struct URLSearchParams {
reflector_: Reflector,
// https://url.spec.whatwg.org/#concept-urlsearchparams-list
list: DOMRefCell<Vec<(DOMString, DOMString)>>,
}
impl URLSearchParams {
fn new_inherited() -> URLSearchParams {
URLSearchParams {
reflector_: Reflector::new(),
list: DOMRefCell::new(vec![]),
}
}
pub fn new(global: GlobalRef) -> Root<URLSearchParams> {
reflect_dom_object(box URLSearchParams::new_inherited(), global,
URLSearchParamsBinding::Wrap)
}
// https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
pub fn Constructor(global: GlobalRef, init: Option<StringOrURLSearchParams>) ->
Fallible<Root<URLSearchParams>> {
// Step 1.
let query = URLSearchParams::new(global);
match init {
Some(eString(init)) => {
// Step 2.
let query = query.r();
*query.list.borrow_mut() = parse(init.as_bytes());
},
Some(eURLSearchParams(init)) => {
// Step 3.
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let query = query.r();
let init = init.r();
*query.list.borrow_mut() = init.list.borrow().clone();
},
None => {}
}
// Step 4.
Ok(query)
}
}
impl<'a> URLSearchParamsMethods for &'a URLSearchParams {
// https://url.spec.whatwg.org/#dom-urlsearchparams-append
fn Append(self, name: DOMString, value: DOMString) {
// Step 1.
self.list.borrow_mut().push((name, value));
// Step 2.
self.update_steps();
}
// https://url.spec.whatwg.org/#dom-urlsearchparams-delete
fn Delete(self, name: DOMString) {
// Step 1.
self.list.borrow_mut().retain(|&(ref k, _)| k != &name);
// Step 2.
self.update_steps();
}
// https://url.spec.whatwg.org/#dom-urlsearchparams-get
fn Get(self, name: DOMString) -> Option<DOMString> {
let list = self.list.borrow();
list.iter().filter_map(|&(ref k, ref v)| {
if k == &name {
Some(v.clone())
} else {
None
}
}).next()
}
// https://url.spec.whatwg.org/#dom-urlsearchparams-has
fn Has(self, name: DOMString) -> bool {
let list = self.list.borrow();
list.iter().find(|&&(ref k, _)| k == &name).is_some()
}
// https://url.spec.whatwg.org/#dom-urlsearchparams-set
fn Set(self, name: DOMString, value: DOMString) {
let mut list = self.list.borrow_mut();
let mut index = None;
let mut i = 0;
list.retain(|&(ref k, _)| {
if index.is_none() {
if k == &name {
index = Some(i);
} else {
i += 1;
}
true
} else {
k != &name
}
});
match index {
Some(index) => list[index].1 = value,
None => list.push((name, value)),
};
self.update_steps();
}
// https://url.spec.whatwg.org/#stringification-behavior
fn Stringifier(self) -> DOMString {
self.serialize(None)
}
}
pub trait URLSearchParamsHelpers {
fn serialize(self, encoding: Option<EncodingRef>) -> DOMString;
}
impl<'a> URLSearchParamsHelpers for &'a URLSearchParams {
// https://url.spec.whatwg.org/#concept-urlencoded-serializer
fn serialize(self, encoding: Option<EncodingRef>) -> DOMString {
let list = self.list.borrow();
serialize_with_encoding(list.iter(), encoding)
}
}
trait PrivateURLSearchParamsHelpers {
fn update_steps(self);
}
impl<'a> PrivateURLSearchParamsHelpers for &'a URLSearchParams {
// https://url.spec.whatwg.org/#concept-uq-update
fn update_steps(self) {
// XXXManishearth Implement this when the URL interface is implemented
}
}