diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 303 | ||||
-rw-r--r-- | components/script/dom/bindings/codegen/Configuration.py | 10 | ||||
-rw-r--r-- | components/script/dom/bindings/utils.rs | 8 | ||||
-rw-r--r-- | components/script/dom/webidls/Document.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/Location.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/Window.webidl | 4 | ||||
-rw-r--r-- | components/script/dom/xmldocument.rs | 6 |
7 files changed, 253 insertions, 82 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index eaf2bbe0fe7..d88e6d9fa32 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -21,7 +21,12 @@ from WebIDL import ( IDLUndefinedValue, ) -from Configuration import getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback +from Configuration import ( + MemberIsUnforgeable, + getTypesFromCallback, + getTypesFromDescriptor, + getTypesFromDictionary, +) AUTOGENERATED_WARNING_COMMENT = \ "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n" @@ -1380,7 +1385,8 @@ class MethodDefiner(PropertyDefiner): """ A class for defining methods on a prototype object. """ - def __init__(self, descriptor, name, static): + def __init__(self, descriptor, name, static, unforgeable): + assert not (static and unforgeable) PropertyDefiner.__init__(self, descriptor, name) # FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=772822 @@ -1391,36 +1397,40 @@ class MethodDefiner(PropertyDefiner): if not descriptor.interface.isCallback() or static: methods = [m for m in descriptor.interface.members if m.isMethod() and m.isStatic() == static and - not m.isIdentifierLess()] + not m.isIdentifierLess() and + MemberIsUnforgeable(m, descriptor) == unforgeable] else: methods = [] self.regular = [{"name": m.identifier.name, "methodInfo": not m.isStatic(), - "length": methodLength(m), - "flags": "JSPROP_ENUMERATE"} for m in methods] + "length": methodLength(m)} for m in methods] # FIXME Check for an existing iterator on the interface first. if any(m.isGetter() and m.isIndexed() for m in methods): self.regular.append({"name": '@@iterator', "methodInfo": False, "selfHostedName": "ArrayValues", - "length": 0, - "flags": "JSPROP_ENUMERATE"}) + "length": 0}) - if not static: + isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable")) + if not static and unforgeable == isUnforgeableInterface: stringifier = descriptor.operations['Stringifier'] if stringifier: self.regular.append({ "name": "toString", "nativeName": stringifier.identifier.name, "length": 0, - "flags": "JSPROP_ENUMERATE" }) + self.unforgeable = unforgeable def generateArray(self, array, name): if len(array) == 0: return "" + flags = "JSPROP_ENUMERATE" + if self.unforgeable: + flags += " | JSPROP_PERMANENT | JSPROP_READONLY" + def specData(m): # TODO: Use something like JS_FNSPEC # https://github.com/servo/servo/issues/6391 @@ -1444,16 +1454,16 @@ class MethodDefiner(PropertyDefiner): accessor = 'Some(%s)' % m.get("nativeName", m["name"]) if m["name"].startswith("@@"): return ('(SymbolCode::%s as i32 + 1)' - % m["name"][2:], accessor, jitinfo, m["length"], m["flags"], selfHostedName) - return (str_to_const_array(m["name"]), accessor, jitinfo, m["length"], m["flags"], selfHostedName) + % m["name"][2:], accessor, jitinfo, m["length"], flags, selfHostedName) + return (str_to_const_array(m["name"]), accessor, jitinfo, m["length"], flags, selfHostedName) return self.generatePrefableArray( array, name, ' JSFunctionSpec {\n' ' name: %s as *const u8 as *const libc::c_char,\n' - ' call: JSNativeWrapper {op: %s, info: %s},\n' + ' call: JSNativeWrapper { op: %s, info: %s },\n' ' nargs: %s,\n' - ' flags: %s as u16,\n' + ' flags: (%s) as u16,\n' ' selfHostedName: %s\n' ' }', ' JSFunctionSpec {\n' @@ -1468,23 +1478,27 @@ class MethodDefiner(PropertyDefiner): class AttrDefiner(PropertyDefiner): - def __init__(self, descriptor, name, static): + def __init__(self, descriptor, name, static, unforgeable): + assert not (static and unforgeable) PropertyDefiner.__init__(self, descriptor, name) self.name = name self.descriptor = descriptor self.regular = [ m - for m in descriptor.interface.members - if m.isAttr() and m.isStatic() == static + for m in descriptor.interface.members if + m.isAttr() and m.isStatic() == static and + MemberIsUnforgeable(m, descriptor) == unforgeable ] self.static = static + self.unforgeable = unforgeable def generateArray(self, array, name): if len(array) == 0: return "" - def flags(attr): - return "JSPROP_SHARED | JSPROP_ENUMERATE" + flags = "JSPROP_ENUMERATE | JSPROP_SHARED" + if self.unforgeable: + flags += " | JSPROP_READONLY | JSPROP_PERMANENT" def getter(attr): if self.static: @@ -1520,7 +1534,7 @@ class AttrDefiner(PropertyDefiner): "native": accessor}) def specData(attr): - return (str_to_const_array(attr.identifier.name), flags(attr), getter(attr), + return (str_to_const_array(attr.identifier.name), flags, getter(attr), setter(attr)) return self.generatePrefableArray( @@ -1844,10 +1858,16 @@ class CGPrototypeJSClass(CGThing): self.descriptor = descriptor def define(self): + name = str_to_const_array(self.descriptor.interface.identifier.name + "Prototype") + slotCount = 0 + if self.descriptor.hasUnforgeableMembers: + slotCount += 1 return """\ static PrototypeClass: JSClass = JSClass { - name: %s as *const u8 as *const libc::c_char, - flags: 0, + name: %(name)s as *const u8 as *const libc::c_char, + flags: + // JSCLASS_HAS_RESERVED_SLOTS(%(slotCount)s) + (%(slotCount)s & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT, addProperty: None, delProperty: None, getProperty: None, @@ -1862,7 +1882,7 @@ static PrototypeClass: JSClass = JSClass { trace: None, reserved: [0 as *mut libc::c_void; 25] }; -""" % str_to_const_array(self.descriptor.interface.identifier.name + "Prototype") +""" % {'name': name, 'slotCount': slotCount} class CGInterfaceObjectJSClass(CGThing): @@ -2181,6 +2201,68 @@ JS_SetReservedSlot(obj.ptr, DOM_WEAK_SLOT, PrivateValue(ptr::null()));""" return create +def InitUnforgeablePropertiesOnHolder(descriptor, properties): + """ + Define the unforgeable properties on the unforgeable holder for + the interface represented by descriptor. + + properties is a PropertyArrays instance. + """ + unforgeables = [] + + defineUnforgeableAttrs = "define_properties(cx, unforgeable_holder.handle(), %s).unwrap();" + defineUnforgeableMethods = "define_methods(cx, unforgeable_holder.handle(), %s).unwrap();" + + unforgeableMembers = [ + (defineUnforgeableAttrs, properties.unforgeable_attrs), + (defineUnforgeableMethods, properties.unforgeable_methods), + ] + for template, array in unforgeableMembers: + if array.length() > 0: + unforgeables.append(CGGeneric(template % array.variableName())) + return CGList(unforgeables, "\n") + + +def CopyUnforgeablePropertiesToInstance(descriptor): + """ + Copy the unforgeable properties from the unforgeable holder for + this interface to the instance object we have. + """ + if not descriptor.hasUnforgeableMembers: + return "" + copyCode = "" + + # For proxies, we want to define on the expando object, not directly on the + # reflector, so we can make sure we don't get confused by named getters. + if descriptor.proxy: + copyCode += """\ +let mut expando = RootedObject::new(cx, ptr::null_mut()); +{ + let _ac = JSAutoCompartment::new(cx, scope.get()); + expando.handle_mut().set(ensure_expando_object(cx, obj.handle())); +} +""" + obj = "expando" + else: + obj = "obj" + + # We can't do the fast copy for globals, because we can't allocate the + # unforgeable holder for those with the right JSClass. Luckily, there + # aren't too many globals being created. + if descriptor.isGlobal(): + copyFunc = "JS_CopyPropertiesFrom" + else: + copyFunc = "JS_InitializePropertiesFromCompatibleNativeObject" + copyCode += """\ +let mut unforgeable_holder = RootedObject::new(cx, ptr::null_mut()); +unforgeable_holder.handle_mut().set( + JS_GetReservedSlot(proto.ptr, DOM_PROTO_UNFORGEABLE_HOLDER_SLOT).to_object()); +assert!(%(copyFunc)s(cx, %(obj)s.handle(), unforgeable_holder.handle())); +""" % {'copyFunc': copyFunc, 'obj': obj} + + return copyCode + + class CGWrapMethod(CGAbstractMethod): """ Class that generates the FooBinding::Wrap function for non-callback @@ -2199,7 +2281,9 @@ class CGWrapMethod(CGAbstractMethod): pub=True, unsafe=True) def definition_body(self): + unforgeable = CopyUnforgeablePropertiesToInstance(self.descriptor) if not self.descriptor.isGlobal(): + create = CreateBindingJSObject(self.descriptor, "scope") return CGGeneric("""\ let _ar = JSAutoRequest::new(cx); let scope = scope.reflector().get_jsobject(); @@ -2213,28 +2297,31 @@ let mut proto = RootedObject::new(cx, ptr::null_mut()); } assert!(!proto.ptr.is_null()); -%s +%(createObject)s +%(copyUnforgeable)s (*raw).init_reflector(obj.ptr); -Root::from_ref(&*raw)""" % CreateBindingJSObject(self.descriptor, "scope")) +Root::from_ref(&*raw)""" % {'copyUnforgeable': unforgeable, 'createObject': create}) else: + create = CreateBindingJSObject(self.descriptor) return CGGeneric("""\ let _ar = JSAutoRequest::new(cx); -%s +%(createObject)s let _ac = JSAutoCompartment::new(cx, obj.ptr); let mut proto = RootedObject::new(cx, ptr::null_mut()); GetProtoObject(cx, obj.handle(), obj.handle(), proto.handle_mut()); JS_SetPrototype(cx, obj.handle(), proto.handle()); +%(copyUnforgeable)s (*raw).init_reflector(obj.ptr); let ret = Root::from_ref(&*raw); RegisterBindings::Register(cx, obj.handle()); -ret""" % CreateBindingJSObject(self.descriptor)) +ret""" % {'copyUnforgeable': unforgeable, 'createObject': create}) class CGIDLInterface(CGThing): @@ -2279,17 +2366,29 @@ class CGAbstractExternMethod(CGAbstractMethod): class PropertyArrays(): def __init__(self, descriptor): self.static_methods = MethodDefiner(descriptor, "StaticMethods", - static=True) + static=True, unforgeable=False) self.static_attrs = AttrDefiner(descriptor, "StaticAttributes", - static=True) - self.methods = MethodDefiner(descriptor, "Methods", static=False) - self.attrs = AttrDefiner(descriptor, "Attributes", static=False) + static=True, unforgeable=False) + self.methods = MethodDefiner(descriptor, "Methods", static=False, unforgeable=False) + self.unforgeable_methods = MethodDefiner(descriptor, "UnforgeableMethods", + static=False, unforgeable=True) + self.attrs = AttrDefiner(descriptor, "Attributes", static=False, unforgeable=False) + self.unforgeable_attrs = AttrDefiner(descriptor, "UnforgeableAttributes", + static=False, unforgeable=True) self.consts = ConstDefiner(descriptor, "Constants") pass @staticmethod def arrayNames(): - return ["static_methods", "static_attrs", "methods", "attrs", "consts"] + return [ + "static_methods", + "static_attrs", + "methods", + "unforgeable_methods", + "attrs", + "unforgeable_attrs", + "consts", + ] def variableNames(self): names = {} @@ -2392,10 +2491,54 @@ let named_constructors: [(NonNullJSNative, &'static str, u32); %d] = [ createArray += "," createArray += "];" + if self.descriptor.hasUnforgeableMembers: + # We want to use the same JSClass and prototype as the object we'll + # end up defining the unforgeable properties on in the end, so that + # we can use JS_InitializePropertiesFromCompatibleNativeObject to do + # a fast copy. In the case of proxies that's null, because the + # expando object is a vanilla object, but in the case of other DOM + # objects it's whatever our class is. + # + # Also, for a global we can't use the global's class; just use + # nullpr and when we do the copy off the holder we'll take a slower + # path. This also means that we don't need to worry about matching + # the prototype. + if self.descriptor.proxy or self.descriptor.isGlobal(): + holderClass = "ptr::null()" + holderProto = "ptr::null_mut()" + else: + holderClass = "&Class.base as *const js::jsapi::Class as *const JSClass" + holderProto = "rval.get()" + # JS_NewObjectWithoutMetadata() is unsafe. + self.unsafe = True + createUnforgeableHolder = CGGeneric(""" +let mut unforgeable_holder = RootedObject::new(cx, ptr::null_mut()); +{ + let holder_class = %(holderClass)s; + let holder_proto = RootedObject::new(cx, %(holderProto)s); + unforgeable_holder.handle_mut().set( + JS_NewObjectWithoutMetadata(cx, holder_class, holder_proto.handle())); + assert!(!unforgeable_holder.ptr.is_null()); +}""" % {'holderClass': holderClass, 'holderProto': holderProto}) + defineUnforgeables = InitUnforgeablePropertiesOnHolder(self.descriptor, + self.properties) + createUnforgeableHolder = CGList( + [createUnforgeableHolder, defineUnforgeables], "\n") + + installUnforgeableHolder = CGGeneric("""\ +JS_SetReservedSlot(rval.get(), DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, + ObjectValue(&*unforgeable_holder.ptr))""") + + unforgeableHolderSetup = CGList( + [createUnforgeableHolder, installUnforgeableHolder], "\n") + else: + unforgeableHolderSetup = None + return CGList([ CGGeneric(getParentProto), CGGeneric(createArray), - CGGeneric(call % self.properties.variableNames()) + CGGeneric(call % self.properties.variableNames()), + unforgeableHolderSetup, ], "\n") @@ -4269,6 +4412,9 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod): namedSetter = self.descriptor.operations['NamedSetter'] if namedSetter: + if self.descriptor.hasUnforgeableMembers: + raise TypeError("Can't handle a named setter on an interface that has " + "unforgeables. Figure out how that should work!") set += ("if RUST_JSID_IS_STRING(id) {\n" + CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + " (*opresult).code_ = 0; /* SpecialCodes::OkCode */\n" + @@ -4308,6 +4454,9 @@ class CGDOMJSProxyHandler_delete(CGAbstractExternMethod): def getBody(self): set = "" if self.descriptor.operations['NamedDeleter']: + if self.descriptor.hasUnforgeableMembers: + raise TypeError("Can't handle a deleter on an interface that has " + "unforgeables. Figure out how that should work!") set += CGProxyNamedDeleter(self.descriptor).define() set += "return proxyhandler::delete(%s);" % ", ".join(a.name for a in self.args) return set @@ -4422,7 +4571,7 @@ return true;""" class CGDOMJSProxyHandler_get(CGAbstractExternMethod): def __init__(self, descriptor): args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', 'proxy'), - Argument('HandleObject', '_receiver'), Argument('HandleId', 'id'), + Argument('HandleObject', 'receiver'), Argument('HandleId', 'id'), Argument('MutableHandleValue', 'vp')] CGAbstractExternMethod.__init__(self, descriptor, "get", "bool", args) self.descriptor = descriptor @@ -4437,7 +4586,7 @@ if !expando.ptr.is_null() { } if hasProp { - return JS_GetPropertyById(cx, expando.handle(), id, vp); + return JS_ForwardGetPropertyTo(cx, expando.handle(), id, receiver, vp); } }""" @@ -4554,7 +4703,10 @@ if !weak_box_ptr.is_null() { } """ % descriptor.concreteType release += """\ -let _ = Box::from_raw(this as *mut %s); +if !this.is_null() { + // The pointer can be null if the object is the unforgeable holder of that interface. + let _ = Box::from_raw(this as *mut %s); +} debug!("%s finalize: {:p}", this);\ """ % (descriptor.concreteType, descriptor.concreteType) return release @@ -5177,30 +5329,31 @@ class CGBindingRoot(CGThing): # Add imports curr = CGImports(curr, descriptors + callbackDescriptors, mainCallbacks, [ 'js', - 'js::JS_CALLEE', - 'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS, JSCLASS_IMPLEMENTS_BARRIERS}', - 'js::{JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_SHIFT}', - 'js::{JSCLASS_RESERVED_SLOTS_MASK}', - 'js::{JSPROP_ENUMERATE, JSPROP_SHARED}', - 'js::{JSITER_OWNONLY, JSITER_HIDDEN, JSITER_SYMBOLS}', + 'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IMPLEMENTS_BARRIERS}', + 'js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_MASK}', + 'js::{JSCLASS_RESERVED_SLOTS_SHIFT, JSITER_HIDDEN, JSITER_OWNONLY}', + 'js::{JSITER_SYMBOLS, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY}', + 'js::{JSPROP_SHARED, JS_CALLEE}', 'js::error::throw_type_error', - 'js::jsapi::{JS_CallFunctionValue, JS_GetClass, JS_GetGlobalForObject}', - 'js::jsapi::{JS_GetObjectPrototype, JS_GetProperty, JS_GetPropertyById}', - 'js::jsapi::{JS_GetPropertyDescriptorById, JS_GetReservedSlot}', - 'js::jsapi::{JS_HasProperty, JS_HasPropertyById, JS_IsExceptionPending}', - 'js::jsapi::{JS_NewObjectWithGivenProto, JS_NewObject, IsCallable, JS_SetProperty, JS_SetPrototype}', - 'js::jsapi::{JS_SetReservedSlot, JS_WrapValue, JSContext}', - 'js::jsapi::{JSClass, FreeOp, JSFreeOp, JSFunctionSpec, jsid}', - 'js::jsapi::{MutableHandleValue, MutableHandleObject, HandleObject, HandleValue, RootedObject}', - 'js::jsapi::{RootedValue, JSNativeWrapper, JSNative, JSObject, JSPropertyDescriptor}', - 'js::jsapi::{RootedId, JS_InternString, RootedString, INTERNED_STRING_TO_JSID}', - 'js::jsapi::{JSPropertySpec}', - 'js::jsapi::{JSString, JSTracer, JSJitInfo, JSTypedMethodJitInfo, OpType, AliasSet, ArgType}', - 'js::jsapi::{MutableHandle, Handle, HandleId, JSType, JSValueType}', - 'js::jsapi::{SymbolCode, ObjectOpResult, HandleValueArray}', - 'js::jsapi::{JSJitGetterCallArgs, JSJitSetterCallArgs, JSJitMethodCallArgs, CallArgs}', - 'js::jsapi::{JSAutoCompartment, JSAutoRequest, JS_ComputeThis}', - 'js::jsapi::{GetGlobalForObjectCrossCompartment, AutoIdVector, GetPropertyKeys}', + 'js::jsapi::{AliasSet, ArgType, AutoIdVector, CallArgs, FreeOp}', + 'js::jsapi::{GetGlobalForObjectCrossCompartment , GetPropertyKeys, Handle}', + 'js::jsapi::{HandleId, HandleObject, HandleValue, HandleValueArray}', + 'js::jsapi::{INTERNED_STRING_TO_JSID, IsCallable, JS_CallFunctionValue}', + 'js::jsapi::{JS_ComputeThis, JS_CopyPropertiesFrom, JS_ForwardGetPropertyTo}', + 'js::jsapi::{JS_GetClass, JS_GetGlobalForObject, JS_GetObjectPrototype}', + 'js::jsapi::{JS_GetProperty, JS_GetPropertyById, JS_GetPropertyDescriptorById}', + 'js::jsapi::{JS_GetReservedSlot, JS_HasProperty, JS_HasPropertyById}', + 'js::jsapi::{JS_InitializePropertiesFromCompatibleNativeObject, JS_InternString}', + 'js::jsapi::{JS_IsExceptionPending, JS_NewObject, JS_NewObjectWithGivenProto}', + 'js::jsapi::{JS_NewObjectWithoutMetadata, JS_SetProperty, JS_SetPrototype}', + 'js::jsapi::{JS_SetReservedSlot, JS_WrapValue, JSAutoCompartment, JSAutoRequest}', + 'js::jsapi::{JSContext, JSClass, JSFreeOp, JSFunctionSpec, JSJitGetterCallArgs}', + 'js::jsapi::{JSJitInfo, JSJitMethodCallArgs, JSJitSetterCallArgs, JSNative}', + 'js::jsapi::{JSObject, JSNativeWrapper, JSPropertyDescriptor, JSPropertySpec}', + 'js::jsapi::{JSString, JSTracer, JSType, JSTypedMethodJitInfo, JSValueType}', + 'js::jsapi::{ObjectOpResult, OpType, MutableHandle, MutableHandleObject}', + 'js::jsapi::{MutableHandleValue, RootedId, RootedObject, RootedString}', + 'js::jsapi::{RootedValue, SymbolCode, jsid}', 'js::jsval::JSVal', 'js::jsval::{ObjectValue, ObjectOrNullValue, PrivateValue}', 'js::jsval::{NullValue, UndefinedValue}', @@ -5209,30 +5362,24 @@ class CGBindingRoot(CGThing): 'js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO}', 'js::glue::{RUST_JS_NumberValue, RUST_JSID_IS_STRING, int_to_jsid}', 'js::glue::AppendToAutoIdVector', - 'js::rust::GCMethods', + 'js::rust::{GCMethods, define_methods, define_properties}', 'dom::bindings', 'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}', 'dom::bindings::js::{JS, Root, RootedReference}', 'dom::bindings::js::{OptionalRootedReference}', 'dom::bindings::reflector::{Reflectable}', - 'dom::bindings::utils::{create_dom_global, do_create_interface_objects}', - 'dom::bindings::utils::ConstantSpec', - 'dom::bindings::utils::{DOMClass}', - 'dom::bindings::utils::{DOMJSClass, JSCLASS_DOM_GLOBAL}', - 'dom::bindings::utils::{find_enum_string_index, get_array_index_from_id}', - 'dom::bindings::utils::{get_property_on_prototype, get_proto_or_iface_array}', - 'dom::bindings::utils::{finalize_global, trace_global}', - 'dom::bindings::utils::has_property_on_prototype', - 'dom::bindings::utils::is_platform_object', - 'dom::bindings::utils::throwing_constructor', - 'dom::bindings::utils::get_dictionary_property', - 'dom::bindings::utils::set_dictionary_property', - 'dom::bindings::utils::{NativeProperties, NativePropertyHooks}', + 'dom::bindings::utils::{ConstantSpec, DOMClass, DOMJSClass}', + 'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}', + 'dom::bindings::utils::{NativeProperties, NativePropertyHooks, NonNullJSNative}', + 'dom::bindings::utils::{create_dom_global, do_create_interface_objects, finalize_global}', + 'dom::bindings::utils::{find_enum_string_index, generic_getter}', + 'dom::bindings::utils::{generic_lenient_getter, generic_lenient_setter}', + 'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}', + 'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}', + 'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}', + 'dom::bindings::utils::{is_platform_object, set_dictionary_property}', + 'dom::bindings::utils::{throwing_constructor, trace_global}', 'dom::bindings::utils::ConstantVal::{IntVal, UintVal}', - 'dom::bindings::utils::NonNullJSNative', - 'dom::bindings::utils::{generic_getter, generic_lenient_getter}', - 'dom::bindings::utils::{generic_lenient_setter, generic_method}', - 'dom::bindings::utils::generic_setter', 'dom::bindings::trace::{JSTraceable, RootedTraceable}', 'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}', 'dom::bindings::callback::{CallSetup,ExceptionHandling}', @@ -5248,8 +5395,8 @@ class CGBindingRoot(CGThing): 'dom::bindings::error::Error::JSFailed', 'dom::bindings::error::throw_dom_exception', 'dom::bindings::proxyhandler', - 'dom::bindings::proxyhandler::{fill_property_descriptor, get_expando_object}', - 'dom::bindings::proxyhandler::{get_property_descriptor}', + 'dom::bindings::proxyhandler::{ensure_expando_object, fill_property_descriptor}', + 'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}', 'dom::bindings::num::Finite', 'dom::bindings::str::ByteString', 'dom::bindings::str::USVString', diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py index 4f59ff09f5b..d0af7e37929 100644 --- a/components/script/dom/bindings/codegen/Configuration.py +++ b/components/script/dom/bindings/codegen/Configuration.py @@ -139,6 +139,13 @@ class DescriptorProvider: return self.config.getDescriptor(interfaceName) +def MemberIsUnforgeable(member, descriptor): + return ((member.isAttr() or member.isMethod()) and + not member.isStatic() and + (member.isUnforgeable() or + bool(descriptor.interface.getExtendedAttribute("Unforgeable")))) + + class Descriptor(DescriptorProvider): """ Represents a single descriptor for an interface. See Bindings.conf. @@ -174,6 +181,9 @@ class Descriptor(DescriptorProvider): # them as having a concrete descendant. self.concrete = (not self.interface.isCallback() and desc.get('concrete', True)) + self.hasUnforgeableMembers = (self.concrete and + any(MemberIsUnforgeable(m, self) for m in + self.interface.members)) self.operations = { 'IndexedGetter': None, diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 97d5bb12eba..fe7c8030baa 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -78,6 +78,10 @@ impl GlobalStaticData { } } +/// The index of the slot where the object holder of that interface's +/// unforgeable members are defined. +pub const DOM_PROTO_UNFORGEABLE_HOLDER_SLOT: u32 = 0; + /// The index of the slot that contains a reference to the ProtoOrIfaceArray. // All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. pub const DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT; @@ -181,8 +185,12 @@ pub fn get_proto_or_iface_array(global: *mut JSObject) -> *mut ProtoOrIfaceArray pub struct NativeProperties { /// Instance methods for the interface. pub methods: Option<&'static [JSFunctionSpec]>, + /// Unforgeable instance methods for the interface. + pub unforgeable_methods: Option<&'static [JSFunctionSpec]>, /// Instance attributes for the interface. pub attrs: Option<&'static [JSPropertySpec]>, + /// Unforgeable instance attributes for the interface. + pub unforgeable_attrs: Option<&'static [JSPropertySpec]>, /// Constants for the interface. pub consts: Option<&'static [ConstantSpec]>, /// Static methods for the interface. diff --git a/components/script/dom/webidls/Document.webidl b/components/script/dom/webidls/Document.webidl index 863824338ed..9df747edc49 100644 --- a/components/script/dom/webidls/Document.webidl +++ b/components/script/dom/webidls/Document.webidl @@ -79,7 +79,7 @@ enum DocumentReadyState { "loading", "interactive", "complete" }; // [OverrideBuiltins] partial /*sealed*/ interface Document { // resource metadata management - // [PutForwards=href, Unforgeable] + [/*PutForwards=href, */Unforgeable] readonly attribute Location/*?*/ location; readonly attribute DOMString domain; // readonly attribute DOMString referrer; diff --git a/components/script/dom/webidls/Location.webidl b/components/script/dom/webidls/Location.webidl index f82031ac74b..8af05fbd178 100644 --- a/components/script/dom/webidls/Location.webidl +++ b/components/script/dom/webidls/Location.webidl @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://html.spec.whatwg.org/multipage/#location -/*[Unforgeable]*/ interface Location { +[Unforgeable] interface Location { /*stringifier*/ attribute USVString href; // attribute USVString origin; attribute USVString protocol; diff --git a/components/script/dom/webidls/Window.webidl b/components/script/dom/webidls/Window.webidl index 82a2f3fd34f..21ac6bf31a8 100644 --- a/components/script/dom/webidls/Window.webidl +++ b/components/script/dom/webidls/Window.webidl @@ -11,9 +11,9 @@ //[Replaceable] readonly attribute WindowProxy self; readonly attribute Window window; [BinaryName="Self_"] readonly attribute Window self; - /*[Unforgeable]*/ readonly attribute Document document; + [Unforgeable] readonly attribute Document document; // attribute DOMString name; - /*[PutForwards=href, Unforgeable]*/ readonly attribute Location location; + [/*PutForwards=href, */Unforgeable] readonly attribute Location location; //readonly attribute History history; //[Replaceable] readonly attribute BarProp locationbar; //[Replaceable] readonly attribute BarProp menubar; diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs index 0553760ca6c..6f73ecbf8ea 100644 --- a/components/script/dom/xmldocument.rs +++ b/components/script/dom/xmldocument.rs @@ -12,6 +12,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::js::{Root, RootedReference}; use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::document::{Document, DocumentSource, IsHTMLDocument}; +use dom::location::Location; use dom::node::Node; use dom::window::Window; use js::jsapi::{JSContext, JSObject}; @@ -85,6 +86,11 @@ impl XMLDocument { } impl XMLDocumentMethods for XMLDocument { + // https://html.spec.whatwg.org/multipage/#dom-document-location + fn Location(&self) -> Root<Location> { + self.document.Location() + } + // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:supported-property-names fn SupportedPropertyNames(&self) -> Vec<DOMString> { self.document.SupportedPropertyNames() |