aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings
diff options
context:
space:
mode:
authorMs2ger <Ms2ger@gmail.com>2016-07-08 15:48:55 +0200
committerMs2ger <Ms2ger@gmail.com>2016-07-12 13:06:56 +0200
commitd678b206169f5d78416b0612d2a614098bf4bc53 (patch)
tree0e999070708461c4abe0b62d6c951a1e49e775ca /components/script/dom/bindings
parentc064c4950d2be040f0c13c5e8db1e0457f844204 (diff)
downloadservo-d678b206169f5d78416b0612d2a614098bf4bc53.tar.gz
servo-d678b206169f5d78416b0612d2a614098bf4bc53.zip
Implement the [Exposed] extended attribute on interfaces.
Fixes #2823.
Diffstat (limited to 'components/script/dom/bindings')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py56
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py2
-rw-r--r--components/script/dom/bindings/interface.rs9
-rw-r--r--components/script/dom/bindings/utils.rs3
4 files changed, 54 insertions, 16 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 1ac3b102574..8c0d27afb82 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -1825,12 +1825,17 @@ def DOMClass(descriptor):
protoList.extend(['PrototypeList::ID::Last'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
heapSizeOf = 'heap_size_of_raw_self_and_children::<%s>' % descriptor.interface.identifier.name
+ if descriptor.isGlobal():
+ globals_ = camel_to_upper_snake(descriptor.name)
+ else:
+ globals_ = 'EMPTY'
return """\
DOMClass {
interface_chain: [ %s ],
type_id: %s,
heap_size_of: %s as unsafe fn(_) -> _,
-}""" % (prototypeChainString, DOMClassTypeId(descriptor), heapSizeOf)
+ global: InterfaceObjectMap::%s,
+}""" % (prototypeChainString, DOMClassTypeId(descriptor), heapSizeOf, globals_)
class CGDOMJSClass(CGThing):
@@ -2233,9 +2238,9 @@ match result {
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.
+ A method for testing whether we should be exposing this interface object.
+ This can perform various tests depending on what conditions are specified
+ on the interface.
"""
def __init__(self, descriptor):
CGAbstractMethod.__init__(self, descriptor,
@@ -2248,6 +2253,11 @@ class CGConstructorEnabled(CGAbstractMethod):
conditions = []
iface = self.descriptor.interface
+ bits = " | ".join(sorted(
+ "InterfaceObjectMap::" + camel_to_upper_snake(i) for i in iface.exposureSet
+ ))
+ conditions.append("is_exposed_in(aObj, %s)" % bits)
+
pref = iface.getExtendedAttribute("Pref")
if pref:
assert isinstance(pref, list) and len(pref) == 1
@@ -2258,8 +2268,6 @@ class CGConstructorEnabled(CGAbstractMethod):
assert isinstance(func, list) and len(func) == 1
conditions.append("%s(aCx, aObj)" % func[0])
- assert conditions
-
return CGList((CGGeneric(cond) for cond in conditions), " &&\n")
@@ -2805,21 +2813,20 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
return CGAbstractMethod.define(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():
function = "GetConstructorObject"
else:
function = "GetProtoObject"
return CGGeneric("""\
assert!(!global.get().is_null());
-%s
+
+if !ConstructorEnabled(cx, global) {
+ return;
+}
+
rooted!(in(cx) let mut proto = ptr::null_mut());
%s(cx, global, proto.handle_mut());
-assert!(!proto.is_null());""" % (getCheck(self.descriptor), function))
+assert!(!proto.is_null());""" % (function,))
def needCx(returnType, arguments, considerTypes):
@@ -5133,8 +5140,7 @@ class CGDescriptor(CGThing):
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
- if descriptor.isExposedConditionally():
- cgThings.append(CGConstructorEnabled(descriptor))
+ cgThings.append(CGConstructorEnabled(descriptor))
if descriptor.proxy:
cgThings.append(CGDefineProxyHandler(descriptor))
@@ -5555,6 +5561,7 @@ class CGBindingRoot(CGThing):
'js::glue::AppendToAutoIdVector',
'js::rust::{GCMethods, define_methods, define_properties}',
'dom::bindings',
+ 'dom::bindings::codegen::InterfaceObjectMap',
'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
@@ -5562,6 +5569,7 @@ class CGBindingRoot(CGThing):
'dom::bindings::interface::{define_guarded_methods, define_guarded_properties}',
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
+ 'dom::bindings::interface::is_exposed_in',
'dom::bindings::js::{JS, Root, RootedReference}',
'dom::bindings::js::{OptionalRootedReference}',
'dom::bindings::reflector::{Reflectable}',
@@ -6215,6 +6223,10 @@ class CallbackSetter(CallbackMember):
return None
+def camel_to_upper_snake(s):
+ return "_".join(m.group(0).upper() for m in re.finditer("[A-Z][a-z]*", s))
+
+
class GlobalGenRoots():
"""
Roots for global codegen.
@@ -6232,6 +6244,18 @@ class GlobalGenRoots():
]
imports = CGList([CGGeneric("use %s;" % mod) for mod in mods], "\n")
+ global_descriptors = config.getDescriptors(isGlobal=True)
+ flags = [("EMPTY", 0)]
+ flags.extend(
+ (camel_to_upper_snake(d.name), 2 ** idx)
+ for (idx, d) in enumerate(global_descriptors)
+ )
+ global_flags = CGWrapper(CGIndenter(CGList([
+ CGGeneric("const %s = %#x," % args)
+ for args in flags
+ ], "\n")), pre="pub flags Globals: u8 {\n", post="\n}")
+ globals_ = CGWrapper(CGIndenter(global_flags), pre="bitflags! {\n", post="\n}")
+
pairs = []
for d in config.getDescriptors(hasInterfaceObject=True):
binding = toBindingNamespace(d.name)
@@ -6251,7 +6275,7 @@ class GlobalGenRoots():
return CGList([
CGGeneric(AUTOGENERATED_WARNING_COMMENT),
- CGList([imports, phf], "\n\n")
+ CGList([imports, globals_, phf], "\n\n")
])
@staticmethod
diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py
index 805bcb1a758..9a39b1bc623 100644
--- a/components/script/dom/bindings/codegen/Configuration.py
+++ b/components/script/dom/bindings/codegen/Configuration.py
@@ -85,6 +85,8 @@ class Configuration:
getter = lambda x: x.interface.isCallback()
elif key == 'isJSImplemented':
getter = lambda x: x.interface.isJSImplemented()
+ elif key == 'isGlobal':
+ getter = lambda x: x.isGlobal()
else:
getter = lambda x: getattr(x, key)
curr = filter(lambda x: getter(x) == val, curr)
diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs
index c61a3f211c4..4e2c630a453 100644
--- a/components/script/dom/bindings/interface.rs
+++ b/components/script/dom/bindings/interface.rs
@@ -4,6 +4,7 @@
//! Machinery to initialise interface prototype objects and interface objects.
+use dom::bindings::codegen::InterfaceObjectMap::Globals;
use dom::bindings::codegen::PrototypeList;
use dom::bindings::conversions::get_dom_class;
use dom::bindings::guard::Guard;
@@ -484,3 +485,11 @@ unsafe extern "C" fn non_new_constructor(
throw_type_error(cx, "This constructor needs to be called with `new`.");
false
}
+
+/// Returns whether an interface with exposure set given by `globals` should
+/// be exposed in the global object `obj`.
+pub unsafe fn is_exposed_in(object: HandleObject, globals: Globals) -> bool {
+ let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ 0);
+ let dom_class = get_dom_class(unwrapped).unwrap();
+ globals.contains(dom_class.global)
+}
diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs
index e7085bf424a..6b2856e7a9e 100644
--- a/components/script/dom/bindings/utils.rs
+++ b/components/script/dom/bindings/utils.rs
@@ -93,6 +93,9 @@ pub struct DOMClass {
/// The HeapSizeOf function wrapper for that interface.
pub heap_size_of: unsafe fn(*const c_void) -> usize,
+
+ /// The `Globals` flag for this global interface, if any.
+ pub global: InterfaceObjectMap::Globals,
}
unsafe impl Sync for DOMClass {}