Bug 1555085. Don't assume that objects whose DOMObjectType is eInterface have a DOMIfaceAndProtoJSClass JSClass. r=peterv

Named constructors are eInterface but are plain Function objects, without a
DOMIfaceAndProtoJSClass class.

Differential Revision: https://phabricator.services.mozilla.com/D32941

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Zbarsky 2019-06-04 09:49:24 +00:00
parent 89b8d31ca7
commit 34522cf0c8
2 changed files with 75 additions and 45 deletions

View File

@ -1731,45 +1731,51 @@ static void DEBUG_CheckXBLLookup(JSContext* cx, JS::PropertyDescriptor* desc) {
JSPROP_PERMANENT | JSPROP_READONLY, desc, cacheOnHolder);
}
if (id.get() == GetJSIDByIndex(cx, XPCJSContext::IDX_ISINSTANCE) &&
DOMIfaceAndProtoJSClass::FromJSClass(js::GetObjectClass(obj))
->wantsInterfaceHasInstance) {
cacheOnHolder = true;
JSNativeWrapper interfaceIsInstanceWrapper = {InterfaceIsInstance,
nullptr};
JSObject* funObj =
XrayCreateFunction(cx, wrapper, interfaceIsInstanceWrapper, 1, id);
if (!funObj) {
return false;
}
if (id.get() == GetJSIDByIndex(cx, XPCJSContext::IDX_ISINSTANCE)) {
const js::Class* objClass = js::GetObjectClass(obj);
if (IsDOMIfaceAndProtoClass(objClass) &&
DOMIfaceAndProtoJSClass::FromJSClass(objClass)
->wantsInterfaceHasInstance) {
cacheOnHolder = true;
JSNativeWrapper interfaceIsInstanceWrapper = {InterfaceIsInstance,
nullptr};
JSObject* funObj =
XrayCreateFunction(cx, wrapper, interfaceIsInstanceWrapper, 1, id);
if (!funObj) {
return false;
}
desc.value().setObject(*funObj);
desc.setAttributes(0);
desc.object().set(wrapper);
desc.setSetter(nullptr);
desc.setGetter(nullptr);
return true;
desc.value().setObject(*funObj);
desc.setAttributes(0);
desc.object().set(wrapper);
desc.setSetter(nullptr);
desc.setGetter(nullptr);
return true;
}
}
if (id.get() == SYMBOL_TO_JSID(JS::GetWellKnownSymbol(
cx, JS::SymbolCode::hasInstance)) &&
DOMIfaceAndProtoJSClass::FromJSClass(js::GetObjectClass(obj))
->wantsInterfaceHasInstance) {
cacheOnHolder = true;
JSNativeWrapper interfaceHasInstanceWrapper = {InterfaceHasInstance,
nullptr};
JSObject* funObj =
XrayCreateFunction(cx, wrapper, interfaceHasInstanceWrapper, 1, id);
if (!funObj) {
return false;
}
cx, JS::SymbolCode::hasInstance))) {
const js::Class* objClass = js::GetObjectClass(obj);
if (IsDOMIfaceAndProtoClass(objClass) &&
DOMIfaceAndProtoJSClass::FromJSClass(objClass)
->wantsInterfaceHasInstance) {
cacheOnHolder = true;
JSNativeWrapper interfaceHasInstanceWrapper = {InterfaceHasInstance,
nullptr};
JSObject* funObj =
XrayCreateFunction(cx, wrapper, interfaceHasInstanceWrapper, 1, id);
if (!funObj) {
return false;
}
desc.value().setObject(*funObj);
desc.setAttributes(JSPROP_READONLY | JSPROP_PERMANENT);
desc.object().set(wrapper);
desc.setSetter(nullptr);
desc.setGetter(nullptr);
return true;
desc.value().setObject(*funObj);
desc.setAttributes(JSPROP_READONLY | JSPROP_PERMANENT);
desc.object().set(wrapper);
desc.setSetter(nullptr);
desc.setGetter(nullptr);
return true;
}
}
} else {
MOZ_ASSERT(IsInterfacePrototype(type));

View File

@ -28,26 +28,33 @@ function checkXrayProperty(obj, name, values) {
do {
var value = values.shift();
if (typeof value == "undefined") {
ok(!obj.hasOwnProperty(name), "hasOwnProperty shouldn't see \"" + name + "\" through Xrays");
is(Object.getOwnPropertyDescriptor(obj, name), undefined, "getOwnPropertyDescriptor shouldn't see \"" + name + "\" through Xrays");
ok(!Object.keys(obj).includes(name), "Enumerating the Xray should not return \"" + name + "\"");
ok(!obj.hasOwnProperty(name), "hasOwnProperty shouldn't see \"" + String(name) + "\" through Xrays");
is(Object.getOwnPropertyDescriptor(obj, name), undefined, "getOwnPropertyDescriptor shouldn't see \"" + String(name) + "\" through Xrays");
ok(!Object.keys(obj).includes(name), "Enumerating the Xray should not return \"" + String(name) + "\"");
ok(!Object.getOwnPropertyNames(obj).includes(name),
`The Xray's property names should not include ${name}`);
`The Xray's property names should not include ${String(name)}`);
ok(!Object.getOwnPropertySymbols(obj).includes(name),
`The Xray's property symbols should not include ${String(name)}`);
} else {
ok(obj.hasOwnProperty(name), "hasOwnProperty should see \"" + name + "\" through Xrays");
ok(obj.hasOwnProperty(name), "hasOwnProperty should see \"" + String(name) + "\" through Xrays");
var pd = Object.getOwnPropertyDescriptor(obj, name);
ok(pd, "getOwnPropertyDescriptor should see \"" + name + "\" through Xrays");
ok(pd, "getOwnPropertyDescriptor should see \"" + String(name) + "\" through Xrays");
if (pd && pd.get) {
is(pd.get.call(instance), value, "Should get the right value for \"" + name + "\" through Xrays");
is(pd.get.call(instance), value, "Should get the right value for \"" + String(name) + "\" through Xrays");
} else {
is(obj[name], value, "Should get the right value for \"" + name + "\" through Xrays");
is(obj[name], value, "Should get the right value for \"" + String(name) + "\" through Xrays");
}
if (pd) {
if (pd.enumerable) {
ok(Object.keys(obj).indexOf("" + name) > -1, "Enumerating the Xray should return \"" + name + "\"");
ok(Object.keys(obj).indexOf("" + name) > -1, "Enumerating the Xray should return \"" + String(name) + "\"");
}
if (typeof name == "symbol") {
ok(Object.getOwnPropertySymbols(obj).includes(name),
`The Xray's property symbols should include ${String(name)}`);
} else {
ok(Object.getOwnPropertyNames(obj).includes("" + name),
`The Xray's property names should include ${name}`);
}
ok(Object.getOwnPropertyNames(obj).indexOf("" + name) > -1,
`The Xray's property names should include ${name}`);
}
}
} while ((obj = Object.getPrototypeOf(obj)));
@ -294,6 +301,23 @@ function test() {
is(elem.wrappedJSObject, undefined, "Shouldn't be an Xray anymore");
is(elem.expando, 5, "Expando should not get lost");
// Instanceof tests
var img = doc.createElement("img");
var img2 = document.createElement("img");
ok(img instanceof win.HTMLImageElement,
"Should be an instance of HTMLImageElement from its global");
ok(win.HTMLImageElement.isInstance(img), "isInstance should work");
ok(HTMLImageElement.isInstance(img), "isInstance should work cross-global");
ok(win.HTMLImageElement.isInstance(img2),
"isInstance should work cross-global in the other direction");
ok(img instanceof win.Image,
"Should be an instance of Image, because Image.prototype == HTMLImageElement.prototype");
ok(!win.Image.isInstance, "Shouldn't have an isInstance method here");
// Image does not have a Symbol.hasInstance, but its proto
// (Function.prototype) does.
checkXrayProperty(win.Image, Symbol.hasInstance,
[undefined, win.Function.prototype[Symbol.hasInstance]]);
SimpleTest.finish();
}