Use TimerHandler IDL union type

This commit is contained in:
Kagami Sascha Rosylight 2019-11-05 23:55:15 +09:00
parent 2aca5c82e4
commit 1b22c10483
5 changed files with 54 additions and 97 deletions

View file

@ -2410,6 +2410,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
'crate::dom::bindings::conversions::StringificationBehavior', 'crate::dom::bindings::conversions::StringificationBehavior',
'crate::dom::bindings::conversions::root_from_handlevalue', 'crate::dom::bindings::conversions::root_from_handlevalue',
'std::ptr::NonNull', 'std::ptr::NonNull',
'std::rc::Rc',
'crate::dom::bindings::record::Record', 'crate::dom::bindings::record::Record',
'crate::dom::bindings::num::Finite', 'crate::dom::bindings::num::Finite',
'crate::dom::bindings::root::DomRoot', 'crate::dom::bindings::root::DomRoot',
@ -2423,6 +2424,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
'js::error::throw_type_error', 'js::error::throw_type_error',
'js::rust::HandleValue', 'js::rust::HandleValue',
'js::jsapi::Heap', 'js::jsapi::Heap',
'js::jsapi::IsCallable',
'js::jsapi::JSContext', 'js::jsapi::JSContext',
'js::jsapi::JSObject', 'js::jsapi::JSObject',
'js::rust::MutableHandleValue', 'js::rust::MutableHandleValue',
@ -2438,9 +2440,10 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
if not t.isUnion(): if not t.isUnion():
continue continue
for memberType in t.flatMemberTypes: for memberType in t.flatMemberTypes:
if memberType.isDictionary() or memberType.isEnum(): if memberType.isDictionary() or memberType.isEnum() or memberType.isCallback():
memberModule = getModuleFromObject(memberType) memberModule = getModuleFromObject(memberType)
memberName = memberType.inner.identifier.name memberName = (memberType.callback.identifier.name
if memberType.isCallback() else memberType.inner.identifier.name)
imports.append("%s::%s" % (memberModule, memberName)) imports.append("%s::%s" % (memberModule, memberName))
if memberType.isEnum(): if memberType.isEnum():
imports.append("%s::%sValues" % (memberModule, memberName)) imports.append("%s::%sValues" % (memberModule, memberName))
@ -4380,6 +4383,9 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
elif is_typed_array(type): elif is_typed_array(type):
name = type.name name = type.name
typeName = "typedarray::Heap" + name typeName = "typedarray::Heap" + name
elif type.isCallback():
name = type.name
typeName = name
else: else:
raise TypeError("Can't handle %s in unions yet" % type) raise TypeError("Can't handle %s in unions yet" % type)
@ -4418,12 +4424,19 @@ class CGUnionStruct(CGThing):
return False return False
def define(self): def define(self):
def getTypeWrapper(t):
if type_needs_tracing(t):
return "RootedTraceableBox"
if t.isCallback():
return "Rc"
return ""
templateVars = map(lambda t: (getUnionTypeTemplateVars(t, self.descriptorProvider), templateVars = map(lambda t: (getUnionTypeTemplateVars(t, self.descriptorProvider),
type_needs_tracing(t)), getTypeWrapper(t)),
self.type.flatMemberTypes) self.type.flatMemberTypes)
enumValues = [ enumValues = [
" %s(%s)," % (v["name"], "RootedTraceableBox<%s>" % v["typeName"] if trace else v["typeName"]) " %s(%s)," % (v["name"], "%s<%s>" % (wrapper, v["typeName"]) if wrapper else v["typeName"])
for (v, trace) in templateVars for (v, wrapper) in templateVars
] ]
enumConversions = [ enumConversions = [
" %s::%s(ref inner) => inner.to_jsval(cx, rval)," " %s::%s(ref inner) => inner.to_jsval(cx, rval),"
@ -4506,7 +4519,8 @@ class CGUnionConversionStruct(CGThing):
callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes) callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes)
if len(callbackMemberTypes) > 0: if len(callbackMemberTypes) > 0:
assert len(callbackMemberTypes) == 1 assert len(callbackMemberTypes) == 1
raise TypeError("Can't handle callbacks in unions.") typeName = callbackMemberTypes[0].name
callbackObject = CGGeneric(get_match(typeName))
else: else:
callbackObject = None callbackObject = None
@ -4537,7 +4551,7 @@ class CGUnionConversionStruct(CGThing):
else: else:
mozMapObject = None mozMapObject = None
hasObjectTypes = object or interfaceObject or arrayObject or dateObject or mozMapObject hasObjectTypes = object or interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject
if hasObjectTypes: if hasObjectTypes:
# "object" is not distinguishable from other types # "object" is not distinguishable from other types
assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject) assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject)
@ -4548,6 +4562,8 @@ class CGUnionConversionStruct(CGThing):
templateBody.append(interfaceObject) templateBody.append(interfaceObject)
if arrayObject: if arrayObject:
templateBody.append(arrayObject) templateBody.append(arrayObject)
if callbackObject:
templateBody.append(callbackObject)
if mozMapObject: if mozMapObject:
templateBody.append(mozMapObject) templateBody.append(mozMapObject)
conversions.append(CGIfWrapper("value.get().is_object()", templateBody)) conversions.append(CGIfWrapper("value.get().is_object()", templateBody))
@ -4608,6 +4624,8 @@ class CGUnionConversionStruct(CGThing):
actualType = templateVars["typeName"] actualType = templateVars["typeName"]
if type_needs_tracing(t): if type_needs_tracing(t):
actualType = "RootedTraceableBox<%s>" % actualType actualType = "RootedTraceableBox<%s>" % actualType
if t.isCallback():
actualType = "Rc<%s>" % actualType
returnType = "Result<Option<%s>, ()>" % actualType returnType = "Result<Option<%s>, ()>" % actualType
jsConversion = templateVars["jsConversion"] jsConversion = templateVars["jsConversion"]

View file

@ -4,8 +4,7 @@
// https://html.spec.whatwg.org/multipage/#windoworworkerglobalscope // https://html.spec.whatwg.org/multipage/#windoworworkerglobalscope
// FIXME(nox): https://github.com/servo/servo/issues/20700 typedef (DOMString or Function) TimerHandler;
// typedef (DOMString or Function) TimerHandler;
[Exposed=(Window,Worker)] [Exposed=(Window,Worker)]
interface mixin WindowOrWorkerGlobalScope { interface mixin WindowOrWorkerGlobalScope {
@ -16,13 +15,9 @@ interface mixin WindowOrWorkerGlobalScope {
[Throws] DOMString atob(DOMString data); [Throws] DOMString atob(DOMString data);
// timers // timers
// FIXME(nox): https://github.com/servo/servo/issues/20700 long setTimeout(TimerHandler handler, optional long timeout = 0, any... arguments);
long setTimeout(Function handler, optional long timeout = 0, any... arguments);
long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
void clearTimeout(optional long handle = 0); void clearTimeout(optional long handle = 0);
// FIXME(nox): https://github.com/servo/servo/issues/20700 long setInterval(TimerHandler handler, optional long timeout = 0, any... arguments);
long setInterval(Function handler, optional long timeout = 0, any... arguments);
long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
void clearInterval(optional long handle = 0); void clearInterval(optional long handle = 0);
// ImageBitmap // ImageBitmap

View file

@ -7,7 +7,6 @@ use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::{ use crate::dom::bindings::codegen::Bindings::DocumentBinding::{
DocumentMethods, DocumentReadyState, DocumentMethods, DocumentReadyState,
}; };
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
use crate::dom::bindings::codegen::Bindings::HistoryBinding::HistoryBinding::HistoryMethods; use crate::dom::bindings::codegen::Bindings::HistoryBinding::HistoryBinding::HistoryMethods;
use crate::dom::bindings::codegen::Bindings::MediaQueryListBinding::MediaQueryListBinding::MediaQueryListMethods; use crate::dom::bindings::codegen::Bindings::MediaQueryListBinding::MediaQueryListBinding::MediaQueryListMethods;
use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::PermissionState; use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::PermissionState;
@ -16,7 +15,7 @@ use crate::dom::bindings::codegen::Bindings::WindowBinding::{
self, FrameRequestCallback, WindowMethods, WindowPostMessageOptions, self, FrameRequestCallback, WindowMethods, WindowPostMessageOptions,
}; };
use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions}; use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
use crate::dom::bindings::codegen::UnionTypes::RequestOrUSVString; use crate::dom::bindings::codegen::UnionTypes::{RequestOrUSVString, StringOrFunction};
use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite; use crate::dom::bindings::num::Finite;
@ -817,28 +816,16 @@ impl WindowMethods for Window {
fn SetTimeout( fn SetTimeout(
&self, &self,
_cx: JSContext, _cx: JSContext,
callback: Rc<Function>, callback: StringOrFunction,
timeout: i32, timeout: i32,
args: Vec<HandleValue>, args: Vec<HandleValue>,
) -> i32 { ) -> i32 {
let callback = match callback {
StringOrFunction::String(i) => TimerCallback::StringTimerCallback(i),
StringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
};
self.upcast::<GlobalScope>().set_timeout_or_interval( self.upcast::<GlobalScope>().set_timeout_or_interval(
TimerCallback::FunctionTimerCallback(callback), callback,
args,
timeout,
IsInterval::NonInterval,
)
}
// https://html.spec.whatwg.org/multipage/#dom-windowtimers-settimeout
fn SetTimeout_(
&self,
_cx: JSContext,
callback: DOMString,
timeout: i32,
args: Vec<HandleValue>,
) -> i32 {
self.upcast::<GlobalScope>().set_timeout_or_interval(
TimerCallback::StringTimerCallback(callback),
args, args,
timeout, timeout,
IsInterval::NonInterval, IsInterval::NonInterval,
@ -855,28 +842,16 @@ impl WindowMethods for Window {
fn SetInterval( fn SetInterval(
&self, &self,
_cx: JSContext, _cx: JSContext,
callback: Rc<Function>, callback: StringOrFunction,
timeout: i32, timeout: i32,
args: Vec<HandleValue>, args: Vec<HandleValue>,
) -> i32 { ) -> i32 {
let callback = match callback {
StringOrFunction::String(i) => TimerCallback::StringTimerCallback(i),
StringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
};
self.upcast::<GlobalScope>().set_timeout_or_interval( self.upcast::<GlobalScope>().set_timeout_or_interval(
TimerCallback::FunctionTimerCallback(callback), callback,
args,
timeout,
IsInterval::Interval,
)
}
// https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
fn SetInterval_(
&self,
_cx: JSContext,
callback: DOMString,
timeout: i32,
args: Vec<HandleValue>,
) -> i32 {
self.upcast::<GlobalScope>().set_timeout_or_interval(
TimerCallback::StringTimerCallback(callback),
args, args,
timeout, timeout,
IsInterval::Interval, IsInterval::Interval,

View file

@ -4,11 +4,10 @@
use crate::compartments::InCompartment; use crate::compartments::InCompartment;
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
use crate::dom::bindings::codegen::Bindings::RequestBinding::RequestInit; use crate::dom::bindings::codegen::Bindings::RequestBinding::RequestInit;
use crate::dom::bindings::codegen::Bindings::WorkerBinding::WorkerType; use crate::dom::bindings::codegen::Bindings::WorkerBinding::WorkerType;
use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods; use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use crate::dom::bindings::codegen::UnionTypes::RequestOrUSVString; use crate::dom::bindings::codegen::UnionTypes::{RequestOrUSVString, StringOrFunction};
use crate::dom::bindings::error::{report_pending_exception, Error, ErrorResult, Fallible}; use crate::dom::bindings::error::{report_pending_exception, Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::DomObject;
@ -297,28 +296,16 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
fn SetTimeout( fn SetTimeout(
&self, &self,
_cx: JSContext, _cx: JSContext,
callback: Rc<Function>, callback: StringOrFunction,
timeout: i32, timeout: i32,
args: Vec<HandleValue>, args: Vec<HandleValue>,
) -> i32 { ) -> i32 {
let callback = match callback {
StringOrFunction::String(i) => TimerCallback::StringTimerCallback(i),
StringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
};
self.upcast::<GlobalScope>().set_timeout_or_interval( self.upcast::<GlobalScope>().set_timeout_or_interval(
TimerCallback::FunctionTimerCallback(callback), callback,
args,
timeout,
IsInterval::NonInterval,
)
}
// https://html.spec.whatwg.org/multipage/#dom-windowtimers-settimeout
fn SetTimeout_(
&self,
_cx: JSContext,
callback: DOMString,
timeout: i32,
args: Vec<HandleValue>,
) -> i32 {
self.upcast::<GlobalScope>().set_timeout_or_interval(
TimerCallback::StringTimerCallback(callback),
args, args,
timeout, timeout,
IsInterval::NonInterval, IsInterval::NonInterval,
@ -335,28 +322,16 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
fn SetInterval( fn SetInterval(
&self, &self,
_cx: JSContext, _cx: JSContext,
callback: Rc<Function>, callback: StringOrFunction,
timeout: i32, timeout: i32,
args: Vec<HandleValue>, args: Vec<HandleValue>,
) -> i32 { ) -> i32 {
let callback = match callback {
StringOrFunction::String(i) => TimerCallback::StringTimerCallback(i),
StringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
};
self.upcast::<GlobalScope>().set_timeout_or_interval( self.upcast::<GlobalScope>().set_timeout_or_interval(
TimerCallback::FunctionTimerCallback(callback), callback,
args,
timeout,
IsInterval::Interval,
)
}
// https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
fn SetInterval_(
&self,
_cx: JSContext,
callback: DOMString,
timeout: i32,
args: Vec<HandleValue>,
) -> i32 {
self.upcast::<GlobalScope>().set_timeout_or_interval(
TimerCallback::StringTimerCallback(callback),
args, args,
timeout, timeout,
IsInterval::Interval, IsInterval::Interval,

View file

@ -1,6 +0,0 @@
[evil-spec-example.html]
type: testharness
expected: ERROR
[Interaction of setTimeout and WebIDL]
expected: NOTRUN