mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 787070 - Expandos on the xray of DOM prototypes should have effect on xrays of DOM nodes, make Xrays walk the prototype chain when resolving DOM properties. r=bholley.
* * * Bug 787070 - Expandos on the xray of DOM prototypes should have effect on xrays of DOM nodes, remove obsolete code. r=bholley. --HG-- extra : rebase_source : 7a9aa81d3e9d74ed958374942020474147aa4f86
This commit is contained in:
parent
02658d3525
commit
d1b9102a2f
@ -250,7 +250,7 @@ const NativePropertyHooks sWindowNamedPropertiesNativePropertyHooks[] = { {
|
||||
static const DOMIfaceAndProtoJSClass WindowNamedPropertiesClass = {
|
||||
PROXY_CLASS_DEF("WindowProperties",
|
||||
DOM_INTERFACE_PROTO_SLOTS_BASE, /* extra slots */
|
||||
0),
|
||||
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS),
|
||||
eNamedPropertiesObject,
|
||||
sWindowNamedPropertiesNativePropertyHooks,
|
||||
"[object WindowProperties]",
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/DOMErrorBinding.h"
|
||||
#include "mozilla/dom/ElementBinding.h"
|
||||
#include "mozilla/dom/HTMLObjectElement.h"
|
||||
#include "mozilla/dom/HTMLObjectElementBinding.h"
|
||||
#include "mozilla/dom/HTMLSharedObjectElement.h"
|
||||
@ -912,14 +913,14 @@ ThrowConstructorWithoutNew(JSContext* cx, const char* name)
|
||||
|
||||
inline const NativePropertyHooks*
|
||||
GetNativePropertyHooks(JSContext *cx, JS::Handle<JSObject*> obj,
|
||||
DOMObjectType& type, bool& isGlobal)
|
||||
DOMObjectType& type)
|
||||
{
|
||||
const js::Class* clasp = js::GetObjectClass(obj);
|
||||
isGlobal = (clasp->flags & JSCLASS_DOM_GLOBAL) != 0;
|
||||
|
||||
const DOMJSClass* domClass = GetDOMClass(clasp);
|
||||
if (domClass) {
|
||||
type = eInstance;
|
||||
bool isGlobal = (clasp->flags & JSCLASS_DOM_GLOBAL) != 0;
|
||||
type = isGlobal ? eGlobalInstance : eInstance;
|
||||
return domClass->mNativeHooks;
|
||||
}
|
||||
|
||||
@ -941,14 +942,6 @@ GetNativePropertyHooks(JSContext *cx, JS::Handle<JSObject*> obj,
|
||||
return ifaceAndProtoJSClass->mNativeHooks;
|
||||
}
|
||||
|
||||
static bool
|
||||
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
const NativePropertyHooks* nativePropertyHooks,
|
||||
DOMObjectType type, JS::Handle<JSObject*> obj,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
bool& cacheOnHolder);
|
||||
|
||||
static bool
|
||||
XrayResolveAttribute(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
@ -1054,7 +1047,7 @@ XrayResolveMethod(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
// Try to resolve a property as an unforgeable property from the given
|
||||
// NativeProperties, if it's there. nativeProperties is allowed to be null (in
|
||||
// which case we of course won't resolve anything).
|
||||
/* static */ bool
|
||||
static bool
|
||||
XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
@ -1220,7 +1213,7 @@ DEBUG_CheckXBLCallable(JSContext *cx, JSObject *obj)
|
||||
MOZ_ASSERT(JS::IsCallable(obj));
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
DEBUG_CheckXBLLookup(JSContext *cx, JSPropertyDescriptor *desc)
|
||||
{
|
||||
if (!desc->obj)
|
||||
@ -1242,7 +1235,7 @@ DEBUG_CheckXBLLookup(JSContext *cx, JSPropertyDescriptor *desc)
|
||||
#define DEBUG_CheckXBLLookup(a, b) {}
|
||||
#endif
|
||||
|
||||
bool
|
||||
/* static */ bool
|
||||
XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
@ -1251,9 +1244,10 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
cacheOnHolder = false;
|
||||
|
||||
DOMObjectType type;
|
||||
bool isGlobal;
|
||||
const NativePropertyHooks *nativePropertyHooks =
|
||||
GetNativePropertyHooks(cx, obj, type, isGlobal);
|
||||
GetNativePropertyHooks(cx, obj, type);
|
||||
const NativePropertiesHolder& nativeProperties =
|
||||
nativePropertyHooks->mNativeProperties;
|
||||
ResolveOwnProperty resolveOwnProperty =
|
||||
nativePropertyHooks->mResolveOwnProperty;
|
||||
|
||||
@ -1263,7 +1257,7 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
}
|
||||
|
||||
// Check for unforgeable properties first.
|
||||
if (type == eInstance) {
|
||||
if (IsInstance(type)) {
|
||||
const NativePropertiesHolder& nativeProperties =
|
||||
nativePropertyHooks->mNativeProperties;
|
||||
if (!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc, cacheOnHolder,
|
||||
@ -1271,11 +1265,8 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (desc.object()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc, cacheOnHolder,
|
||||
if (!desc.object() && xpc::AccessCheck::isChrome(wrapper) &&
|
||||
!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc, cacheOnHolder,
|
||||
nativeProperties.chromeOnly)) {
|
||||
return false;
|
||||
}
|
||||
@ -1285,21 +1276,7 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
}
|
||||
}
|
||||
|
||||
if (type != eInstance || (isGlobal && GlobalPropertiesAreOwn())) {
|
||||
// For prototype objects and interface objects, just return their
|
||||
// normal set of properties. For global objects the WebIDL properties live
|
||||
// on the instance objects, so resolve those here too.
|
||||
if (!XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type,
|
||||
obj, id, desc, cacheOnHolder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (desc.object()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == eInstance) {
|
||||
if (IsInstance(type)) {
|
||||
if (resolveOwnProperty) {
|
||||
if (!resolveOwnProperty(cx, wrapper, obj, id, desc)) {
|
||||
return false;
|
||||
@ -1307,27 +1284,46 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
|
||||
if (desc.object()) {
|
||||
// None of these should be cached on the holder, since they're dynamic.
|
||||
cacheOnHolder = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're a special scope for in-content XBL, our script expects to see
|
||||
// the bound XBL methods and attributes when accessing content. However,
|
||||
// these members are implemented in content via custom-spliced prototypes,
|
||||
// and thus aren't visible through Xray wrappers unless we handle them
|
||||
// explicitly. So we check if we're running in such a scope, and if so,
|
||||
// whether the wrappee is a bound element. If it is, we do a lookup via
|
||||
// specialized XBL machinery.
|
||||
//
|
||||
// While we have to do some sketchy walking through content land, we should
|
||||
// be protected by read-only/non-configurable properties, and any functions
|
||||
// we end up with should _always_ be living in our own scope (the XBL scope).
|
||||
// Make sure to assert that.
|
||||
Element* element;
|
||||
if (xpc::ObjectScope(wrapper)->IsContentXBLScope() &&
|
||||
NS_SUCCEEDED(UNWRAP_OBJECT(Element, obj, element))) {
|
||||
if (!nsContentUtils::LookupBindingMember(cx, element, id, desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_CheckXBLLookup(cx, desc.address());
|
||||
|
||||
if (desc.object()) {
|
||||
// XBL properties shouldn't be cached on the holder, as they might be
|
||||
// shadowed by own properties returned from mResolveOwnProperty.
|
||||
desc.object().set(wrapper);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
const NativePropertyHooks* nativePropertyHooks,
|
||||
DOMObjectType type, JS::Handle<JSObject*> obj,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
bool& cacheOnHolder)
|
||||
{
|
||||
MOZ_ASSERT(type != eNamedPropertiesObject);
|
||||
|
||||
if (type == eInterface) {
|
||||
// For non-global instance Xrays there are no other properties, so return
|
||||
// here for them.
|
||||
if (type != eGlobalInstance || !GlobalPropertiesAreOwn()) {
|
||||
return true;
|
||||
}
|
||||
} else if (type == eInterface) {
|
||||
if (IdEquals(id, "prototype")) {
|
||||
return nativePropertyHooks->mPrototypeID == prototypes::id::_ID_Count ||
|
||||
ResolvePrototypeOrConstructor(cx, wrapper, obj,
|
||||
@ -1351,17 +1347,22 @@ XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
|
||||
return JS_WrapPropertyDescriptor(cx, desc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(IsInterfacePrototype(type));
|
||||
|
||||
if (type == eInterfacePrototype && IdEquals(id, "constructor")) {
|
||||
return nativePropertyHooks->mConstructorID == constructors::id::_ID_Count ||
|
||||
ResolvePrototypeOrConstructor(cx, wrapper, obj,
|
||||
nativePropertyHooks->mConstructorID,
|
||||
0, desc, cacheOnHolder);
|
||||
}
|
||||
if (IdEquals(id, "constructor")) {
|
||||
return nativePropertyHooks->mConstructorID == constructors::id::_ID_Count ||
|
||||
ResolvePrototypeOrConstructor(cx, wrapper, obj,
|
||||
nativePropertyHooks->mConstructorID,
|
||||
0, desc, cacheOnHolder);
|
||||
}
|
||||
|
||||
const NativePropertiesHolder& nativeProperties =
|
||||
nativePropertyHooks->mNativeProperties;
|
||||
// The properties for globals live on the instance, so return here as there
|
||||
// are no properties on their interface prototype object.
|
||||
if (type == eGlobalInterfacePrototype && GlobalPropertiesAreOwn()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (nativeProperties.regular &&
|
||||
!XrayResolveProperty(cx, wrapper, obj, id, desc, cacheOnHolder, type,
|
||||
@ -1380,56 +1381,6 @@ XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
bool& cacheOnHolder)
|
||||
{
|
||||
cacheOnHolder = false;
|
||||
|
||||
DOMObjectType type;
|
||||
bool isGlobal;
|
||||
const NativePropertyHooks* nativePropertyHooks =
|
||||
GetNativePropertyHooks(cx, obj, type, isGlobal);
|
||||
|
||||
if (type == eNamedPropertiesObject) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == eInstance) {
|
||||
// Global objects return their interfaces' properties from
|
||||
// XrayResolveOwnProperty, so skip those.
|
||||
if (isGlobal && GlobalPropertiesAreOwn()) {
|
||||
nativePropertyHooks = nativePropertyHooks->mProtoHooks;
|
||||
}
|
||||
|
||||
// Force the type to be eInterfacePrototype, since we need to walk the
|
||||
// prototype chain.
|
||||
type = eInterfacePrototype;
|
||||
}
|
||||
|
||||
if (type == eInterfacePrototype) {
|
||||
while (nativePropertyHooks) {
|
||||
if (!XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type,
|
||||
obj, id, desc, cacheOnHolder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (desc.object()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nativePropertyHooks = nativePropertyHooks->mProtoHooks;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type, obj,
|
||||
id, desc, cacheOnHolder);
|
||||
}
|
||||
|
||||
bool
|
||||
XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
@ -1483,19 +1434,23 @@ bool
|
||||
XrayEnumerateProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj,
|
||||
unsigned flags, JS::AutoIdVector& props,
|
||||
DOMObjectType type, bool isGlobal,
|
||||
DOMObjectType type,
|
||||
const NativeProperties* nativeProperties)
|
||||
{
|
||||
MOZ_ASSERT(type != eNamedPropertiesObject);
|
||||
|
||||
if (type == eInstance) {
|
||||
if (IsInstance(type)) {
|
||||
ENUMERATE_IF_DEFINED(unforgeableMethod);
|
||||
ENUMERATE_IF_DEFINED(unforgeableAttribute);
|
||||
if (type == eGlobalInstance && GlobalPropertiesAreOwn()) {
|
||||
ENUMERATE_IF_DEFINED(method);
|
||||
ENUMERATE_IF_DEFINED(attribute);
|
||||
}
|
||||
} else if (type == eInterface) {
|
||||
ENUMERATE_IF_DEFINED(staticMethod);
|
||||
ENUMERATE_IF_DEFINED(staticAttribute);
|
||||
} else {
|
||||
MOZ_ASSERT(type == eInterfacePrototype);
|
||||
} else if (type != eGlobalInterfacePrototype || !GlobalPropertiesAreOwn()) {
|
||||
MOZ_ASSERT(IsInterfacePrototype(type));
|
||||
ENUMERATE_IF_DEFINED(method);
|
||||
ENUMERATE_IF_DEFINED(attribute);
|
||||
}
|
||||
@ -1524,7 +1479,7 @@ XrayEnumerateProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
bool
|
||||
XrayEnumerateNativeProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
const NativePropertyHooks* nativePropertyHooks,
|
||||
DOMObjectType type, bool isGlobal,
|
||||
DOMObjectType type,
|
||||
JS::Handle<JSObject*> obj, unsigned flags,
|
||||
JS::AutoIdVector& props)
|
||||
{
|
||||
@ -1536,7 +1491,7 @@ XrayEnumerateNativeProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == eInterfacePrototype &&
|
||||
if (IsInterfacePrototype(type) &&
|
||||
nativePropertyHooks->mConstructorID != constructors::id::_ID_Count &&
|
||||
(flags & JSITER_HIDDEN) &&
|
||||
!AddStringToIDVector(cx, props, "constructor")) {
|
||||
@ -1547,14 +1502,14 @@ XrayEnumerateNativeProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
nativePropertyHooks->mNativeProperties;
|
||||
|
||||
if (nativeProperties.regular &&
|
||||
!XrayEnumerateProperties(cx, wrapper, obj, flags, props, type, isGlobal,
|
||||
!XrayEnumerateProperties(cx, wrapper, obj, flags, props, type,
|
||||
nativeProperties.regular)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nativeProperties.chromeOnly &&
|
||||
xpc::AccessCheck::isChrome(js::GetObjectCompartment(wrapper)) &&
|
||||
!XrayEnumerateProperties(cx, wrapper, obj, flags, props, type, isGlobal,
|
||||
!XrayEnumerateProperties(cx, wrapper, obj, flags, props, type,
|
||||
nativeProperties.chromeOnly)) {
|
||||
return false;
|
||||
}
|
||||
@ -1568,9 +1523,8 @@ XrayEnumerateProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
unsigned flags, JS::AutoIdVector& props)
|
||||
{
|
||||
DOMObjectType type;
|
||||
bool isGlobal;
|
||||
const NativePropertyHooks* nativePropertyHooks =
|
||||
GetNativePropertyHooks(cx, obj, type, isGlobal);
|
||||
GetNativePropertyHooks(cx, obj, type);
|
||||
EnumerateOwnProperties enumerateOwnProperties =
|
||||
nativePropertyHooks->mEnumerateOwnProperties;
|
||||
|
||||
@ -1578,46 +1532,18 @@ XrayEnumerateProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
return enumerateOwnProperties(cx, wrapper, obj, props);
|
||||
}
|
||||
|
||||
if (type == eInstance) {
|
||||
if (IsInstance(type)) {
|
||||
// FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=1071189
|
||||
// Should do something about XBL properties too.
|
||||
if (enumerateOwnProperties &&
|
||||
!enumerateOwnProperties(cx, wrapper, obj, props)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle Unforgeable properties.
|
||||
if (!XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
|
||||
isGlobal, obj, flags, props)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This will incorrectly return properties from EventTarget.prototype as own
|
||||
// property names for Window.
|
||||
if (!(isGlobal && GlobalPropertiesAreOwn()) && (flags & JSITER_OWNONLY)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Force the type to be eInterfacePrototype, since we need to walk the
|
||||
// prototype chain.
|
||||
type = eInterfacePrototype;
|
||||
}
|
||||
|
||||
if (type == eInterfacePrototype) {
|
||||
do {
|
||||
if (!XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
|
||||
isGlobal, obj, flags, props)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flags & JSITER_OWNONLY) {
|
||||
return true;
|
||||
}
|
||||
} while ((nativePropertyHooks = nativePropertyHooks->mProtoHooks));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
|
||||
isGlobal, obj, flags, props);
|
||||
return (type == eGlobalInterfacePrototype && GlobalPropertiesAreOwn()) ||
|
||||
XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
|
||||
obj, flags, props);
|
||||
}
|
||||
|
||||
NativePropertyHooks sWorkerNativePropertyHooks = {
|
||||
@ -1740,85 +1666,6 @@ DictionaryBase::AppendJSONToString(const char16_t* aJSONData,
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSString*
|
||||
ConcatJSString(JSContext* cx, const char* pre, JS::Handle<JSString*> str, const char* post)
|
||||
{
|
||||
if (!str) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::Rooted<JSString*> preString(cx, JS_NewStringCopyN(cx, pre, strlen(pre)));
|
||||
JS::Rooted<JSString*> postString(cx, JS_NewStringCopyN(cx, post, strlen(post)));
|
||||
if (!preString || !postString) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
preString = JS_ConcatStrings(cx, preString, str);
|
||||
if (!preString) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return JS_ConcatStrings(cx, preString, postString);
|
||||
}
|
||||
|
||||
bool
|
||||
NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj,
|
||||
JS::MutableHandle<JS::Value> v)
|
||||
{
|
||||
JS::Rooted<JSPropertyDescriptor> toStringDesc(cx);
|
||||
toStringDesc.object().set(nullptr);
|
||||
toStringDesc.setAttributes(0);
|
||||
toStringDesc.setGetter(nullptr);
|
||||
toStringDesc.setSetter(nullptr);
|
||||
toStringDesc.value().set(JS::UndefinedValue());
|
||||
JS::Rooted<jsid> id(cx,
|
||||
nsXPConnect::GetRuntimeInstance()->GetStringID(XPCJSRuntime::IDX_TO_STRING));
|
||||
bool unused;
|
||||
if (!XrayResolveNativeProperty(cx, wrapper, obj, id, &toStringDesc, unused)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSString*> str(cx);
|
||||
{
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
if (toStringDesc.object()) {
|
||||
JS::Rooted<JS::Value> toString(cx, toStringDesc.value());
|
||||
if (!JS_WrapValue(cx, &toString)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(JS::IsCallable(&toString.toObject()));
|
||||
JS::Rooted<JS::Value> toStringResult(cx);
|
||||
if (JS_CallFunctionValue(cx, obj, toString, JS::HandleValueArray::empty(),
|
||||
&toStringResult)) {
|
||||
str = toStringResult.toString();
|
||||
} else {
|
||||
str = nullptr;
|
||||
}
|
||||
} else {
|
||||
const js::Class* clasp = js::GetObjectClass(obj);
|
||||
if (IsDOMClass(clasp)) {
|
||||
str = JS_NewStringCopyZ(cx, clasp->name);
|
||||
str = ConcatJSString(cx, "[object ", str, "]");
|
||||
} else if (IsDOMIfaceAndProtoClass(clasp)) {
|
||||
const DOMIfaceAndProtoJSClass* ifaceAndProtoJSClass =
|
||||
DOMIfaceAndProtoJSClass::FromJSClass(clasp);
|
||||
str = JS_NewStringCopyZ(cx, ifaceAndProtoJSClass->mToString);
|
||||
} else {
|
||||
MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
|
||||
JS::Rooted<JSFunction*> fun(cx, JS_GetObjectFunction(obj));
|
||||
str = JS_DecompileFunction(cx, fun, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
|
||||
v.setString(str);
|
||||
return JS_WrapValue(cx, v);
|
||||
}
|
||||
|
||||
// Dynamically ensure that two objects don't end up with the same reserved slot.
|
||||
class MOZ_STACK_CLASS AutoCloneDOMObjectSlotGuard
|
||||
|
@ -2317,7 +2317,7 @@ AddStringToIDVector(JSContext* cx, JS::AutoIdVector& vector, const char* name)
|
||||
// Implementation of the bits that XrayWrapper needs
|
||||
|
||||
/**
|
||||
* This resolves indexed or named properties of obj.
|
||||
* This resolves operations, attributes and constants of the interfaces for obj.
|
||||
*
|
||||
* wrapper is the Xray JS object.
|
||||
* obj is the target object of the Xray, a binding's instance object or a
|
||||
@ -2330,19 +2330,6 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
bool& cacheOnHolder);
|
||||
|
||||
/**
|
||||
* This resolves operations, attributes and constants of the interfaces for obj.
|
||||
*
|
||||
* wrapper is the Xray JS object.
|
||||
* obj is the target object of the Xray, a binding's instance object or a
|
||||
* interface or interface prototype object.
|
||||
*/
|
||||
bool
|
||||
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
bool& cacheOnHolder);
|
||||
|
||||
/**
|
||||
* Define a property on obj through an Xray wrapper.
|
||||
*
|
||||
@ -2464,23 +2451,6 @@ MustInheritFromNonRefcountedDOMObject(NonRefcountedDOMObject*)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a JSString containing the value that the toString function for
|
||||
* obj should create according to the WebIDL specification, ignoring any
|
||||
* modifications by script. The value is prefixed with pre and postfixed with
|
||||
* post, unless this is called for an object that has a stringifier. It is
|
||||
* specifically for use by Xray code.
|
||||
*
|
||||
* wrapper is the Xray JS object.
|
||||
* obj is the target object of the Xray, a binding's instance object or a
|
||||
* interface or interface prototype object.
|
||||
* v contains the JSString for the value if the function returns true.
|
||||
*/
|
||||
bool
|
||||
NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Handle<JSObject*> obj,
|
||||
JS::MutableHandle<JS::Value> v);
|
||||
|
||||
HAS_MEMBER(JSBindingFinalized)
|
||||
|
||||
template<class T, bool hasCallback=HasJSBindingFinalizedMember<T>::Value>
|
||||
@ -2995,12 +2965,6 @@ GlobalPropertiesAreOwn()
|
||||
void
|
||||
AssertReturnTypeMatchesJitinfo(const JSJitInfo* aJitinfo,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
|
||||
extern void
|
||||
DEBUG_CheckXBLLookup(JSContext *cx, JSPropertyDescriptor *desc);
|
||||
#else
|
||||
#define DEBUG_CheckXBLLookup(a, b) {}
|
||||
|
||||
#endif
|
||||
|
||||
// Returns true if aObj's global has any of the permissions named in aPermissions
|
||||
|
@ -648,6 +648,7 @@ class CGPrototypeJSClass(CGThing):
|
||||
if UseHolderForUnforgeable(self.descriptor):
|
||||
slotCount += " + 1 /* slot for the JSObject holding the unforgeable properties */"
|
||||
(protoGetter, _) = InterfacePrototypeObjectProtoGetter(self.descriptor)
|
||||
type = "eGlobalInterfacePrototype" if self.descriptor.isGlobal() else "eInterfacePrototype"
|
||||
return fill(
|
||||
"""
|
||||
static const DOMIfaceAndProtoJSClass PrototypeClass = {
|
||||
@ -670,7 +671,7 @@ class CGPrototypeJSClass(CGThing):
|
||||
JS_NULL_CLASS_EXT,
|
||||
JS_NULL_OBJECT_OPS
|
||||
},
|
||||
eInterfacePrototype,
|
||||
${type},
|
||||
${hooks},
|
||||
"[object ${name}Prototype]",
|
||||
${prototypeID},
|
||||
@ -680,6 +681,7 @@ class CGPrototypeJSClass(CGThing):
|
||||
""",
|
||||
name=self.descriptor.interface.identifier.name,
|
||||
slotCount=slotCount,
|
||||
type=type,
|
||||
hooks=NativePropertyHooks(self.descriptor),
|
||||
prototypeID=prototypeID,
|
||||
depth=depth,
|
||||
|
@ -156,17 +156,34 @@ struct NativePropertyHooks
|
||||
// constructors::id::_ID_Count.
|
||||
constructors::ID mConstructorID;
|
||||
|
||||
// The NativePropertyHooks instance for the parent interface.
|
||||
// The NativePropertyHooks instance for the parent interface (for
|
||||
// ShimInterfaceInfo).
|
||||
const NativePropertyHooks* mProtoHooks;
|
||||
};
|
||||
|
||||
enum DOMObjectType {
|
||||
eInstance,
|
||||
eGlobalInstance,
|
||||
eInterface,
|
||||
eInterfacePrototype,
|
||||
eGlobalInterfacePrototype,
|
||||
eNamedPropertiesObject
|
||||
};
|
||||
|
||||
inline
|
||||
bool
|
||||
IsInstance(DOMObjectType type)
|
||||
{
|
||||
return type == eInstance || type == eGlobalInstance;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
IsInterfacePrototype(DOMObjectType type)
|
||||
{
|
||||
return type == eInterfacePrototype || type == eGlobalInterfacePrototype;
|
||||
}
|
||||
|
||||
typedef JSObject* (*ParentGetter)(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
||||
|
||||
typedef JSObject* (*ProtoGetter)(JSContext* aCx,
|
||||
@ -229,7 +246,8 @@ struct DOMIfaceAndProtoJSClass
|
||||
// initialization for aggregate/POD types.
|
||||
const js::Class mBase;
|
||||
|
||||
// Either eInterface, eInterfacePrototype or eNamedPropertiesObject
|
||||
// Either eInterface, eInterfacePrototype, eGlobalInterfacePrototype or
|
||||
// eNamedPropertiesObject.
|
||||
DOMObjectType mType;
|
||||
|
||||
const NativePropertyHooks* mNativeHooks;
|
||||
|
@ -74,12 +74,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
|
||||
} finally {
|
||||
isnot(xhr.prototype, "notok", "'XMLHttpRequest.prototype' should be readonly");
|
||||
}
|
||||
try {
|
||||
var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
|
||||
delete xhr.prototype;
|
||||
} catch (e) {
|
||||
ok(true, "'XMLHttpRequest.prototype' should be permanent");
|
||||
}
|
||||
var constructorWritable = false;
|
||||
try {
|
||||
var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox);
|
||||
xhr.constructor = "ok";
|
||||
@ -87,12 +82,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
|
||||
} catch (e) {
|
||||
ok(false, "'XMLHttpRequest.prototype.constructor' should be writeable");
|
||||
}
|
||||
try {
|
||||
var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox);
|
||||
delete xhr.constructor;
|
||||
} catch (e) {
|
||||
is(xhr.constructor, undefined, "'XMLHttpRequest.prototype.constructor' should be permanent");
|
||||
}
|
||||
try {
|
||||
var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
|
||||
is(xhr, XMLHttpRequest + "", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
|
||||
@ -114,6 +103,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
|
||||
} catch (e) {
|
||||
ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (1)");
|
||||
}
|
||||
try {
|
||||
var xhr = Components.utils.evalInSandbox("XMLHttpRequest.toString = function () { return 'Failed'; }; XMLHttpRequest;", sandbox);
|
||||
is(xhr.toString(), XMLHttpRequest + "", "XMLHttpRequest.toString in the sandbox should not override the native toString behaviour");
|
||||
} catch (e) {
|
||||
ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox");
|
||||
}
|
||||
try {
|
||||
var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype.toString = function () { return 'Failed'; }; new XMLHttpRequest();", sandbox);
|
||||
is(xhr.toString(), new XMLHttpRequest() + "", "XMLHttpRequest.prototype.toString in the sandbox should not override the native toString behaviour");
|
||||
@ -137,6 +132,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
|
||||
} catch (e) {
|
||||
ok(false, "XMLHttpRequest.prototype manipulation via an Xray shouldn't throw" + e);
|
||||
}
|
||||
try {
|
||||
Components.utils.evalInSandbox("XMLHttpRequest.prototype.a = 'expando a'", sandbox);
|
||||
Components.utils.evalInSandbox("XMLHttpRequest.prototype.b = 'expando b'", sandbox);
|
||||
Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox).b = 'xrayexpando';
|
||||
var xhr = Components.utils.evalInSandbox("new XMLHttpRequest()", sandbox);
|
||||
is(xhr.a, undefined, "'XMLHttpRequest()' in a sandbox should not have expandos from inside the sandbox");
|
||||
is(xhr.b, "xrayexpando", "'new XMLHttpRequest()' in a sandbox should have Xray expandos");
|
||||
} catch (e) {
|
||||
ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox");
|
||||
}
|
||||
try {
|
||||
Components.utils.evalInSandbox("document.defaultView.XMLHttpRequest = function() {};", sandbox);
|
||||
var win = Components.utils.evalInSandbox("document.defaultView", sandbox);
|
||||
|
@ -8,11 +8,10 @@
|
||||
#include "AccessCheck.h"
|
||||
#include "WrapperFactory.h"
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "nsIControllers.h"
|
||||
#include "nsDependentString.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "XPCWrapper.h"
|
||||
#include "xpcprivate.h"
|
||||
@ -1053,9 +1052,6 @@ IsWindow(JSContext *cx, JSObject *wrapper)
|
||||
return !!AsWindow(cx, wrapper);
|
||||
}
|
||||
|
||||
static nsQueryInterface
|
||||
do_QueryInterfaceNative(JSContext* cx, HandleObject wrapper);
|
||||
|
||||
void
|
||||
XPCWrappedNativeXrayTraits::preserveWrapper(JSObject *target)
|
||||
{
|
||||
@ -1509,33 +1505,6 @@ DOMXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsWrapper, Handl
|
||||
JS_GetPropertyDescriptorById(cx, holder, id, desc);
|
||||
}
|
||||
|
||||
bool
|
||||
DOMXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wrapper,
|
||||
HandleObject holder, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
bool unused;
|
||||
RootedObject obj(cx, getTargetObject(wrapper));
|
||||
if (!XrayResolveNativeProperty(cx, wrapper, obj, id, desc, unused))
|
||||
return false;
|
||||
|
||||
if (!desc.object() &&
|
||||
id == nsXPConnect::GetRuntimeInstance()->GetStringID(XPCJSRuntime::IDX_TO_STRING))
|
||||
{
|
||||
|
||||
JSFunction *toString = JS_NewFunction(cx, XrayToString, 0, 0, wrapper, "toString");
|
||||
if (!toString)
|
||||
return false;
|
||||
|
||||
FillPropertyDescriptor(desc, wrapper, 0,
|
||||
ObjectValue(*JS_GetFunctionObject(toString)));
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!desc.object() || desc.object() == wrapper, "What did we resolve this on?");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc,
|
||||
@ -1636,6 +1605,14 @@ DOMXrayTraits::construct(JSContext *cx, HandleObject wrapper,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DOMXrayTraits::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
|
||||
JS::HandleObject target,
|
||||
JS::MutableHandleObject protop)
|
||||
{
|
||||
return mozilla::dom::XrayGetNativeProto(cx, target, protop);
|
||||
}
|
||||
|
||||
void
|
||||
DOMXrayTraits::preserveWrapper(JSObject *target)
|
||||
{
|
||||
@ -1729,19 +1706,7 @@ XrayToString(JSContext *cx, unsigned argc, Value *vp)
|
||||
}
|
||||
|
||||
RootedObject obj(cx, XrayTraits::getTargetObject(wrapper));
|
||||
XrayType type = GetXrayType(obj);
|
||||
if (type == XrayForDOMObject) {
|
||||
{
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
JSString *str = JS_BasicObjectToString(cx, obj);
|
||||
if (!str)
|
||||
return false;
|
||||
args.rval().setString(str);
|
||||
}
|
||||
return JS_WrapValue(cx, args.rval());
|
||||
}
|
||||
|
||||
if (type != XrayForWrappedNative) {
|
||||
if (GetXrayType(obj) != XrayForWrappedNative) {
|
||||
JS_ReportError(cx, "XrayToString called on an incompatible object");
|
||||
return false;
|
||||
}
|
||||
@ -1868,29 +1833,6 @@ XrayWrapper<Base, Traits>::getPropertyDescriptor(JSContext *cx, HandleObject wra
|
||||
}
|
||||
}
|
||||
|
||||
// If we're a special scope for in-content XBL, our script expects to see
|
||||
// the bound XBL methods and attributes when accessing content. However,
|
||||
// these members are implemented in content via custom-spliced prototypes,
|
||||
// and thus aren't visible through Xray wrappers unless we handle them
|
||||
// explicitly. So we check if we're running in such a scope, and if so,
|
||||
// whether the wrappee is a bound element. If it is, we do a lookup via
|
||||
// specialized XBL machinery.
|
||||
//
|
||||
// While we have to do some sketchy walking through content land, we should
|
||||
// be protected by read-only/non-configurable properties, and any functions
|
||||
// we end up with should _always_ be living in an XBL scope (usually ours,
|
||||
// but could be another if the node has been adopted).
|
||||
//
|
||||
// Make sure to assert this.
|
||||
nsCOMPtr<nsIContent> content;
|
||||
if (!desc.object() && ObjectScope(wrapper)->IsContentXBLScope() &&
|
||||
(content = do_QueryInterfaceNative(cx, wrapper)))
|
||||
{
|
||||
if (!nsContentUtils::LookupBindingMember(cx, content, id, desc))
|
||||
return false;
|
||||
DEBUG_CheckXBLLookup(cx, desc.address());
|
||||
}
|
||||
|
||||
// If we still have nothing, we're done.
|
||||
if (!desc.object())
|
||||
return true;
|
||||
@ -2119,6 +2061,7 @@ XrayWrapper<Base, Traits>::set(JSContext *cx, HandleObject wrapper,
|
||||
HandleObject receiver, HandleId id,
|
||||
bool strict, MutableHandleValue vp) const
|
||||
{
|
||||
MOZ_ASSERT(!Traits::HasPrototype);
|
||||
// Delegate to Traits.
|
||||
// NB: None of the functions we call are prepared for the receiver not
|
||||
// being the wrapper, so ignore the receiver here.
|
||||
@ -2290,25 +2233,4 @@ template<>
|
||||
const SCSecurityXrayXPCWN SCSecurityXrayXPCWN::singleton(0);
|
||||
template class SCSecurityXrayXPCWN;
|
||||
|
||||
static nsQueryInterface
|
||||
do_QueryInterfaceNative(JSContext* cx, HandleObject wrapper)
|
||||
{
|
||||
nsISupports* nativeSupports = nullptr;
|
||||
if (IsWrapper(wrapper) && WrapperFactory::IsXrayWrapper(wrapper)) {
|
||||
RootedObject target(cx, XrayTraits::getTargetObject(wrapper));
|
||||
XrayType type = GetXrayType(target);
|
||||
if (type == XrayForDOMObject) {
|
||||
nativeSupports = UnwrapDOMObjectToISupports(target);
|
||||
} else if (type == XrayForWrappedNative) {
|
||||
XPCWrappedNative *wn = XPCWrappedNative::Get(target);
|
||||
nativeSupports = wn->Native();
|
||||
}
|
||||
} else {
|
||||
nsIXPConnect *xpc = nsXPConnect::XPConnect();
|
||||
nativeSupports = xpc->GetNativeOfWrapper(cx, wrapper);
|
||||
}
|
||||
|
||||
return nsQueryInterface(nativeSupports);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -154,14 +154,26 @@ class DOMXrayTraits : public XrayTraits
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
HasPrototype = 0
|
||||
HasPrototype = 1
|
||||
};
|
||||
|
||||
static const XrayType Type = XrayForDOMObject;
|
||||
|
||||
virtual bool resolveNativeProperty(JSContext *cx, JS::HandleObject wrapper,
|
||||
JS::HandleObject holder, JS::HandleId id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE
|
||||
{
|
||||
// Xrays for DOM binding objects have a prototype chain that consists of
|
||||
// Xrays for the prototypes of the DOM binding object (ignoring changes
|
||||
// in the prototype chain made by script, plugins or XBL). All properties for
|
||||
// these Xrays are really own properties, either of the instance object or
|
||||
// of the prototypes.
|
||||
// FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=1072482
|
||||
// This should really be:
|
||||
// MOZ_CRASH("resolveNativeProperty hook should never be called with HasPrototype = 1");
|
||||
// but we can't do that yet because XrayUtils::HasNativeProperty calls this.
|
||||
return true;
|
||||
}
|
||||
virtual bool resolveOwnProperty(JSContext *cx, const js::Wrapper &jsWrapper, JS::HandleObject wrapper,
|
||||
JS::HandleObject holder, JS::HandleId id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
|
||||
@ -177,6 +189,10 @@ public:
|
||||
static bool construct(JSContext *cx, JS::HandleObject wrapper,
|
||||
const JS::CallArgs &args, const js::Wrapper& baseInstance);
|
||||
|
||||
static bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
|
||||
JS::HandleObject target,
|
||||
JS::MutableHandleObject protop);
|
||||
|
||||
virtual void preserveWrapper(JSObject *target) MOZ_OVERRIDE;
|
||||
|
||||
virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
|
Loading…
Reference in New Issue
Block a user