mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 945416 part 3. Make GlobalResolve fill in a JSPropertyDescriptor that nsWindowSH::NewResolve then uses to actually define the property. r=bholley,peterv
This commit is contained in:
parent
2cc31b028d
commit
3ecc0d422f
@ -1630,8 +1630,8 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
||||
const nsDOMClassInfoData *ci_data,
|
||||
const nsGlobalNameStruct *name_struct,
|
||||
nsScriptNameSpaceManager *nameSpaceManager,
|
||||
JSObject *dot_prototype, bool install, bool *did_resolve);
|
||||
|
||||
JSObject *dot_prototype,
|
||||
JS::MutableHandle<JSPropertyDescriptor> ctorDesc);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
|
||||
@ -1727,19 +1727,30 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
|
||||
}
|
||||
|
||||
// Don't overwrite a property set by content.
|
||||
bool found;
|
||||
bool contentDefinedProperty;
|
||||
if (!::JS_AlreadyHasOwnUCProperty(cx, global, reinterpret_cast<const jschar*>(mData->mNameUTF16),
|
||||
NS_strlen(mData->mNameUTF16), &found)) {
|
||||
NS_strlen(mData->mNameUTF16),
|
||||
&contentDefinedProperty)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_OK);
|
||||
|
||||
bool unused;
|
||||
return ResolvePrototype(sXPConnect, win, cx, global, mData->mNameUTF16,
|
||||
mData, nullptr, nameSpaceManager, proto, !found,
|
||||
&unused);
|
||||
JS::Rooted<JSPropertyDescriptor> desc(cx);
|
||||
nsresult rv = ResolvePrototype(sXPConnect, win, cx, global, mData->mNameUTF16,
|
||||
mData, nullptr, nameSpaceManager, proto,
|
||||
&desc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined() &&
|
||||
!JS_DefineUCProperty(cx, global, mData->mNameUTF16,
|
||||
NS_strlen(mData->mNameUTF16),
|
||||
desc.value(), desc.getter(), desc.setter(),
|
||||
desc.attributes())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
@ -2181,20 +2192,6 @@ public:
|
||||
JS::Handle<JSObject*> obj, const jsval &val, bool *bp,
|
||||
bool *_retval);
|
||||
|
||||
nsresult Install(JSContext *cx, JS::Handle<JSObject*> target,
|
||||
JS::Handle<JS::Value> aThisAsVal)
|
||||
{
|
||||
JS::Rooted<JS::Value> thisAsVal(cx, aThisAsVal);
|
||||
// The 'attrs' argument used to be JSPROP_PERMANENT. See bug 628612.
|
||||
bool ok = JS_WrapValue(cx, &thisAsVal) &&
|
||||
::JS_DefineUCProperty(cx, target,
|
||||
reinterpret_cast<const jschar *>(mClassName),
|
||||
NS_strlen(mClassName), thisAsVal, JS_PropertyStub,
|
||||
JS_StrictPropertyStub, 0);
|
||||
|
||||
return ok ? NS_OK : NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsresult ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj);
|
||||
|
||||
private:
|
||||
@ -2616,7 +2613,8 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
||||
const nsDOMClassInfoData *ci_data,
|
||||
const nsGlobalNameStruct *name_struct,
|
||||
nsScriptNameSpaceManager *nameSpaceManager,
|
||||
JSObject* aDot_prototype, bool install, bool *did_resolve)
|
||||
JSObject* aDot_prototype,
|
||||
JS::MutableHandle<JSPropertyDescriptor> ctorDesc)
|
||||
{
|
||||
JS::Rooted<JSObject*> dot_prototype(cx, aDot_prototype);
|
||||
NS_ASSERTION(ci_data ||
|
||||
@ -2635,9 +2633,12 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
||||
false, &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (install) {
|
||||
rv = constructor->Install(cx, obj, v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
FillPropertyDescriptor(ctorDesc, obj, 0, v);
|
||||
// And make sure we wrap the value into the right compartment. Note that we
|
||||
// do this with ctorDesc.value(), not with v, because we need v to be in the
|
||||
// right compartment (that of the reflector of |constructor|) below.
|
||||
if (!JS_WrapValue(cx, ctorDesc.value())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> class_obj(cx, &v.toObject());
|
||||
@ -2766,8 +2767,6 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
*did_resolve = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2801,21 +2800,20 @@ OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct,
|
||||
}
|
||||
|
||||
static nsresult
|
||||
DefineComponentsShim(JSContext *cx, JS::Handle<JSObject*> global, nsPIDOMWindow *win);
|
||||
LookupComponentsShim(JSContext *cx, JS::Handle<JSObject*> global,
|
||||
nsPIDOMWindow *win,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
bool *did_resolve)
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) {
|
||||
*did_resolve = true;
|
||||
return DefineComponentsShim(cx, obj, aWin);
|
||||
return LookupComponentsShim(cx, obj, aWin, desc);
|
||||
}
|
||||
|
||||
*did_resolve = false;
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
@ -2829,6 +2827,9 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The class_name had better match our name
|
||||
MOZ_ASSERT(name.Equals(class_name));
|
||||
|
||||
NS_ENSURE_TRUE(class_name, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
@ -2859,39 +2860,73 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
JS::Rooted<JSObject*> global(cx);
|
||||
bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj);
|
||||
if (isXray) {
|
||||
global = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
|
||||
// The DOM constructor resolve machinery interacts with Xrays in tricky
|
||||
// ways, and there are some asymmetries that are important to understand.
|
||||
//
|
||||
// In the regular (non-Xray) case, we only want to resolve constructors
|
||||
// once (so that if they're deleted, they don't reappear). We do this by
|
||||
// stashing the constructor in a slot on the global, such that we can see
|
||||
// during resolve whether we've created it already. This is rather
|
||||
// memory-intensive, so we don't try to maintain these semantics when
|
||||
// manipulating a global over Xray (so the properties just re-resolve if
|
||||
// they've been deleted).
|
||||
//
|
||||
// Unfortunately, there's a bit of an impedance-mismatch between the Xray
|
||||
// and non-Xray machinery. The Xray machinery wants an API that returns a
|
||||
// JSPropertyDescriptor, so that the resolve hook doesn't have to get
|
||||
// snared up with trying to define a property on the Xray holder. At the
|
||||
// same time, the DefineInterface callbacks are set up to define things
|
||||
// directly on the global. And re-jiggering them to return property
|
||||
// descriptors is tricky, because some DefineInterface callbacks define
|
||||
// multiple things (like the Image() alias for HTMLImageElement).
|
||||
//
|
||||
// So the setup is as-follows:
|
||||
//
|
||||
// * The resolve function takes a JSPropertyDescriptor, but in the
|
||||
// non-Xray case, callees may define things directly on the global, and
|
||||
// set the value on the property descriptor to |undefined| to indicate
|
||||
// that there's nothing more for the caller to do. We assert against
|
||||
// this behavior in the Xray case.
|
||||
//
|
||||
// * We make sure that we do a non-Xray resolve first, so that all the
|
||||
// slots are set up. In the Xray case, this means unwrapping and doing
|
||||
// a non-Xray resolve before doing the Xray resolve.
|
||||
//
|
||||
// This all could use some grand refactoring, but for now we just limp
|
||||
// along.
|
||||
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
|
||||
JS::Rooted<JSObject*> global(cx,
|
||||
js::CheckedUnwrap(obj, /* stopAtOuter = */ false));
|
||||
if (!global) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
ac.construct(cx, global);
|
||||
} else {
|
||||
global = obj;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> interfaceObject(cx,
|
||||
getOrCreateInterfaceObject(cx, global, id, !isXray));
|
||||
if (!interfaceObject) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (isXray) {
|
||||
// This really should be handled by the Xray for the window.
|
||||
ac.destroy();
|
||||
if (!JS_WrapObject(cx, &interfaceObject) ||
|
||||
!JS_DefinePropertyById(cx, obj, id,
|
||||
JS::ObjectValue(*interfaceObject), JS_PropertyStub,
|
||||
JS_StrictPropertyStub, 0)) {
|
||||
JS::Rooted<JSObject*> interfaceObject(cx);
|
||||
{
|
||||
JSAutoCompartment ac(cx, global);
|
||||
interfaceObject = getOrCreateInterfaceObject(cx, global, id, false);
|
||||
}
|
||||
if (NS_WARN_IF(!interfaceObject)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!JS_WrapObject(cx, &interfaceObject)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
FillPropertyDescriptor(desc, obj, 0, JS::ObjectValue(*interfaceObject));
|
||||
} else {
|
||||
JS::Rooted<JSObject*> interfaceObject(cx,
|
||||
getOrCreateInterfaceObject(cx, obj, id, true));
|
||||
if (NS_WARN_IF(!interfaceObject)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// We've already defined the property. We indicate this to the caller
|
||||
// by filling a property descriptor with JS::UndefinedValue() as the
|
||||
// value. We still have to fill in a property descriptor, though, so
|
||||
// that the caller knows the property is in fact on this object. It
|
||||
// doesn't matter what we pass for the "readonly" argument here.
|
||||
FillPropertyDescriptor(desc, obj, JS::UndefinedValue(), false);
|
||||
}
|
||||
|
||||
*did_resolve = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
@ -2912,20 +2947,22 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
false, &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = constructor->Install(cx, obj, v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JSObject*> class_obj(cx, &v.toObject());
|
||||
|
||||
// ... and define the constants from the DOM interface on that
|
||||
// constructor object.
|
||||
|
||||
JSAutoCompartment ac(cx, class_obj);
|
||||
rv = DefineInterfaceConstants(cx, class_obj, &name_struct->mIID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
{
|
||||
JSAutoCompartment ac(cx, class_obj);
|
||||
rv = DefineInterfaceConstants(cx, class_obj, &name_struct->mIID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
*did_resolve = true;
|
||||
if (!JS_WrapValue(cx, &v)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
FillPropertyDescriptor(desc, obj, 0, v);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2936,38 +2973,42 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
}
|
||||
|
||||
// Create the XPConnect prototype for our classinfo, PostCreateProto will
|
||||
// set up the prototype chain.
|
||||
// set up the prototype chain. This will go ahead and define things on the
|
||||
// actual window's global.
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
|
||||
rv = GetXPCProto(sXPConnect, cx, aWin, name_struct,
|
||||
getter_AddRefs(proto_holder));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && obj != aWin->GetGlobalJSObject()) {
|
||||
JS::Rooted<JSObject*> dot_prototype(cx, proto_holder->GetJSObject());
|
||||
NS_ENSURE_STATE(dot_prototype);
|
||||
|
||||
const nsDOMClassInfoData *ci_data;
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
ci_data = &sClassInfoData[name_struct->mDOMClassInfoID];
|
||||
} else {
|
||||
ci_data = name_struct->mData;
|
||||
}
|
||||
|
||||
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data,
|
||||
name_struct, nameSpaceManager, dot_prototype,
|
||||
true, did_resolve);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj);
|
||||
MOZ_ASSERT_IF(obj != aWin->GetGlobalJSObject(), isXray);
|
||||
if (!isXray) {
|
||||
// GetXPCProto already defined the property for us
|
||||
FillPropertyDescriptor(desc, obj, JS::UndefinedValue(), false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*did_resolve = NS_SUCCEEDED(rv);
|
||||
// This is the Xray case. Look up the constructor object for this
|
||||
// prototype.
|
||||
JS::Rooted<JSObject*> dot_prototype(cx, proto_holder->GetJSObject());
|
||||
NS_ENSURE_STATE(dot_prototype);
|
||||
|
||||
return rv;
|
||||
const nsDOMClassInfoData *ci_data;
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
ci_data = &sClassInfoData[name_struct->mDOMClassInfoID];
|
||||
} else {
|
||||
ci_data = name_struct->mData;
|
||||
}
|
||||
|
||||
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data,
|
||||
name_struct, nameSpaceManager, dot_prototype,
|
||||
desc);
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
|
||||
// We don't have a XPConnect prototype object, let ResolvePrototype create
|
||||
// one.
|
||||
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, nullptr,
|
||||
name_struct, nameSpaceManager, nullptr, true,
|
||||
did_resolve);
|
||||
name_struct, nameSpaceManager, nullptr, desc);
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
|
||||
@ -2996,8 +3037,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
}
|
||||
|
||||
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data,
|
||||
name_struct, nameSpaceManager, nullptr, true,
|
||||
did_resolve);
|
||||
name_struct, nameSpaceManager, nullptr, desc);
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
|
||||
@ -3009,15 +3049,12 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
|
||||
false, &val);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = constructor->Install(cx, obj, val);
|
||||
true, &val);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(val.isObject(), "Why didn't we get a JSObject?");
|
||||
|
||||
*did_resolve = true;
|
||||
FillPropertyDescriptor(desc, obj, 0, val);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3066,13 +3103,9 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
bool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE);
|
||||
FillPropertyDescriptor(desc, obj, prop_val, false);
|
||||
|
||||
*did_resolve = true;
|
||||
|
||||
return ok ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -3184,7 +3217,9 @@ const InterfaceShimEntry kInterfaceShimMap[] =
|
||||
{ "nsIDOMXPathResult", "XPathResult" } };
|
||||
|
||||
static nsresult
|
||||
DefineComponentsShim(JSContext *cx, JS::Handle<JSObject*> global, nsPIDOMWindow *win)
|
||||
LookupComponentsShim(JSContext *cx, JS::Handle<JSObject*> global,
|
||||
nsPIDOMWindow *win,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
// Keep track of how often this happens.
|
||||
Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true);
|
||||
@ -3198,16 +3233,14 @@ DefineComponentsShim(JSContext *cx, JS::Handle<JSObject*> global, nsPIDOMWindow
|
||||
// Create a fake Components object.
|
||||
JS::Rooted<JSObject*> components(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), global));
|
||||
NS_ENSURE_TRUE(components, NS_ERROR_OUT_OF_MEMORY);
|
||||
bool ok = JS_DefineProperty(cx, global, "Components", JS::ObjectValue(*components),
|
||||
JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Create a fake interfaces object.
|
||||
JS::Rooted<JSObject*> interfaces(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), global));
|
||||
NS_ENSURE_TRUE(interfaces, NS_ERROR_OUT_OF_MEMORY);
|
||||
ok = JS_DefineProperty(cx, components, "interfaces", JS::ObjectValue(*interfaces),
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
bool ok =
|
||||
JS_DefineProperty(cx, components, "interfaces", JS::ObjectValue(*interfaces),
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM
|
||||
@ -3234,6 +3267,8 @@ DefineComponentsShim(JSContext *cx, JS::Handle<JSObject*> global, nsPIDOMWindow
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
FillPropertyDescriptor(desc, global, JS::ObjectValue(*components), false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3339,18 +3374,39 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
// (and any relevant named constructor names) has been resolved before;
|
||||
// this allows us to avoid re-resolving in the Xray case if the property is
|
||||
// deleted by page script.
|
||||
bool ignored;
|
||||
JS::Rooted<JSObject*> global(cx,
|
||||
js::UncheckedUnwrap(obj, /* stopAtOuter = */ false));
|
||||
JSAutoCompartment ac(cx, global);
|
||||
nsresult rv = GlobalResolve(win, cx, global, id, &ignored);
|
||||
JS::Rooted<JSPropertyDescriptor> desc(cx);
|
||||
nsresult rv = GlobalResolve(win, cx, global, id, &desc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// If we have an object here, that means we resolved the property.
|
||||
// But if the value is undefined, that means that GlobalResolve
|
||||
// also already defined it, so we don't have to.
|
||||
if (desc.object() && !desc.value().isUndefined() &&
|
||||
!JS_DefinePropertyById(cx, global, id, desc.value(),
|
||||
desc.getter(), desc.setter(),
|
||||
desc.attributes())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
bool did_resolve = false;
|
||||
nsresult rv = GlobalResolve(win, cx, obj, id, &did_resolve);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (did_resolve) {
|
||||
JS::Rooted<JSPropertyDescriptor> desc(cx);
|
||||
nsresult rv = GlobalResolve(win, cx, obj, id, &desc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (desc.object()) {
|
||||
// If we have an object here, that means we resolved the property.
|
||||
// But if the value is undefined, that means that GlobalResolve
|
||||
// also already defined it, so we don't have to. Note that in the
|
||||
// Xray case we should never see undefined.
|
||||
MOZ_ASSERT_IF(isXray, !desc.value().isUndefined());
|
||||
if (!desc.value().isUndefined() &&
|
||||
!JS_DefinePropertyById(cx, obj, id, desc.value(),
|
||||
desc.getter(), desc.setter(),
|
||||
desc.attributes())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*objp = obj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -256,7 +256,7 @@ protected:
|
||||
|
||||
static nsresult GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
bool *did_resolve);
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
|
||||
public:
|
||||
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
|
@ -165,6 +165,18 @@ FillPropertyDescriptor(JS::MutableHandle<JSPropertyDescriptor> desc, JSObject* o
|
||||
FillPropertyDescriptor(desc, obj, readonly);
|
||||
}
|
||||
|
||||
inline void
|
||||
FillPropertyDescriptor(JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
JSObject* obj, unsigned attributes, JS::Value v)
|
||||
{
|
||||
desc.object().set(obj);
|
||||
desc.value().set(v);
|
||||
desc.setAttributes(attributes);
|
||||
desc.setGetter(nullptr);
|
||||
desc.setSetter(nullptr);
|
||||
desc.setShortId(0);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user