зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1104955 part 3. Pass our unscopable names to CreateInterfaceObjects and have it define the right thing on the prototype. r=khuey
This commit is contained in:
Родитель
99babb71e8
Коммит
4622df74e0
|
@ -766,7 +766,8 @@ CreateInterfacePrototypeObject(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
JS::Handle<JSObject*> parentProto,
|
||||
const js::Class* protoClass,
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties)
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* const* unscopableNames)
|
||||
{
|
||||
JS::Rooted<JSObject*> ourProto(cx,
|
||||
JS_NewObjectWithUniqueType(cx, Jsvalify(protoClass), parentProto));
|
||||
|
@ -775,6 +776,28 @@ CreateInterfacePrototypeObject(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (unscopableNames) {
|
||||
JS::Rooted<JSObject*> unscopableObj(cx, JS_NewPlainObject(cx));
|
||||
if (!unscopableObj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (; *unscopableNames; ++unscopableNames) {
|
||||
if (!JS_DefineProperty(cx, unscopableObj, *unscopableNames,
|
||||
JS::TrueHandleValue, JSPROP_ENUMERATE)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JS::Rooted<jsid> unscopableId(cx,
|
||||
SYMBOL_TO_JSID(JS::GetWellKnownSymbol(cx, JS::SymbolCode::unscopables)));
|
||||
// Readonly and non-enumerable to match Array.prototype.
|
||||
if (!JS_DefinePropertyById(cx, ourProto, unscopableId, unscopableObj,
|
||||
JSPROP_READONLY)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return ourProto;
|
||||
}
|
||||
|
||||
|
@ -830,7 +853,8 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
JS::Heap<JSObject*>* constructorCache,
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name, bool defineOnGlobal)
|
||||
const char* name, bool defineOnGlobal,
|
||||
const char* const* unscopableNames)
|
||||
{
|
||||
MOZ_ASSERT(protoClass || constructorClass || constructor,
|
||||
"Need at least one class or a constructor!");
|
||||
|
@ -861,7 +885,8 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
if (protoClass) {
|
||||
proto =
|
||||
CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
|
||||
properties, chromeOnlyProperties);
|
||||
properties, chromeOnlyProperties,
|
||||
unscopableNames);
|
||||
if (!proto) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -594,6 +594,8 @@ struct NamedConstructor
|
|||
* false in situations where we want the properties to only
|
||||
* appear on privileged Xrays but not on the unprivileged
|
||||
* underlying global.
|
||||
* unscopableNames if not null it points to a null-terminated list of const
|
||||
* char* names of the unscopable properties for this interface.
|
||||
*
|
||||
* At least one of protoClass, constructorClass or constructor should be
|
||||
* non-null. If constructorClass or constructor are non-null, the resulting
|
||||
|
@ -610,7 +612,8 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
JS::Heap<JSObject*>* constructorCache,
|
||||
const NativeProperties* regularProperties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name, bool defineOnGlobal);
|
||||
const char* name, bool defineOnGlobal,
|
||||
const char* const* unscopableNames);
|
||||
|
||||
/**
|
||||
* Define the properties (regular and chrome-only) on obj.
|
||||
|
|
|
@ -2745,13 +2745,14 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
|
||||
properties should be a PropertyArrays instance.
|
||||
"""
|
||||
def __init__(self, descriptor, properties):
|
||||
def __init__(self, descriptor, properties, haveUnscopables):
|
||||
args = [Argument('JSContext*', 'aCx'),
|
||||
Argument('JS::Handle<JSObject*>', 'aGlobal'),
|
||||
Argument('ProtoAndIfaceCache&', 'aProtoAndIfaceCache'),
|
||||
Argument('bool', 'aDefineOnGlobal')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
|
||||
self.properties = properties
|
||||
self.haveUnscopables = haveUnscopables
|
||||
|
||||
def definition_body(self):
|
||||
(protoGetter, protoHandleGetter) = InterfacePrototypeObjectProtoGetter(self.descriptor)
|
||||
|
@ -2891,7 +2892,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
interfaceCache,
|
||||
${properties},
|
||||
${chromeProperties},
|
||||
${name}, aDefineOnGlobal);
|
||||
${name}, aDefineOnGlobal,
|
||||
${unscopableNames});
|
||||
""",
|
||||
protoClass=protoClass,
|
||||
parentProto=parentProto,
|
||||
|
@ -2903,7 +2905,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
interfaceCache=interfaceCache,
|
||||
properties=properties,
|
||||
chromeProperties=chromeProperties,
|
||||
name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr")
|
||||
name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr",
|
||||
unscopableNames="unscopableNames" if self.haveUnscopables else "nullptr")
|
||||
|
||||
# If we fail after here, we must clear interface and prototype caches
|
||||
# using this code: intermediate failure must not expose the interface in
|
||||
|
@ -12078,7 +12081,8 @@ class CGDescriptor(CGThing):
|
|||
|
||||
# CGCreateInterfaceObjectsMethod needs to come after our
|
||||
# CGDOMJSClass and unscopables, if any.
|
||||
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
|
||||
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties,
|
||||
haveUnscopables))
|
||||
|
||||
# CGGetProtoObjectMethod and CGGetConstructorObjectMethod need
|
||||
# to come after CGCreateInterfaceObjectsMethod.
|
||||
|
|
|
@ -34873,6 +34873,12 @@
|
|||
"url": "/dom/collections/HTMLCollection-as-proto-length-get-throws.html"
|
||||
}
|
||||
],
|
||||
"dom/nodes/remove-unscopable.html": [
|
||||
{
|
||||
"path": "dom/nodes/remove-unscopable.html",
|
||||
"url": "/dom/nodes/remove-unscopable.html"
|
||||
}
|
||||
],
|
||||
"js/builtins/Promise-incumbent-global.sub.html": [
|
||||
{
|
||||
"path": "js/builtins/Promise-incumbent-global.sub.html",
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title></title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<div id="testDiv" onclick="result1 = remove; result2 = this.remove;"></div>
|
||||
<script>
|
||||
var remove = "Hello there";
|
||||
var result1;
|
||||
var result2;
|
||||
test(function() {
|
||||
assert_true(Element.prototype[Symbol.unscopables].remove);
|
||||
var div = document.querySelector("#testDiv");
|
||||
div.dispatchEvent(new Event("click"));
|
||||
assert_equals(typeof result1, "string");
|
||||
assert_equals(typeof result2, "function");
|
||||
}, "remove() should be unscopable")
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче