aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py303
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py10
-rw-r--r--components/script/dom/bindings/utils.rs8
-rw-r--r--components/script/dom/webidls/Document.webidl2
-rw-r--r--components/script/dom/webidls/Location.webidl2
-rw-r--r--components/script/dom/webidls/Window.webidl4
-rw-r--r--components/script/dom/xmldocument.rs6
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()