mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #10081 - jdm:interfacepref, r=nox
Support controlling interface and member visibility via preferences This was easier to throw together than per-attribute/method support, and it gets rid of some nonstandard properties from our globals. Fixes #7626. r? @Ms2ger <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10081) <!-- Reviewable:end -->
This commit is contained in:
commit
8255e74a61
28 changed files with 352 additions and 53 deletions
|
@ -1317,6 +1317,33 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
|
||||||
returnType)
|
returnType)
|
||||||
|
|
||||||
|
|
||||||
|
class MemberCondition:
|
||||||
|
"""
|
||||||
|
An object representing the condition for a member to actually be
|
||||||
|
exposed. Any of the arguments can be None. If not
|
||||||
|
None, they should have the following types:
|
||||||
|
|
||||||
|
pref: The name of the preference.
|
||||||
|
func: The name of the function.
|
||||||
|
"""
|
||||||
|
def __init__(self, pref=None, func=None):
|
||||||
|
assert pref is None or isinstance(pref, str)
|
||||||
|
assert func is None or isinstance(func, str)
|
||||||
|
self.pref = pref
|
||||||
|
|
||||||
|
def toFuncPtr(val):
|
||||||
|
if val is None:
|
||||||
|
return "None"
|
||||||
|
return "Some(%s)" % val
|
||||||
|
self.func = toFuncPtr(func)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return (self.pref == other.pref and self.func == other.func)
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
|
||||||
class PropertyDefiner:
|
class PropertyDefiner:
|
||||||
"""
|
"""
|
||||||
A common superclass for defining things on prototype objects.
|
A common superclass for defining things on prototype objects.
|
||||||
|
@ -1340,8 +1367,26 @@ class PropertyDefiner:
|
||||||
# up used via ResolveProperty or EnumerateProperties.
|
# up used via ResolveProperty or EnumerateProperties.
|
||||||
return self.generateArray(self.regular, self.variableName())
|
return self.generateArray(self.regular, self.variableName())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getStringAttr(member, name):
|
||||||
|
attr = member.getExtendedAttribute(name)
|
||||||
|
if attr is None:
|
||||||
|
return None
|
||||||
|
# It's a list of strings
|
||||||
|
assert len(attr) == 1
|
||||||
|
assert attr[0] is not None
|
||||||
|
return attr[0]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getControllingCondition(interfaceMember, descriptor):
|
||||||
|
return MemberCondition(
|
||||||
|
PropertyDefiner.getStringAttr(interfaceMember,
|
||||||
|
"Pref"),
|
||||||
|
PropertyDefiner.getStringAttr(interfaceMember,
|
||||||
|
"Func"))
|
||||||
|
|
||||||
def generatePrefableArray(self, array, name, specTemplate, specTerminator,
|
def generatePrefableArray(self, array, name, specTemplate, specTerminator,
|
||||||
specType, getDataTuple):
|
specType, getCondition, getDataTuple):
|
||||||
"""
|
"""
|
||||||
This method generates our various arrays.
|
This method generates our various arrays.
|
||||||
|
|
||||||
|
@ -1360,17 +1405,53 @@ class PropertyDefiner:
|
||||||
returns a tuple suitable for substitution into specTemplate.
|
returns a tuple suitable for substitution into specTemplate.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# We generate an all-encompassing list of lists of specs, with each sublist
|
||||||
|
# representing a group of members that share a common pref name. That will
|
||||||
|
# make sure the order of the properties as exposed on the interface and
|
||||||
|
# interface prototype objects does not change when pref control is added to
|
||||||
|
# members while still allowing us to define all the members in the smallest
|
||||||
|
# number of JSAPI calls.
|
||||||
assert len(array) != 0
|
assert len(array) != 0
|
||||||
|
# So we won't put a specTerminator at the very front of the list:
|
||||||
|
lastCondition = getCondition(array[0], self.descriptor)
|
||||||
specs = []
|
specs = []
|
||||||
|
currentSpecs = []
|
||||||
|
prefableSpecs = []
|
||||||
|
|
||||||
|
prefableTemplate = ' Prefable { pref: %s, specs: %s[%d], terminator: %s }'
|
||||||
|
|
||||||
|
def switchToCondition(props, condition):
|
||||||
|
prefableSpecs.append(prefableTemplate %
|
||||||
|
('Some("%s")' % condition.pref if condition.pref else 'None',
|
||||||
|
name + "_specs",
|
||||||
|
len(specs),
|
||||||
|
'true' if specTerminator else 'false'))
|
||||||
|
specs.append("&[\n" + ",\n".join(currentSpecs) + "]\n")
|
||||||
|
del currentSpecs[:]
|
||||||
|
|
||||||
for member in array:
|
for member in array:
|
||||||
specs.append(specTemplate % getDataTuple(member))
|
curCondition = getCondition(member, self.descriptor)
|
||||||
|
if lastCondition != curCondition:
|
||||||
|
# Terminate previous list
|
||||||
if specTerminator:
|
if specTerminator:
|
||||||
specs.append(specTerminator)
|
currentSpecs.append(specTerminator)
|
||||||
|
# And switch to our new pref
|
||||||
|
switchToCondition(self, lastCondition)
|
||||||
|
lastCondition = curCondition
|
||||||
|
# And the actual spec
|
||||||
|
currentSpecs.append(specTemplate % getDataTuple(member))
|
||||||
|
if specTerminator:
|
||||||
|
currentSpecs.append(specTerminator)
|
||||||
|
switchToCondition(self, lastCondition)
|
||||||
|
|
||||||
return (("const %s: &'static [%s] = &[\n" +
|
specsArray = ("const %s_specs: &'static [&'static[%s]] = &[\n" +
|
||||||
",\n".join(specs) + "\n" +
|
",\n".join(specs) + "\n" +
|
||||||
"];\n") % (name, specType))
|
"];\n") % (name, specType)
|
||||||
|
|
||||||
|
prefArray = ("const %s: &'static [Prefable<%s>] = &[\n" +
|
||||||
|
",\n".join(prefableSpecs) + "\n" +
|
||||||
|
"];\n") % (name, specType)
|
||||||
|
return specsArray + prefArray
|
||||||
|
|
||||||
|
|
||||||
# The length of a method is the minimum of the lengths of the
|
# The length of a method is the minimum of the lengths of the
|
||||||
|
@ -1404,14 +1485,17 @@ class MethodDefiner(PropertyDefiner):
|
||||||
methods = []
|
methods = []
|
||||||
self.regular = [{"name": m.identifier.name,
|
self.regular = [{"name": m.identifier.name,
|
||||||
"methodInfo": not m.isStatic(),
|
"methodInfo": not m.isStatic(),
|
||||||
"length": methodLength(m)} for m in methods]
|
"length": methodLength(m),
|
||||||
|
"condition": PropertyDefiner.getControllingCondition(m, descriptor)}
|
||||||
|
for m in methods]
|
||||||
|
|
||||||
# FIXME Check for an existing iterator on the interface first.
|
# FIXME Check for an existing iterator on the interface first.
|
||||||
if any(m.isGetter() and m.isIndexed() for m in methods):
|
if any(m.isGetter() and m.isIndexed() for m in methods):
|
||||||
self.regular.append({"name": '@@iterator',
|
self.regular.append({"name": '@@iterator',
|
||||||
"methodInfo": False,
|
"methodInfo": False,
|
||||||
"selfHostedName": "ArrayValues",
|
"selfHostedName": "ArrayValues",
|
||||||
"length": 0})
|
"length": 0,
|
||||||
|
"condition": MemberCondition()})
|
||||||
|
|
||||||
isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable"))
|
isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable"))
|
||||||
if not static and unforgeable == isUnforgeableInterface:
|
if not static and unforgeable == isUnforgeableInterface:
|
||||||
|
@ -1421,6 +1505,7 @@ class MethodDefiner(PropertyDefiner):
|
||||||
"name": "toString",
|
"name": "toString",
|
||||||
"nativeName": stringifier.identifier.name,
|
"nativeName": stringifier.identifier.name,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
|
"condition": PropertyDefiner.getControllingCondition(stringifier, descriptor)
|
||||||
})
|
})
|
||||||
self.unforgeable = unforgeable
|
self.unforgeable = unforgeable
|
||||||
|
|
||||||
|
@ -1428,6 +1513,9 @@ class MethodDefiner(PropertyDefiner):
|
||||||
if len(array) == 0:
|
if len(array) == 0:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def condition(m, d):
|
||||||
|
return m["condition"]
|
||||||
|
|
||||||
flags = "JSPROP_ENUMERATE"
|
flags = "JSPROP_ENUMERATE"
|
||||||
if self.unforgeable:
|
if self.unforgeable:
|
||||||
flags += " | JSPROP_PERMANENT | JSPROP_READONLY"
|
flags += " | JSPROP_PERMANENT | JSPROP_READONLY"
|
||||||
|
@ -1475,7 +1563,7 @@ class MethodDefiner(PropertyDefiner):
|
||||||
' selfHostedName: 0 as *const libc::c_char\n'
|
' selfHostedName: 0 as *const libc::c_char\n'
|
||||||
' }',
|
' }',
|
||||||
'JSFunctionSpec',
|
'JSFunctionSpec',
|
||||||
specData)
|
condition, specData)
|
||||||
|
|
||||||
|
|
||||||
class AttrDefiner(PropertyDefiner):
|
class AttrDefiner(PropertyDefiner):
|
||||||
|
@ -1553,7 +1641,7 @@ class AttrDefiner(PropertyDefiner):
|
||||||
' setter: JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }\n'
|
' setter: JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }\n'
|
||||||
' }',
|
' }',
|
||||||
'JSPropertySpec',
|
'JSPropertySpec',
|
||||||
specData)
|
PropertyDefiner.getControllingCondition, specData)
|
||||||
|
|
||||||
|
|
||||||
class ConstDefiner(PropertyDefiner):
|
class ConstDefiner(PropertyDefiner):
|
||||||
|
@ -1578,7 +1666,7 @@ class ConstDefiner(PropertyDefiner):
|
||||||
' ConstantSpec { name: %s, value: %s }',
|
' ConstantSpec { name: %s, value: %s }',
|
||||||
None,
|
None,
|
||||||
'ConstantSpec',
|
'ConstantSpec',
|
||||||
specData)
|
PropertyDefiner.getControllingCondition, specData)
|
||||||
|
|
||||||
# We'll want to insert the indent at the beginnings of lines, but we
|
# We'll want to insert the indent at the beginnings of lines, but we
|
||||||
# don't want to indent empty lines. So only indent lines that have a
|
# don't want to indent empty lines. So only indent lines that have a
|
||||||
|
@ -1925,7 +2013,10 @@ class CGList(CGThing):
|
||||||
"""
|
"""
|
||||||
def __init__(self, children, joiner=""):
|
def __init__(self, children, joiner=""):
|
||||||
CGThing.__init__(self)
|
CGThing.__init__(self)
|
||||||
self.children = children
|
# Make a copy of the kids into a list, because if someone passes in a
|
||||||
|
# generator we won't be able to both declare and define ourselves, or
|
||||||
|
# define ourselves more than once!
|
||||||
|
self.children = list(children)
|
||||||
self.joiner = joiner
|
self.joiner = joiner
|
||||||
|
|
||||||
def append(self, child):
|
def append(self, child):
|
||||||
|
@ -1934,12 +2025,15 @@ class CGList(CGThing):
|
||||||
def prepend(self, child):
|
def prepend(self, child):
|
||||||
self.children.insert(0, child)
|
self.children.insert(0, child)
|
||||||
|
|
||||||
def join(self, generator):
|
def join(self, iterable):
|
||||||
return self.joiner.join(filter(lambda s: len(s) > 0, (child for child in generator)))
|
return self.joiner.join(s for s in iterable if len(s) > 0)
|
||||||
|
|
||||||
def define(self):
|
def define(self):
|
||||||
return self.join(child.define() for child in self.children if child is not None)
|
return self.join(child.define() for child in self.children if child is not None)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.children)
|
||||||
|
|
||||||
|
|
||||||
class CGIfElseWrapper(CGList):
|
class CGIfElseWrapper(CGList):
|
||||||
def __init__(self, condition, ifTrue, ifFalse):
|
def __init__(self, condition, ifTrue, ifFalse):
|
||||||
|
@ -2145,6 +2239,49 @@ class CGAbstractMethod(CGThing):
|
||||||
raise NotImplementedError # Override me!
|
raise NotImplementedError # Override me!
|
||||||
|
|
||||||
|
|
||||||
|
class CGConstructorEnabled(CGAbstractMethod):
|
||||||
|
"""
|
||||||
|
A method for testing whether we should be exposing this interface
|
||||||
|
object or navigator property. This can perform various tests
|
||||||
|
depending on what conditions are specified on the interface.
|
||||||
|
"""
|
||||||
|
def __init__(self, descriptor):
|
||||||
|
CGAbstractMethod.__init__(self, descriptor,
|
||||||
|
'ConstructorEnabled', 'bool',
|
||||||
|
[Argument("*mut JSContext", "aCx"),
|
||||||
|
Argument("HandleObject", "aObj")])
|
||||||
|
|
||||||
|
def definition_body(self):
|
||||||
|
body = CGList([], "\n")
|
||||||
|
|
||||||
|
conditions = []
|
||||||
|
iface = self.descriptor.interface
|
||||||
|
|
||||||
|
pref = iface.getExtendedAttribute("Pref")
|
||||||
|
if pref:
|
||||||
|
assert isinstance(pref, list) and len(pref) == 1
|
||||||
|
conditions.append('prefs::get_pref("%s").as_boolean().unwrap_or(false)' % pref[0])
|
||||||
|
func = iface.getExtendedAttribute("Func")
|
||||||
|
if func:
|
||||||
|
assert isinstance(func, list) and len(func) == 1
|
||||||
|
conditions.append("%s(aCx, aObj)" % func[0])
|
||||||
|
# We should really have some conditions
|
||||||
|
assert len(body) or len(conditions)
|
||||||
|
|
||||||
|
conditionsWrapper = ""
|
||||||
|
if len(conditions):
|
||||||
|
conditionsWrapper = CGWrapper(CGList((CGGeneric(cond) for cond in conditions),
|
||||||
|
" &&\n"),
|
||||||
|
pre="return ",
|
||||||
|
post=";\n",
|
||||||
|
reindent=True)
|
||||||
|
else:
|
||||||
|
conditionsWrapper = CGGeneric("return true;\n")
|
||||||
|
|
||||||
|
body.append(conditionsWrapper)
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
def CreateBindingJSObject(descriptor, parent=None):
|
def CreateBindingJSObject(descriptor, parent=None):
|
||||||
create = "let raw = Box::into_raw(object);\nlet _rt = RootedTraceable::new(&*raw);\n"
|
create = "let raw = Box::into_raw(object);\nlet _rt = RootedTraceable::new(&*raw);\n"
|
||||||
if descriptor.proxy:
|
if descriptor.proxy:
|
||||||
|
@ -2191,8 +2328,8 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties):
|
||||||
"""
|
"""
|
||||||
unforgeables = []
|
unforgeables = []
|
||||||
|
|
||||||
defineUnforgeableAttrs = "define_properties(cx, unforgeable_holder.handle(), %s).unwrap();"
|
defineUnforgeableAttrs = "define_prefable_properties(cx, unforgeable_holder.handle(), %s);"
|
||||||
defineUnforgeableMethods = "define_methods(cx, unforgeable_holder.handle(), %s).unwrap();"
|
defineUnforgeableMethods = "define_prefable_methods(cx, unforgeable_holder.handle(), %s);"
|
||||||
|
|
||||||
unforgeableMembers = [
|
unforgeableMembers = [
|
||||||
(defineUnforgeableAttrs, properties.unforgeable_attrs),
|
(defineUnforgeableAttrs, properties.unforgeable_attrs),
|
||||||
|
@ -2684,15 +2821,21 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
|
||||||
return CGAbstractMethod.define(self)
|
return CGAbstractMethod.define(self)
|
||||||
|
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
|
def getCheck(desc):
|
||||||
|
if not desc.isExposedConditionally():
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
return "if !ConstructorEnabled(cx, global) { return; }"
|
||||||
if self.descriptor.interface.isCallback():
|
if self.descriptor.interface.isCallback():
|
||||||
function = "GetConstructorObject"
|
function = "GetConstructorObject"
|
||||||
else:
|
else:
|
||||||
function = "GetProtoObject"
|
function = "GetProtoObject"
|
||||||
return CGGeneric("""\
|
return CGGeneric("""\
|
||||||
assert!(!global.get().is_null());
|
assert!(!global.get().is_null());
|
||||||
|
%s
|
||||||
let mut proto = RootedObject::new(cx, ptr::null_mut());
|
let mut proto = RootedObject::new(cx, ptr::null_mut());
|
||||||
%s(cx, global, proto.handle_mut());
|
%s(cx, global, proto.handle_mut());
|
||||||
assert!(!proto.ptr.is_null());""" % function)
|
assert!(!proto.ptr.is_null());""" % (getCheck(self.descriptor), function))
|
||||||
|
|
||||||
|
|
||||||
def needCx(returnType, arguments, considerTypes):
|
def needCx(returnType, arguments, considerTypes):
|
||||||
|
@ -5003,6 +5146,8 @@ class CGDescriptor(CGThing):
|
||||||
|
|
||||||
if descriptor.interface.hasInterfaceObject():
|
if descriptor.interface.hasInterfaceObject():
|
||||||
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
|
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
|
||||||
|
if descriptor.isExposedConditionally():
|
||||||
|
cgThings.append(CGConstructorEnabled(descriptor))
|
||||||
|
|
||||||
if descriptor.proxy:
|
if descriptor.proxy:
|
||||||
cgThings.append(CGDefineProxyHandler(descriptor))
|
cgThings.append(CGDefineProxyHandler(descriptor))
|
||||||
|
@ -5405,12 +5550,13 @@ class CGBindingRoot(CGThing):
|
||||||
'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
|
'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
|
||||||
'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
|
'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
|
||||||
'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
|
'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
|
||||||
|
'dom::bindings::interface::{define_prefable_methods, define_prefable_properties}',
|
||||||
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
|
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
|
||||||
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
|
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
|
||||||
'dom::bindings::js::{JS, Root, RootedReference}',
|
'dom::bindings::js::{JS, Root, RootedReference}',
|
||||||
'dom::bindings::js::{OptionalRootedReference}',
|
'dom::bindings::js::{OptionalRootedReference}',
|
||||||
'dom::bindings::reflector::{Reflectable}',
|
'dom::bindings::reflector::{Reflectable}',
|
||||||
'dom::bindings::utils::{DOMClass, DOMJSClass}',
|
'dom::bindings::utils::{DOMClass, DOMJSClass, Prefable}',
|
||||||
'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
|
'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
|
||||||
'dom::bindings::utils::{ProtoOrIfaceArray, create_dom_global}',
|
'dom::bindings::utils::{ProtoOrIfaceArray, create_dom_global}',
|
||||||
'dom::bindings::utils::{enumerate_global, finalize_global, find_enum_string_index}',
|
'dom::bindings::utils::{enumerate_global, finalize_global, find_enum_string_index}',
|
||||||
|
@ -5444,6 +5590,7 @@ class CGBindingRoot(CGThing):
|
||||||
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
|
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
|
||||||
'mem::heap_size_of_raw_self_and_children',
|
'mem::heap_size_of_raw_self_and_children',
|
||||||
'libc',
|
'libc',
|
||||||
|
'util::prefs',
|
||||||
'util::str::DOMString',
|
'util::str::DOMString',
|
||||||
'std::borrow::ToOwned',
|
'std::borrow::ToOwned',
|
||||||
'std::cmp',
|
'std::cmp',
|
||||||
|
|
|
@ -165,6 +165,12 @@ class Descriptor(DescriptorProvider):
|
||||||
DescriptorProvider.__init__(self, config)
|
DescriptorProvider.__init__(self, config)
|
||||||
self.interface = interface
|
self.interface = interface
|
||||||
|
|
||||||
|
if not self.isExposedConditionally():
|
||||||
|
if interface.parent and interface.parent.isExposedConditionally():
|
||||||
|
raise TypeError("%s is not conditionally exposed but inherits from "
|
||||||
|
"%s which is" %
|
||||||
|
(interface.identifier.name, interface.parent.identifier.name))
|
||||||
|
|
||||||
# Read the desc, and fill in the relevant defaults.
|
# Read the desc, and fill in the relevant defaults.
|
||||||
ifaceName = self.interface.identifier.name
|
ifaceName = self.interface.identifier.name
|
||||||
|
|
||||||
|
@ -351,6 +357,9 @@ class Descriptor(DescriptorProvider):
|
||||||
assert self.interface.hasInterfaceObject()
|
assert self.interface.hasInterfaceObject()
|
||||||
return self.interface.isCallback() or self.hasDescendants()
|
return self.interface.isCallback() or self.hasDescendants()
|
||||||
|
|
||||||
|
def isExposedConditionally(self):
|
||||||
|
return self.interface.isExposedConditionally()
|
||||||
|
|
||||||
def isGlobal(self):
|
def isGlobal(self):
|
||||||
"""
|
"""
|
||||||
Returns true if this is the primary interface for a global object
|
Returns true if this is the primary interface for a global object
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use dom::bindings::codegen::PrototypeList;
|
use dom::bindings::codegen::PrototypeList;
|
||||||
use dom::bindings::conversions::get_dom_class;
|
use dom::bindings::conversions::get_dom_class;
|
||||||
use dom::bindings::utils::get_proto_or_iface_array;
|
use dom::bindings::utils::{get_proto_or_iface_array, Prefable};
|
||||||
use js::error::throw_type_error;
|
use js::error::throw_type_error;
|
||||||
use js::glue::UncheckedUnwrapObject;
|
use js::glue::UncheckedUnwrapObject;
|
||||||
use js::jsapi::{Class, ClassExtension, ClassSpec, GetGlobalForObjectCrossCompartment};
|
use js::jsapi::{Class, ClassExtension, ClassSpec, GetGlobalForObjectCrossCompartment};
|
||||||
|
@ -212,13 +212,15 @@ impl InterfaceConstructorBehavior {
|
||||||
pub unsafe fn create_callback_interface_object(
|
pub unsafe fn create_callback_interface_object(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
receiver: HandleObject,
|
receiver: HandleObject,
|
||||||
constants: &'static [ConstantSpec],
|
constants: &'static [Prefable<ConstantSpec>],
|
||||||
name: &'static [u8],
|
name: &'static [u8],
|
||||||
rval: MutableHandleObject) {
|
rval: MutableHandleObject) {
|
||||||
assert!(!constants.is_empty());
|
assert!(!constants.is_empty());
|
||||||
rval.set(JS_NewObject(cx, ptr::null()));
|
rval.set(JS_NewObject(cx, ptr::null()));
|
||||||
assert!(!rval.ptr.is_null());
|
assert!(!rval.ptr.is_null());
|
||||||
define_constants(cx, rval.handle(), constants);
|
for prefable in constants {
|
||||||
|
define_constants(cx, rval.handle(), prefable.specs());
|
||||||
|
}
|
||||||
define_name(cx, rval.handle(), name);
|
define_name(cx, rval.handle(), name);
|
||||||
define_on_global_object(cx, receiver, name, rval.handle());
|
define_on_global_object(cx, receiver, name, rval.handle());
|
||||||
}
|
}
|
||||||
|
@ -228,9 +230,9 @@ pub unsafe fn create_interface_prototype_object(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
proto: HandleObject,
|
proto: HandleObject,
|
||||||
class: &'static JSClass,
|
class: &'static JSClass,
|
||||||
regular_methods: Option<&'static [JSFunctionSpec]>,
|
regular_methods: Option<&'static [Prefable<JSFunctionSpec>]>,
|
||||||
regular_properties: Option<&'static [JSPropertySpec]>,
|
regular_properties: Option<&'static [Prefable<JSPropertySpec>]>,
|
||||||
constants: &'static [ConstantSpec],
|
constants: &'static [Prefable<ConstantSpec>],
|
||||||
rval: MutableHandleObject) {
|
rval: MutableHandleObject) {
|
||||||
create_object(cx, proto, class, regular_methods, regular_properties, constants, rval);
|
create_object(cx, proto, class, regular_methods, regular_properties, constants, rval);
|
||||||
}
|
}
|
||||||
|
@ -241,9 +243,9 @@ pub unsafe fn create_noncallback_interface_object(
|
||||||
receiver: HandleObject,
|
receiver: HandleObject,
|
||||||
proto: HandleObject,
|
proto: HandleObject,
|
||||||
class: &'static NonCallbackInterfaceObjectClass,
|
class: &'static NonCallbackInterfaceObjectClass,
|
||||||
static_methods: Option<&'static [JSFunctionSpec]>,
|
static_methods: Option<&'static [Prefable<JSFunctionSpec>]>,
|
||||||
static_properties: Option<&'static [JSPropertySpec]>,
|
static_properties: Option<&'static [Prefable<JSPropertySpec>]>,
|
||||||
constants: &'static [ConstantSpec],
|
constants: &'static [Prefable<ConstantSpec>],
|
||||||
interface_prototype_object: HandleObject,
|
interface_prototype_object: HandleObject,
|
||||||
name: &'static [u8],
|
name: &'static [u8],
|
||||||
length: u32,
|
length: u32,
|
||||||
|
@ -355,19 +357,39 @@ unsafe fn create_object(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
proto: HandleObject,
|
proto: HandleObject,
|
||||||
class: &'static JSClass,
|
class: &'static JSClass,
|
||||||
methods: Option<&'static [JSFunctionSpec]>,
|
methods: Option<&'static [Prefable<JSFunctionSpec>]>,
|
||||||
properties: Option<&'static [JSPropertySpec]>,
|
properties: Option<&'static [Prefable<JSPropertySpec>]>,
|
||||||
constants: &'static [ConstantSpec],
|
constants: &'static [Prefable<ConstantSpec>],
|
||||||
rval: MutableHandleObject) {
|
rval: MutableHandleObject) {
|
||||||
rval.set(JS_NewObjectWithUniqueType(cx, class, proto));
|
rval.set(JS_NewObjectWithUniqueType(cx, class, proto));
|
||||||
assert!(!rval.ptr.is_null());
|
assert!(!rval.ptr.is_null());
|
||||||
if let Some(methods) = methods {
|
if let Some(methods) = methods {
|
||||||
define_methods(cx, rval.handle(), methods).unwrap();
|
define_prefable_methods(cx, rval.handle(), methods);
|
||||||
}
|
}
|
||||||
if let Some(properties) = properties {
|
if let Some(properties) = properties {
|
||||||
define_properties(cx, rval.handle(), properties).unwrap();
|
define_prefable_properties(cx, rval.handle(), properties);
|
||||||
|
}
|
||||||
|
for prefable in constants {
|
||||||
|
define_constants(cx, rval.handle(), prefable.specs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Conditionally define methods on an object.
|
||||||
|
pub unsafe fn define_prefable_methods(cx: *mut JSContext,
|
||||||
|
obj: HandleObject,
|
||||||
|
methods: &'static [Prefable<JSFunctionSpec>]) {
|
||||||
|
for prefable in methods {
|
||||||
|
define_methods(cx, obj, prefable.specs()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Conditionally define properties on an object.
|
||||||
|
pub unsafe fn define_prefable_properties(cx: *mut JSContext,
|
||||||
|
obj: HandleObject,
|
||||||
|
properties: &'static [Prefable<JSPropertySpec>]) {
|
||||||
|
for prefable in properties {
|
||||||
|
define_properties(cx, obj, prefable.specs()).unwrap();
|
||||||
}
|
}
|
||||||
define_constants(cx, rval.handle(), constants);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn define_name(cx: *mut JSContext, obj: HandleObject, name: &'static [u8]) {
|
unsafe fn define_name(cx: *mut JSContext, obj: HandleObject, name: &'static [u8]) {
|
||||||
|
|
|
@ -41,6 +41,7 @@ use std::os::raw::c_void;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use util::non_geckolib::jsstring_to_str;
|
use util::non_geckolib::jsstring_to_str;
|
||||||
|
use util::prefs;
|
||||||
|
|
||||||
/// Proxy handler for a WindowProxy.
|
/// Proxy handler for a WindowProxy.
|
||||||
pub struct WindowProxyHandler(pub *const libc::c_void);
|
pub struct WindowProxyHandler(pub *const libc::c_void);
|
||||||
|
@ -557,3 +558,31 @@ unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi::
|
||||||
pub const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks {
|
pub const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks {
|
||||||
instanceClassMatchesProto: Some(instance_class_has_proto_at_depth),
|
instanceClassMatchesProto: Some(instance_class_has_proto_at_depth),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A container around JS member specifications that are conditionally enabled.
|
||||||
|
pub struct Prefable<T: 'static> {
|
||||||
|
/// If present, the name of the preference used to conditionally enable these specs.
|
||||||
|
pub pref: Option<&'static str>,
|
||||||
|
/// The underlying slice of specifications.
|
||||||
|
pub specs: &'static [T],
|
||||||
|
/// Whether the specifications contain special terminating entries that should be
|
||||||
|
/// included or not.
|
||||||
|
pub terminator: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Prefable<T> {
|
||||||
|
/// Retrieve the slice represented by this container, unless the condition
|
||||||
|
/// guarding it is false.
|
||||||
|
pub fn specs(&self) -> &'static [T] {
|
||||||
|
if let Some(pref) = self.pref {
|
||||||
|
if !prefs::get_pref(pref).as_boolean().unwrap_or(false) {
|
||||||
|
return if self.terminator {
|
||||||
|
&self.specs[self.specs.len() - 1..]
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.specs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -493,10 +493,18 @@ impl TestBindingMethods for TestBinding {
|
||||||
fn StringMozPreference(&self, pref_name: DOMString) -> DOMString {
|
fn StringMozPreference(&self, pref_name: DOMString) -> DOMString {
|
||||||
get_pref(pref_name.as_ref()).as_string().map(|s| DOMString::from(s)).unwrap_or_else(|| DOMString::new())
|
get_pref(pref_name.as_ref()).as_string().map(|s| DOMString::from(s)).unwrap_or_else(|| DOMString::new())
|
||||||
}
|
}
|
||||||
|
fn PrefControlledAttributeDisabled(&self) -> bool { false }
|
||||||
|
fn PrefControlledAttributeEnabled(&self) -> bool { false }
|
||||||
|
fn PrefControlledMethodDisabled(&self) {}
|
||||||
|
fn PrefControlledMethodEnabled(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestBinding {
|
impl TestBinding {
|
||||||
pub fn BooleanAttributeStatic(_: GlobalRef) -> bool { false }
|
pub fn BooleanAttributeStatic(_: GlobalRef) -> bool { false }
|
||||||
pub fn SetBooleanAttributeStatic(_: GlobalRef, _: bool) {}
|
pub fn SetBooleanAttributeStatic(_: GlobalRef, _: bool) {}
|
||||||
pub fn ReceiveVoidStatic(_: GlobalRef) {}
|
pub fn ReceiveVoidStatic(_: GlobalRef) {}
|
||||||
|
pub fn PrefControlledStaticAttributeDisabled(_: GlobalRef) -> bool { false }
|
||||||
|
pub fn PrefControlledStaticAttributeEnabled(_: GlobalRef) -> bool { false }
|
||||||
|
pub fn PrefControlledStaticMethodDisabled(_: GlobalRef) {}
|
||||||
|
pub fn PrefControlledStaticMethodEnabled(_: GlobalRef) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth
|
// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface Bluetooth {
|
interface Bluetooth {
|
||||||
// Promise<BluetoothDevice> requestDevice(RequestDeviceOptions options);
|
// Promise<BluetoothDevice> requestDevice(RequestDeviceOptions options);
|
||||||
BluetoothDevice? requestDevice(/*RequestDeviceOptions options*/);
|
BluetoothDevice? requestDevice(/*RequestDeviceOptions options*/);
|
||||||
|
|
|
@ -12,6 +12,7 @@ interface BluetoothServiceDataMap {
|
||||||
readonly maplike<UUID, DataView>;
|
readonly maplike<UUID, DataView>;
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface BluetoothAdvertisingData {
|
interface BluetoothAdvertisingData {
|
||||||
readonly attribute unsigned short? appearance;
|
readonly attribute unsigned short? appearance;
|
||||||
readonly attribute byte? txPower;
|
readonly attribute byte? txPower;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#characteristicproperties
|
// https://webbluetoothcg.github.io/web-bluetooth/#characteristicproperties
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface BluetoothCharacteristicProperties {
|
interface BluetoothCharacteristicProperties {
|
||||||
readonly attribute boolean broadcast;
|
readonly attribute boolean broadcast;
|
||||||
readonly attribute boolean read;
|
readonly attribute boolean read;
|
||||||
|
|
|
@ -10,6 +10,7 @@ enum VendorIDSource {
|
||||||
"usb"
|
"usb"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface BluetoothDevice {
|
interface BluetoothDevice {
|
||||||
readonly attribute DOMString id;
|
readonly attribute DOMString id;
|
||||||
readonly attribute DOMString? name;
|
readonly attribute DOMString? name;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattcharacteristic
|
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattcharacteristic
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface BluetoothRemoteGATTCharacteristic {
|
interface BluetoothRemoteGATTCharacteristic {
|
||||||
readonly attribute BluetoothRemoteGATTService service;
|
readonly attribute BluetoothRemoteGATTService service;
|
||||||
readonly attribute DOMString uuid;
|
readonly attribute DOMString uuid;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
// http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor
|
// http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface BluetoothRemoteGATTDescriptor {
|
interface BluetoothRemoteGATTDescriptor {
|
||||||
readonly attribute BluetoothRemoteGATTCharacteristic characteristic;
|
readonly attribute BluetoothRemoteGATTCharacteristic characteristic;
|
||||||
readonly attribute DOMString uuid;
|
readonly attribute DOMString uuid;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
//https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattserver
|
//https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattserver
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface BluetoothRemoteGATTServer {
|
interface BluetoothRemoteGATTServer {
|
||||||
readonly attribute BluetoothDevice device;
|
readonly attribute BluetoothDevice device;
|
||||||
readonly attribute boolean connected;
|
readonly attribute boolean connected;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
|
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface BluetoothRemoteGATTService {
|
interface BluetoothRemoteGATTService {
|
||||||
readonly attribute BluetoothDevice device;
|
readonly attribute BluetoothDevice device;
|
||||||
readonly attribute DOMString uuid;
|
readonly attribute DOMString uuid;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothuuid
|
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothuuid
|
||||||
|
|
||||||
|
[Pref="dom.bluetooth.enabled"]
|
||||||
interface BluetoothUUID {
|
interface BluetoothUUID {
|
||||||
[Throws]
|
[Throws]
|
||||||
static UUID getService(BluetoothServiceUUID name);
|
static UUID getService(BluetoothServiceUUID name);
|
||||||
|
|
|
@ -147,22 +147,22 @@ interface BrowserElementPrivileged {
|
||||||
// unsigned long modifiers);
|
// unsigned long modifiers);
|
||||||
|
|
||||||
[Throws,
|
[Throws,
|
||||||
Pref="dom.mozBrowserFramesEnabled",
|
Pref="dom.mozbrowser.enabled",
|
||||||
CheckAnyPermissions="browser"]
|
CheckAnyPermissions="browser"]
|
||||||
void goBack();
|
void goBack();
|
||||||
|
|
||||||
[Throws,
|
[Throws,
|
||||||
Pref="dom.mozBrowserFramesEnabled",
|
Pref="dom.mozbrowser.enabled",
|
||||||
CheckAnyPermissions="browser"]
|
CheckAnyPermissions="browser"]
|
||||||
void goForward();
|
void goForward();
|
||||||
|
|
||||||
[Throws,
|
[Throws,
|
||||||
Pref="dom.mozBrowserFramesEnabled",
|
Pref="dom.mozbrowser.enabled",
|
||||||
CheckAnyPermissions="browser"]
|
CheckAnyPermissions="browser"]
|
||||||
void reload(optional boolean hardReload = false);
|
void reload(optional boolean hardReload = false);
|
||||||
|
|
||||||
[Throws,
|
[Throws,
|
||||||
Pref="dom.mozBrowserFramesEnabled",
|
Pref="dom.mozbrowser.enabled",
|
||||||
CheckAnyPermissions="browser"]
|
CheckAnyPermissions="browser"]
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ partial interface HTMLIFrameElement {
|
||||||
};
|
};
|
||||||
|
|
||||||
partial interface HTMLIFrameElement {
|
partial interface HTMLIFrameElement {
|
||||||
[ChromeOnly,SetterThrows]
|
[ChromeOnly,SetterThrows,Pref="dom.mozbrowser.enabled"]
|
||||||
attribute boolean mozbrowser;
|
attribute boolean mozbrowser;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ interface MouseEvent : UIEvent {
|
||||||
//readonly attribute unsigned short buttons;
|
//readonly attribute unsigned short buttons;
|
||||||
//boolean getModifierState (DOMString keyArg);
|
//boolean getModifierState (DOMString keyArg);
|
||||||
|
|
||||||
|
[Pref="dom.mouseevent.which.enabled"]
|
||||||
readonly attribute long which;
|
readonly attribute long which;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,8 @@ dictionary TestDictionaryDefaults {
|
||||||
|
|
||||||
[Constructor,
|
[Constructor,
|
||||||
Constructor(sequence<unrestricted double> numberSequence),
|
Constructor(sequence<unrestricted double> numberSequence),
|
||||||
Constructor(unrestricted double num)]
|
Constructor(unrestricted double num),
|
||||||
|
Pref="dom.testbinding.enabled"]
|
||||||
interface TestBinding {
|
interface TestBinding {
|
||||||
attribute boolean booleanAttribute;
|
attribute boolean booleanAttribute;
|
||||||
attribute byte byteAttribute;
|
attribute byte byteAttribute;
|
||||||
|
@ -401,4 +402,26 @@ interface TestBinding {
|
||||||
static void receiveVoidStatic();
|
static void receiveVoidStatic();
|
||||||
boolean BooleanMozPreference(DOMString pref_name);
|
boolean BooleanMozPreference(DOMString pref_name);
|
||||||
DOMString StringMozPreference(DOMString pref_name);
|
DOMString StringMozPreference(DOMString pref_name);
|
||||||
|
|
||||||
|
[Pref="dom.testbinding.prefcontrolled.enabled"]
|
||||||
|
readonly attribute boolean prefControlledAttributeDisabled;
|
||||||
|
[Pref="dom.testbinding.prefcontrolled.enabled"]
|
||||||
|
static readonly attribute boolean prefControlledStaticAttributeDisabled;
|
||||||
|
[Pref="dom.testbinding.prefcontrolled.enabled"]
|
||||||
|
void prefControlledMethodDisabled();
|
||||||
|
[Pref="dom.testbinding.prefcontrolled.enabled"]
|
||||||
|
static void prefControlledStaticMethodDisabled();
|
||||||
|
[Pref="dom.testbinding.prefcontrolled.enabled"]
|
||||||
|
const unsigned short prefControlledConstDisabled = 0;
|
||||||
|
|
||||||
|
[Pref="dom.testbinding.prefcontrolled2.enabled"]
|
||||||
|
readonly attribute boolean prefControlledAttributeEnabled;
|
||||||
|
[Pref="dom.testbinding.prefcontrolled2.enabled"]
|
||||||
|
static readonly attribute boolean prefControlledStaticAttributeEnabled;
|
||||||
|
[Pref="dom.testbinding.prefcontrolled2.enabled"]
|
||||||
|
void prefControlledMethodEnabled();
|
||||||
|
[Pref="dom.testbinding.prefcontrolled2.enabled"]
|
||||||
|
static void prefControlledStaticMethodEnabled();
|
||||||
|
[Pref="dom.testbinding.prefcontrolled2.enabled"]
|
||||||
|
const unsigned short prefControlledConstEnabled = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
// This interface is entirely internal to Servo, and should not be accessible to
|
// This interface is entirely internal to Servo, and should not be accessible to
|
||||||
// web pages.
|
// web pages.
|
||||||
|
|
||||||
|
[Pref="dom.testbinding.enabled"]
|
||||||
interface TestBindingProxy : TestBinding {
|
interface TestBindingProxy : TestBinding {
|
||||||
readonly attribute unsigned long length;
|
readonly attribute unsigned long length;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
{
|
{
|
||||||
|
"dom.bluetooth.enabled": false,
|
||||||
"dom.forcetouch.enabled": false,
|
"dom.forcetouch.enabled": false,
|
||||||
"dom.mouseevent.which.enabled": false,
|
"dom.mouseevent.which.enabled": false,
|
||||||
"dom.mozbrowser.enabled": false,
|
"dom.mozbrowser.enabled": false,
|
||||||
|
"dom.testbinding.enabled": false,
|
||||||
"gfx.webrender.enabled": false,
|
"gfx.webrender.enabled": false,
|
||||||
"js.baseline.enabled": true,
|
"js.baseline.enabled": true,
|
||||||
"js.ion.enabled": true,
|
"js.ion.enabled": true,
|
||||||
|
|
|
@ -6424,6 +6424,12 @@
|
||||||
"url": "/_mozilla/mozilla/innerHTML.html"
|
"url": "/_mozilla/mozilla/innerHTML.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"mozilla/interface_member_exposed.html": [
|
||||||
|
{
|
||||||
|
"path": "mozilla/interface_member_exposed.html",
|
||||||
|
"url": "/_mozilla/mozilla/interface_member_exposed.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"mozilla/interfaces.html": [
|
"mozilla/interfaces.html": [
|
||||||
{
|
{
|
||||||
"path": "mozilla/interfaces.html",
|
"path": "mozilla/interfaces.html",
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[interface_member_exposed.html]
|
||||||
|
type: testharness
|
||||||
|
prefs: [dom.testbinding.enabled:true,
|
||||||
|
dom.testbinding.prefcontrolled2.enabled:true]
|
|
@ -1,3 +1,3 @@
|
||||||
[preferences.html]
|
[preferences.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
prefs: [dom.testbinding.preference_value.falsy:false, dom.testbinding.preference_value.truthy:true, dom.testbinding.preference_value.string_empty:, dom.testbinding.preference_value.string_test:test, dom.testbinding.preference_value.space_string_test:test1 test2, dom.testbinding.preference_value.quote_string_test:"test1 test2"]
|
prefs: [dom.testbinding.enabled:true, dom.testbinding.preference_value.falsy:false, dom.testbinding.preference_value.truthy:true, dom.testbinding.preference_value.string_empty:, dom.testbinding.preference_value.string_test:test, dom.testbinding.preference_value.space_string_test:test1 test2, dom.testbinding.preference_value.quote_string_test:"test1 test2"]
|
||||||
|
|
3
tests/wpt/mozilla/meta/mozilla/sequence-hole.html.ini
Normal file
3
tests/wpt/mozilla/meta/mozilla/sequence-hole.html.ini
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[sequence-hole.html]
|
||||||
|
type: testharness
|
||||||
|
prefs: [dom.testbinding.enabled:true]
|
|
@ -0,0 +1,3 @@
|
||||||
|
[variadic-interface.html]
|
||||||
|
type: testharness
|
||||||
|
prefs: [dom.testbinding.enabled:true]
|
3
tests/wpt/mozilla/meta/mozilla/weakref.html.ini
Normal file
3
tests/wpt/mozilla/meta/mozilla/weakref.html.ini
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[weakref.html]
|
||||||
|
type: testharness
|
||||||
|
prefs: [dom.testbinding.enabled:true]
|
|
@ -0,0 +1,41 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title></title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script>
|
||||||
|
function test_member(name, enabled, target) {
|
||||||
|
var status = enabled ? "Enabled" : "Disabled";
|
||||||
|
var verb = enabled ? "shows" : "hides";
|
||||||
|
test(function() {
|
||||||
|
var interface = target(window.TestBinding);
|
||||||
|
var descriptor = Object.getOwnPropertyDescriptor(interface, name);
|
||||||
|
if (enabled) {
|
||||||
|
assert_not_equals(descriptor, undefined);
|
||||||
|
} else {
|
||||||
|
assert_equals(descriptor, undefined);
|
||||||
|
}
|
||||||
|
}, status + " preference " + verb + " member controlled by that preference: " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
var members = [
|
||||||
|
'prefControlledAttribute',
|
||||||
|
'prefControlledMethod'
|
||||||
|
];
|
||||||
|
var staticMembers = [
|
||||||
|
'prefControlledStaticAttribute',
|
||||||
|
'prefControlledStaticMethod',
|
||||||
|
'prefControlledConst'
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < members.length; i++) {
|
||||||
|
var name = members[i];
|
||||||
|
test_member(name + 'Enabled', true, function(o) { return Object.getPrototypeOf(new o()) });
|
||||||
|
test_member(name + 'Disabled', false, function(o) { return Object.getPrototypeOf(new o()) });
|
||||||
|
}
|
||||||
|
for (var i = 0; i < staticMembers.length; i++) {
|
||||||
|
var name = staticMembers[i];
|
||||||
|
test_member(name + 'Enabled', true, function(o) { return o; });
|
||||||
|
test_member(name + 'Disabled', false, function(o) { return o; });
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -22,8 +22,6 @@ var ecmaGlobals = [
|
||||||
"EvalError",
|
"EvalError",
|
||||||
"Float32Array",
|
"Float32Array",
|
||||||
"Float64Array",
|
"Float64Array",
|
||||||
"FocusEvent",
|
|
||||||
"ForceTouchEvent",
|
|
||||||
"Function",
|
"Function",
|
||||||
"Infinity",
|
"Infinity",
|
||||||
"Int16Array",
|
"Int16Array",
|
||||||
|
@ -74,15 +72,6 @@ var ecmaGlobals = [
|
||||||
var interfaceNamesInGlobalScope = [
|
var interfaceNamesInGlobalScope = [
|
||||||
"Attr",
|
"Attr",
|
||||||
"Blob",
|
"Blob",
|
||||||
"Bluetooth",
|
|
||||||
"BluetoothAdvertisingData",
|
|
||||||
"BluetoothCharacteristicProperties",
|
|
||||||
"BluetoothDevice",
|
|
||||||
"BluetoothRemoteGATTCharacteristic",
|
|
||||||
"BluetoothRemoteGATTDescriptor",
|
|
||||||
"BluetoothRemoteGATTServer",
|
|
||||||
"BluetoothRemoteGATTService",
|
|
||||||
"BluetoothUUID",
|
|
||||||
"CanvasGradient",
|
"CanvasGradient",
|
||||||
"CanvasRenderingContext2D",
|
"CanvasRenderingContext2D",
|
||||||
"CanvasPattern",
|
"CanvasPattern",
|
||||||
|
@ -115,6 +104,7 @@ var interfaceNamesInGlobalScope = [
|
||||||
"File",
|
"File",
|
||||||
"FileList",
|
"FileList",
|
||||||
"FileReader",
|
"FileReader",
|
||||||
|
"FocusEvent",
|
||||||
"FormData",
|
"FormData",
|
||||||
"HTMLAnchorElement",
|
"HTMLAnchorElement",
|
||||||
"HTMLAppletElement",
|
"HTMLAppletElement",
|
||||||
|
@ -215,8 +205,6 @@ var interfaceNamesInGlobalScope = [
|
||||||
"StorageEvent",
|
"StorageEvent",
|
||||||
"StyleSheet",
|
"StyleSheet",
|
||||||
"StyleSheetList",
|
"StyleSheetList",
|
||||||
"TestBinding", // XXX
|
|
||||||
"TestBindingProxy", // XXX
|
|
||||||
"Text",
|
"Text",
|
||||||
"TextDecoder",
|
"TextDecoder",
|
||||||
"TextEncoder",
|
"TextEncoder",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue