Auto merge of #15544 - servo:RootedTraceable-dict, r=nox

Root dictionaries that contain any or object.

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15544)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-02-16 02:03:54 -08:00 committed by GitHub
commit 0cc6d3e997
18 changed files with 206 additions and 69 deletions

2
Cargo.lock generated
View file

@ -1303,7 +1303,7 @@ dependencies = [
[[package]]
name = "js"
version = "0.1.4"
source = "git+https://github.com/servo/rust-mozjs#b391ec674babe4a3955f562635ea936180c7eea3"
source = "git+https://github.com/servo/rust-mozjs#93e59ef1263e451143d0ed431f1aa564ea101ab8"
dependencies = [
"cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -19,6 +19,7 @@ from WebIDL import (
IDLBuiltinType,
IDLNullValue,
IDLNullableType,
IDLObject,
IDLType,
IDLInterfaceMember,
IDLUndefinedValue,
@ -581,11 +582,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
If isDefinitelyObject is True, that means we know the value
isObject() and we have no need to recheck that.
if isMember is True, we're being converted from a property of some
JS object, not from an actual method argument, so we can't rely on
our jsval being rooted or outliving us in any way. Any caller
passing true needs to ensure that it is handled correctly in
typeIsSequenceOrHasSequenceMember.
isMember is `False`, "Dictionary", "Union" or "Variadic", and affects
whether this function returns code suitable for an on-stack rooted binding
or suitable for storing in an appropriate larger structure.
invalidEnumValueFatal controls whether an invalid enum value conversion
attempt will throw (if true) or simply return without doing anything (if
@ -1033,33 +1032,33 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if type.isAny():
assert not isEnforceRange and not isClamp
assert isMember != "Union"
declType = ""
default = ""
if isMember == "Dictionary":
# TODO: Need to properly root dictionaries
# https://github.com/servo/servo/issues/6381
declType = CGGeneric("JSVal")
declType = CGGeneric("Heap<JSVal>")
if defaultValue is None:
default = None
elif isinstance(defaultValue, IDLNullValue):
default = "NullValue()"
default = "Heap::new(NullValue())"
elif isinstance(defaultValue, IDLUndefinedValue):
default = "UndefinedValue()"
default = "Heap::new(UndefinedValue())"
else:
raise TypeError("Can't handle non-null, non-undefined default value here")
return handleOptional("Heap::new(${val}.get())", declType, default)
declType = CGGeneric("HandleValue")
if defaultValue is None:
default = None
elif isinstance(defaultValue, IDLNullValue):
default = "HandleValue::null()"
elif isinstance(defaultValue, IDLUndefinedValue):
default = "HandleValue::undefined()"
else:
declType = CGGeneric("HandleValue")
if defaultValue is None:
default = None
elif isinstance(defaultValue, IDLNullValue):
default = "HandleValue::null()"
elif isinstance(defaultValue, IDLUndefinedValue):
default = "HandleValue::undefined()"
else:
raise TypeError("Can't handle non-null, non-undefined default value here")
raise TypeError("Can't handle non-null, non-undefined default value here")
return handleOptional("${val}", declType, default)
@ -1068,13 +1067,22 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
# TODO: Need to root somehow
# https://github.com/servo/servo/issues/6382
declType = CGGeneric("*mut JSObject")
default = "ptr::null_mut()"
templateBody = wrapObjectTemplate("${val}.get().to_object()",
"ptr::null_mut()",
default,
isDefinitelyObject, type, failureCode)
if isMember in ("Dictionary", "Union"):
declType = CGGeneric("Heap<*mut JSObject>")
templateBody = "Heap::new(%s)" % templateBody
default = "Heap::new(%s)" % default
else:
# TODO: Need to root somehow
# https://github.com/servo/servo/issues/6382
declType = CGGeneric("*mut JSObject")
return handleOptional(templateBody, declType,
handleDefaultNull("ptr::null_mut()"))
handleDefaultNull(default))
if type.isDictionary():
# There are no nullable dictionaries
@ -1083,15 +1091,21 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
typeName = "%s::%s" % (CGDictionary.makeModuleName(type.inner),
CGDictionary.makeDictionaryName(type.inner))
declType = CGGeneric(typeName)
template = ("match %s::new(cx, ${val}) {\n"
empty = "%s::empty(cx)" % typeName
if isMember != "Dictionary" and type_needs_tracing(type):
declType = CGTemplatedType("RootedTraceableBox", declType)
empty = "RootedTraceableBox::new(%s)" % empty
template = ("match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n"
" Ok(ConversionResult::Success(dictionary)) => dictionary,\n"
" Ok(ConversionResult::Failure(error)) => {\n"
"%s\n"
" }\n"
" _ => { %s },\n"
"}" % (typeName, indent(failOrPropagate, 8), exceptionCode))
"}" % (indent(failOrPropagate, 8), exceptionCode))
return handleOptional(template, declType, handleDefaultNull("%s::empty(cx)" % typeName))
return handleOptional(template, declType, handleDefaultNull(empty))
if type.isVoid():
# This one only happens for return values, and its easy: Just
@ -2233,6 +2247,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
'dom::types::*',
'js::error::throw_type_error',
'js::jsapi::HandleValue',
'js::jsapi::Heap',
'js::jsapi::JSContext',
'js::jsapi::JSObject',
'js::jsapi::MutableHandleValue',
@ -3139,7 +3154,7 @@ class CGCallGenerator(CGThing):
args = CGList([CGGeneric(arg) for arg in argsPre], ", ")
for (a, name) in arguments:
# XXXjdm Perhaps we should pass all nontrivial types by borrowed pointer
if a.type.isDictionary():
if a.type.isDictionary() and not type_needs_tracing(a.type):
name = "&" + name
args.append(CGGeneric(name))
@ -4052,14 +4067,15 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
typeName = builtinNames[type.tag()]
elif type.isObject():
name = type.name
typeName = "*mut JSObject"
typeName = "Heap<*mut JSObject>"
else:
raise TypeError("Can't handle %s in unions yet" % type)
info = getJSToNativeConversionInfo(
type, descriptorProvider, failureCode="return Ok(None);",
exceptionCode='return Err(());',
isDefinitelyObject=True)
isDefinitelyObject=True,
isMember="Union")
template = info.template
jsConversion = string.Template(template).substitute({
@ -4094,6 +4110,7 @@ class CGUnionStruct(CGThing):
% (self.type, v["name"]) for v in templateVars
]
return ("""\
#[derive(JSTraceable)]
pub enum %s {
%s
}
@ -5567,6 +5584,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
'dom::bindings::utils::trace_global',
'dom::bindings::trace::JSTraceable',
'dom::bindings::trace::RootedTraceable',
'dom::bindings::trace::RootedTraceableBox',
'dom::bindings::callback::CallSetup',
'dom::bindings::callback::CallbackContainer',
'dom::bindings::callback::CallbackInterface',
@ -5872,6 +5890,7 @@ class CGDictionary(CGThing):
for m in self.memberInfo]
return (string.Template(
"#[derive(JSTraceable)]\n"
"pub struct ${selfName} {\n" +
"${inheritance}" +
"\n".join(memberDecls) + "\n" +
@ -5995,8 +6014,6 @@ class CGDictionary(CGThing):
default = info.default
replacements = {"val": "rval.handle()"}
conversion = string.Template(templateBody).substitute(replacements)
if memberType.isAny():
conversion = "%s.get()" % conversion
assert (member.defaultValue is None) == (default is None)
if not member.optional:
@ -6154,6 +6171,45 @@ class CGBindingRoot(CGThing):
return stripTrailingWhitespace(self.root.define())
def type_needs_tracing(t):
assert isinstance(t, IDLObject), (t, type(t))
if t.isType():
if isinstance(t, IDLWrapperType):
return type_needs_tracing(t.inner)
if t.nullable():
return type_needs_tracing(t.inner)
if t.isAny():
return True
if t.isObject():
return True
if t.isSequence():
return type_needs_tracing(t.inner)
return False
if t.isDictionary():
if t.parent and type_needs_tracing(t.parent):
return True
if any(type_needs_tracing(member.type) for member in t.members):
return True
return False
if t.isInterface():
return False
if t.isEnum():
return False
assert False, (t, type(t))
def argument_type(descriptorProvider, ty, optional=False, defaultValue=None, variadic=False):
info = getJSToNativeConversionInfo(
ty, descriptorProvider, isArgument=True)
@ -6167,7 +6223,7 @@ def argument_type(descriptorProvider, ty, optional=False, defaultValue=None, var
elif optional and not defaultValue:
declType = CGWrapper(declType, pre="Option<", post=">")
if ty.isDictionary():
if ty.isDictionary() and not type_needs_tracing(ty):
declType = CGWrapper(declType, pre="&")
return declType.define()

View file

@ -37,6 +37,7 @@ use dom::bindings::js::Root;
use dom::bindings::num::Finite;
use dom::bindings::reflector::{DomObject, Reflector};
use dom::bindings::str::{ByteString, DOMString, USVString};
use dom::bindings::trace::{JSTraceable, RootedTraceableBox};
use dom::bindings::utils::DOMClass;
use js;
pub use js::conversions::{FromJSValConvertible, ToJSValConvertible, ConversionResult};
@ -117,6 +118,22 @@ impl <T: DomObject + IDLInterface> FromJSValConvertible for Root<T> {
}
}
impl <T: FromJSValConvertible + JSTraceable> FromJSValConvertible for RootedTraceableBox<T> {
type Config = T::Config;
unsafe fn from_jsval(cx: *mut JSContext,
value: HandleValue,
config: Self::Config)
-> Result<ConversionResult<Self>, ()> {
T::from_jsval(cx, value, config).map(|result| {
match result {
ConversionResult::Success(v) => ConversionResult::Success(RootedTraceableBox::new(v)),
ConversionResult::Failure(e) => ConversionResult::Failure(e),
}
})
}
}
/// Convert `id` to a `DOMString`, assuming it is string-valued.
///
/// Handling of invalid UTF-16 in strings depends on the relevant option.

View file

@ -15,7 +15,7 @@ use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::trace::JSTraceable;
use dom::globalscope::GlobalScope;
use js::conversions::ToJSValConvertible;
use js::jsapi::{HandleValue, JSContext, JSObject, MutableHandleObject};
use js::jsapi::{HandleValue, Heap, JSContext, JSObject, MutableHandleObject};
use js::jsval::UndefinedValue;
use std::cell::Cell;
use std::ptr;
@ -116,7 +116,7 @@ fn dict_return(cx: *mut JSContext,
value: HandleValue) -> Fallible<()> {
let mut dict = unsafe { IterableKeyOrValueResult::empty(cx) };
dict.done = done;
dict.value = value.get();
dict.value.set(value.get());
rooted!(in(cx) let mut dict_value = UndefinedValue());
unsafe {
dict.to_jsval(cx, dict_value.handle_mut());
@ -131,7 +131,7 @@ fn key_and_value_return(cx: *mut JSContext,
value: HandleValue) -> Fallible<()> {
let mut dict = unsafe { IterableKeyAndValueResult::empty(cx) };
dict.done = false;
dict.value = Some(vec![key.get(), value.get()]);
dict.value = Some(vec![Heap::new(key.get()), Heap::new(value.get())]);
rooted!(in(cx) let mut dict_value = UndefinedValue());
unsafe {
dict.to_jsval(cx, dict_value.handle_mut());

View file

@ -642,3 +642,9 @@ impl<T: DomObject> Drop for Root<T> {
}
}
}
unsafe impl<T: DomObject> JSTraceable for Root<T> {
unsafe fn trace(&self, _: *mut JSTracer) {
// Already traced.
}
}

View file

@ -23,7 +23,7 @@ use std::collections::HashMap;
use std::ops::Deref;
/// The `MozMap` (open-ended dictionary) type.
#[derive(Clone)]
#[derive(Clone, JSTraceable)]
pub struct MozMap<T> {
map: HashMap<DOMString, T>,
}

View file

@ -653,6 +653,61 @@ impl<'a, T: JSTraceable + 'static> Drop for RootedTraceable<'a, T> {
}
}
/// Roots any JSTraceable thing
///
/// If you have a valid DomObject, use Root.
/// If you have GC things like *mut JSObject or JSVal, use rooted!.
/// If you have an arbitrary number of DomObjects to root, use rooted_vec!.
/// If you know what you're doing, use this.
pub struct RootedTraceableBox<T: 'static + JSTraceable> {
ptr: *mut T,
}
unsafe impl<T: JSTraceable + 'static> JSTraceable for RootedTraceableBox<T> {
unsafe fn trace(&self, tracer: *mut JSTracer) {
(*self.ptr).trace(tracer);
}
}
impl<T: JSTraceable + 'static> RootedTraceableBox<T> {
/// Root a JSTraceable thing for the life of this RootedTraceable
pub fn new(traceable: T) -> RootedTraceableBox<T> {
let traceable = Box::into_raw(box traceable);
unsafe {
RootedTraceableSet::add(traceable);
}
RootedTraceableBox {
ptr: traceable,
}
}
}
impl<T: JSTraceable> Deref for RootedTraceableBox<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
&*self.ptr
}
}
}
impl<T: JSTraceable> DerefMut for RootedTraceableBox<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
&mut *self.ptr
}
}
}
impl<T: JSTraceable + 'static> Drop for RootedTraceableBox<T> {
fn drop(&mut self) {
unsafe {
RootedTraceableSet::remove(self.ptr);
let _ = Box::from_raw(self.ptr);
}
}
}
/// A vector of items to be rooted with `RootedVec`.
/// Guaranteed to be empty when not rooted.
/// Usage: `rooted_vec!(let mut v);` or if you have an

View file

@ -10,6 +10,7 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{MutHeapJSVal, Root};
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::bindings::trace::RootedTraceableBox;
use dom::event::Event;
use dom::globalscope::GlobalScope;
use js::jsapi::{HandleValue, JSContext};
@ -51,13 +52,13 @@ impl CustomEvent {
#[allow(unsafe_code)]
pub fn Constructor(global: &GlobalScope,
type_: DOMString,
init: &CustomEventBinding::CustomEventInit)
init: RootedTraceableBox<CustomEventBinding::CustomEventInit>)
-> Fallible<Root<CustomEvent>> {
Ok(CustomEvent::new(global,
Atom::from(type_),
init.parent.bubbles,
init.parent.cancelable,
unsafe { HandleValue::from_marked_location(&init.detail) }))
init.detail.handle()))
}
fn init_custom_event(&self,

View file

@ -11,6 +11,7 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{MutHeapJSVal, Root};
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::bindings::trace::RootedTraceableBox;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::globalscope::GlobalScope;
use js::jsapi::{HandleValue, JSContext};
@ -72,7 +73,8 @@ impl ErrorEvent {
pub fn Constructor(global: &GlobalScope,
type_: DOMString,
init: &ErrorEventBinding::ErrorEventInit) -> Fallible<Root<ErrorEvent>>{
init: RootedTraceableBox<ErrorEventBinding::ErrorEventInit>)
-> Fallible<Root<ErrorEvent>>{
let msg = match init.message.as_ref() {
Some(message) => message.clone(),
None => DOMString::new(),
@ -91,9 +93,6 @@ impl ErrorEvent {
let cancelable = EventCancelable::from(init.parent.cancelable);
// Dictionaries need to be rooted
// https://github.com/servo/servo/issues/6381
rooted!(in(global.get_cx()) let error = init.error);
let event = ErrorEvent::new(
global,
Atom::from(type_),
@ -103,7 +102,7 @@ impl ErrorEvent {
file_name,
line_num,
col_num,
error.handle());
init.error.handle());
Ok(event)
}

View file

@ -9,6 +9,7 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::bindings::trace::RootedTraceableBox;
use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::extendableevent::ExtendableEvent;
@ -47,15 +48,14 @@ impl ExtendableMessageEvent {
pub fn Constructor(worker: &ServiceWorkerGlobalScope,
type_: DOMString,
init: &ExtendableMessageEventBinding::ExtendableMessageEventInit)
init: RootedTraceableBox<ExtendableMessageEventBinding::ExtendableMessageEventInit>)
-> Fallible<Root<ExtendableMessageEvent>> {
let global = worker.upcast::<GlobalScope>();
rooted!(in(global.get_cx()) let data = init.data);
let ev = ExtendableMessageEvent::new(global,
Atom::from(type_),
init.parent.parent.bubbles,
init.parent.parent.cancelable,
data.handle(),
init.data.handle(),
init.origin.clone().unwrap(),
init.lastEventId.clone().unwrap());
Ok(ev)

View file

@ -344,7 +344,7 @@ impl FileReaderMethods for FileReader {
FileReaderResult::String(ref string) =>
StringOrObject::String(string.clone()),
FileReaderResult::ArrayBuffer(ref arr_buffer) => {
StringOrObject::Object((*arr_buffer.ptr.get()).to_object())
StringOrObject::Object(Heap::new((*arr_buffer.ptr.get()).to_object()))
}
})
}

View file

@ -10,6 +10,7 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::bindings::trace::RootedTraceableBox;
use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
@ -60,16 +61,13 @@ impl MessageEvent {
pub fn Constructor(global: &GlobalScope,
type_: DOMString,
init: &MessageEventBinding::MessageEventInit)
init: RootedTraceableBox<MessageEventBinding::MessageEventInit>)
-> Fallible<Root<MessageEvent>> {
// Dictionaries need to be rooted
// https://github.com/servo/servo/issues/6381
rooted!(in(global.get_cx()) let data = init.data);
let ev = MessageEvent::new(global,
Atom::from(type_),
init.parent.bubbles,
init.parent.cancelable,
data.handle(),
init.data.handle(),
init.origin.clone(),
init.lastEventId.clone());
Ok(ev)

View file

@ -10,6 +10,7 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{MutHeapJSVal, Root};
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::bindings::trace::RootedTraceableBox;
use dom::event::Event;
use dom::window::Window;
use js::jsapi::{HandleValue, JSContext};
@ -53,16 +54,15 @@ impl PopStateEvent {
ev
}
#[allow(unsafe_code)]
pub fn Constructor(window: &Window,
type_: DOMString,
init: &PopStateEventBinding::PopStateEventInit)
init: RootedTraceableBox<PopStateEventBinding::PopStateEventInit>)
-> Fallible<Root<PopStateEvent>> {
Ok(PopStateEvent::new(window,
Atom::from(type_),
init.parent.bubbles,
init.parent.cancelable,
unsafe { HandleValue::from_marked_location(&init.state) }))
init.state.handle()))
}
}

View file

@ -20,6 +20,7 @@ use dom::bindings::error::{Error, Fallible};
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::str::{ByteString, DOMString, USVString};
use dom::bindings::trace::RootedTraceableBox;
use dom::globalscope::GlobalScope;
use dom::headers::{Guard, Headers};
use dom::promise::Promise;
@ -80,7 +81,7 @@ impl Request {
// https://fetch.spec.whatwg.org/#dom-request
pub fn Constructor(global: &GlobalScope,
input: RequestInfo,
init: &RequestInit)
init: RootedTraceableBox<RequestInit>)
-> Fallible<Root<Request>> {
// Step 1
let temporary_request: NetTraitsRequest;
@ -139,12 +140,12 @@ impl Request {
// TODO: `environment settings object` is not implemented in Servo yet.
// Step 10
if !init.window.is_undefined() && !init.window.is_null() {
if !init.window.handle().is_null_or_undefined() {
return Err(Error::Type("Window is present and is not null".to_string()))
}
// Step 11
if !init.window.is_undefined() {
if !init.window.handle().is_undefined() {
window = Window::NoWindow;
}
@ -179,7 +180,7 @@ impl Request {
init.redirect.is_some() ||
init.referrer.is_some() ||
init.referrerPolicy.is_some() ||
!init.window.is_undefined() {
!init.window.handle().is_undefined() {
// Step 13.1
if request.mode == NetTraitsRequestMode::Navigate {
return Err(Error::Type(
@ -311,7 +312,7 @@ impl Request {
if let Some(possible_header) = init.headers.as_ref() {
match possible_header {
&HeadersInit::Headers(ref init_headers) => {
headers_copy = init_headers.clone();
headers_copy = Root::from_ref(&*init_headers);
}
&HeadersInit::ByteStringSequenceSequence(ref init_sequence) => {
try!(headers_copy.fill(Some(

View file

@ -27,13 +27,14 @@ use dom::bindings::num::Finite;
use dom::bindings::refcounted::TrustedPromise;
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::str::{ByteString, DOMString, USVString};
use dom::bindings::trace::RootedTraceableBox;
use dom::bindings::weakref::MutableWeakRef;
use dom::blob::{Blob, BlobImpl};
use dom::globalscope::GlobalScope;
use dom::promise::Promise;
use dom::promisenativehandler::{PromiseNativeHandler, Callback};
use dom::url::URL;
use js::jsapi::{HandleObject, HandleValue, JSContext, JSObject, JSAutoCompartment};
use js::jsapi::{HandleObject, HandleValue, Heap, JSContext, JSObject, JSAutoCompartment};
use js::jsapi::{JS_NewPlainObject, JS_NewUint8ClampedArray};
use js::jsval::{JSVal, NullValue};
use script_traits::MsDuration;
@ -338,12 +339,12 @@ impl TestBindingMethods for TestBinding {
fn ReceiveNullableSequence(&self) -> Option<Vec<i32>> { Some(vec![1]) }
fn ReceiveTestDictionaryWithSuccessOnKeyword(&self) -> TestDictionary {
TestDictionary {
anyValue: NullValue(),
anyValue: Heap::new(NullValue()),
booleanValue: None,
byteValue: None,
dict: TestDictionaryDefaults {
UnrestrictedDoubleValue: 0.0,
anyValue: NullValue(),
anyValue: Heap::new(NullValue()),
booleanValue: false,
bytestringValue: ByteString::new(vec![]),
byteValue: 0,
@ -359,7 +360,7 @@ impl TestBindingMethods for TestBinding {
nullableFloatValue: None,
nullableLongLongValue: None,
nullableLongValue: None,
nullableObjectValue: ptr::null_mut(),
nullableObjectValue: Heap::new(ptr::null_mut()),
nullableOctetValue: None,
nullableShortValue: None,
nullableStringValue: None,
@ -402,7 +403,7 @@ impl TestBindingMethods for TestBinding {
}
}
fn DictMatchesPassedValues(&self, arg: &TestDictionary) -> bool {
fn DictMatchesPassedValues(&self, arg: RootedTraceableBox<TestDictionary>) -> bool {
arg.type_.as_ref().map(|s| s == "success").unwrap_or(false) &&
arg.nonRequiredNullable.is_none() &&
arg.nonRequiredNullable2 == Some(None)

View file

@ -26,6 +26,7 @@ use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::DomObject;
use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::trace::RootedTraceableBox;
use dom::bindings::utils::{GlobalStaticData, WindowProxyHandler};
use dom::bluetooth::BluetoothExtraPermissionData;
use dom::browsingcontext::BrowsingContext;
@ -921,7 +922,7 @@ impl WindowMethods for Window {
#[allow(unrooted_must_root)]
// https://fetch.spec.whatwg.org/#fetch-method
fn Fetch(&self, input: RequestOrUSVString, init: &RequestInit) -> Rc<Promise> {
fn Fetch(&self, input: RequestOrUSVString, init: RootedTraceableBox<RequestInit>) -> Rc<Promise> {
fetch::Fetch(&self.upcast(), input, init)
}

View file

@ -14,6 +14,7 @@ use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::reflector::DomObject;
use dom::bindings::settings_stack::AutoEntryScript;
use dom::bindings::str::DOMString;
use dom::bindings::trace::RootedTraceableBox;
use dom::crypto::Crypto;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::globalscope::GlobalScope;
@ -314,7 +315,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
#[allow(unrooted_must_root)]
// https://fetch.spec.whatwg.org/#fetch-method
fn Fetch(&self, input: RequestOrUSVString, init: &RequestInit) -> Rc<Promise> {
fn Fetch(&self, input: RequestOrUSVString, init: RootedTraceableBox<RequestInit>) -> Rc<Promise> {
fetch::Fetch(self.upcast(), input, init)
}
}

View file

@ -10,6 +10,7 @@ use dom::bindings::error::Error;
use dom::bindings::js::Root;
use dom::bindings::refcounted::{Trusted, TrustedPromise};
use dom::bindings::reflector::DomObject;
use dom::bindings::trace::RootedTraceableBox;
use dom::globalscope::GlobalScope;
use dom::headers::Guard;
use dom::promise::Promise;
@ -68,7 +69,7 @@ fn request_init_from_request(request: NetTraitsRequest) -> NetTraitsRequestInit
// https://fetch.spec.whatwg.org/#fetch-method
#[allow(unrooted_must_root)]
pub fn Fetch(global: &GlobalScope, input: RequestInfo, init: &RequestInit) -> Rc<Promise> {
pub fn Fetch(global: &GlobalScope, input: RequestInfo, init: RootedTraceableBox<RequestInit>) -> Rc<Promise> {
let core_resource_thread = global.core_resource_thread();
// Step 1