Fix for bug 484764 (Set up DOM prototype chains from PostCreateProto instead of PostCreate). r/sr=jst.

--HG--
extra : rebase_source : 8e24cbcede7e48e42c4c06a55d3bc7dd91603020
This commit is contained in:
Peter Van der Beken 2009-06-03 17:30:18 +02:00
parent 75552f6810
commit 517988bd1b
7 changed files with 250 additions and 212 deletions

View File

@ -187,7 +187,6 @@
#include "nsIDOMViewCSS.h"
#include "nsIDOMElement.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIScriptGlobalObject.h"
#include "nsStyleSet.h"
#include "nsStyleContext.h"
#include "nsAutoPtr.h"
@ -497,17 +496,20 @@ static const char kDOMStringBundleURL[] =
#define ELEMENT_SCRIPTABLE_FLAGS \
((NODE_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) | \
nsIXPCScriptable::WANT_POSTCREATE | \
nsIXPCScriptable::WANT_ENUMERATE)
#define EXTERNAL_OBJ_SCRIPTABLE_FLAGS \
((ELEMENT_SCRIPTABLE_FLAGS & \
~nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY) | \
nsIXPCScriptable::WANT_POSTCREATE | \
nsIXPCScriptable::WANT_GETPROPERTY | \
nsIXPCScriptable::WANT_SETPROPERTY | \
nsIXPCScriptable::WANT_CALL)
#define DOCUMENT_SCRIPTABLE_FLAGS \
(NODE_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_POSTCREATE | \
nsIXPCScriptable::WANT_ADDPROPERTY | \
nsIXPCScriptable::WANT_DELPROPERTY | \
nsIXPCScriptable::WANT_GETPROPERTY | \
@ -538,6 +540,7 @@ static const char kDOMStringBundleURL[] =
#define NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _name, _helper, \
_flags) \
{ #_name, \
nsnull, \
{ _helper::doCreate }, \
nsnull, \
nsnull, \
@ -1757,7 +1760,8 @@ nsDOMClassInfo::RegisterClassName(PRInt32 aClassInfoID)
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
nameSpaceManager->RegisterClassName(sClassInfoData[aClassInfoID].mName,
aClassInfoID);
aClassInfoID,
&sClassInfoData[aClassInfoID].mNameUTF16);
return NS_OK;
}
@ -3843,66 +3847,9 @@ NS_IMETHODIMP
nsDOMClassInfo::PostCreate(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj)
{
static const nsIID *sSupportsIID = &NS_GET_IID(nsISupports);
NS_WARNING("nsDOMClassInfo::PostCreate Don't call me!");
// This is safe because...
if (mData->mProtoChainInterface == sSupportsIID ||
!mData->mProtoChainInterface) {
return NS_OK;
}
#ifdef DEBUG
{
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
NS_ASSERTION(!sgo || sgo->GetGlobalJSObject() == nsnull,
"Multiple wrappers created for global object!");
}
#endif
JSObject *proto = nsnull;
wrapper->GetJSObjectPrototype(&proto);
JSAutoRequest ar(cx);
JSObject *proto_proto = ::JS_GetPrototype(cx, proto);
if (!proto_proto) {
// If our prototype doesn't have a proto, then we've probably already
// wrapped this object and someone's done something evil, like set
// our prototype's proto to null, so bail.
return NS_OK;
}
JSClass *proto_proto_class = JS_GET_CLASS(cx, proto_proto);
if (proto_proto_class != sObjectClass) {
// We've just wrapped an object of a type that has been wrapped on
// this scope already so the prototype of the xpcwrapped native's
// prototype is already set up.
return NS_OK;
}
// Look up the name of our constructor in the current global scope. We do
// this because triggering this lookup can cause us to call
// nsWindowSH::NewResolve, which will end up in nsWindowSH::GlobalResolve.
// GlobalResolve does some prototype magic (which satisfies the if condition
// above) in order to make sure that prototype delegation works correctly.
// Consider if a site sets HTMLElement.prototype.foopy = function () { ... }
// Now, calling document.body.foopy() needs to ensure that looking up foopy
// on document.body's prototype will find the right function. Thisb
// LookupProperty accomplishes that.
// XXX This shouldn't need to go through the JS engine. Instead, we should
// be calling nsWindowSH::GlobalResolve directly.
JSObject *global = ::JS_GetGlobalForObject(cx, obj);
jsval val;
if (!::JS_LookupPropertyWithFlags(cx, global, mData->mName,
JSRESOLVE_CLASSNAME, &val)) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
@ -4172,10 +4119,11 @@ GetExternalClassInfo(nsScriptNameSpaceManager *aNameSpaceManager,
static nsresult
ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
JSObject *obj, JSString *str,
JSObject *obj, const PRUnichar *name,
const nsDOMClassInfoData *ci_data,
const nsGlobalNameStruct *name_struct,
nsScriptNameSpaceManager *nameSpaceManager,
PRBool *did_resolve);
JSObject *dot_prototype, PRBool *did_resolve);
NS_IMETHODIMP
@ -4195,6 +4143,18 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
JS_ClearPendingException(cx);
}
static const nsIID *sSupportsIID = &NS_GET_IID(nsISupports);
// This is safe because...
if (mData->mProtoChainInterface == sSupportsIID ||
!mData->mProtoChainInterface) {
return NS_OK;
}
NS_ASSERTION(::JS_GetPrototype(cx, proto) &&
JS_GET_CLASS(cx, ::JS_GetPrototype(cx, proto)) == sObjectClass,
"Hmm, somebody did something evil?");
#ifdef DEBUG
if (mData->mHasClassInterface) {
nsCOMPtr<nsIInterfaceInfoManager>
@ -4215,7 +4175,43 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
}
#endif
return NS_OK;
// Make prototype delegation work correctly. Consider if a site sets
// HTMLElement.prototype.foopy = function () { ... } Now, calling
// document.body.foopy() needs to ensure that looking up foopy on
// document.body's prototype will find the right function.
JSObject *global = ::JS_GetGlobalForObject(cx, proto);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
sXPConnect->GetWrappedNativeOfJSObject(cx, global, getter_AddRefs(wrapper));
if (!wrapper) {
return NS_OK;
}
// Only do this if the global object is a window.
// XXX Is there a better way to check this?
nsCOMPtr<nsPIDOMWindow> piwin = do_QueryWrappedNative(wrapper);
if(!piwin) {
return NS_OK;
}
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
if (win->IsOuterWindow()) {
// XXXjst: Do security checks here when we remove the security
// checks on the inner window.
win = win->GetCurrentInnerWindowInternal();
if (!win || !(global = win->GetGlobalJSObject())) {
return NS_OK;
}
}
nsScriptNameSpaceManager *nameSpaceManager =
nsJSRuntime::GetNameSpaceManager();
NS_ENSURE_TRUE(nameSpaceManager, NS_OK);
PRBool unused;
return ResolvePrototype(sXPConnect, win, cx, global, mData->mNameUTF16,
mData, nsnull, nameSpaceManager, proto, &unused);
}
// static
@ -5035,11 +5031,12 @@ nsWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
static const char*
FindConstructorContractID(PRInt32 aDOMClassInfoID)
FindConstructorContractID(const nsDOMClassInfoData *aDOMClassInfoData)
{
PRUint32 i;
for (i = 0; i < NS_ARRAY_LENGTH(kConstructorMap); ++i) {
if (kConstructorMap[i].mDOMClassInfoID == aDOMClassInfoID) {
if (&sClassInfoData[kConstructorMap[i].mDOMClassInfoID] ==
aDOMClassInfoData) {
return kConstructorMap[i].mContractID;
}
}
@ -5047,10 +5044,11 @@ FindConstructorContractID(PRInt32 aDOMClassInfoID)
}
static nsDOMConstructorFunc
FindConstructorFunc(PRInt32 aDOMClassInfoID)
FindConstructorFunc(const nsDOMClassInfoData *aDOMClassInfoData)
{
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(kConstructorFuncMap); ++i) {
if (kConstructorFuncMap[i].mDOMClassInfoID == aDOMClassInfoID) {
if (&sClassInfoData[kConstructorFuncMap[i].mDOMClassInfoID] ==
aDOMClassInfoData) {
return kConstructorFuncMap[i].mConstructorFunc;
}
}
@ -5065,14 +5063,14 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
nsresult rv;
nsCOMPtr<nsISupports> native;
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
const char *contractid =
FindConstructorContractID(name_struct->mDOMClassInfoID);
const nsDOMClassInfoData* ci_data =
&sClassInfoData[name_struct->mDOMClassInfoID];
const char *contractid = FindConstructorContractID(ci_data);
if (contractid) {
native = do_CreateInstance(contractid, &rv);
}
else {
nsDOMConstructorFunc func =
FindConstructorFunc(name_struct->mDOMClassInfoID);
nsDOMConstructorFunc func = FindConstructorFunc(ci_data);
if (func) {
rv = func(getter_AddRefs(native));
}
@ -5210,11 +5208,11 @@ DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
class nsDOMConstructor : public nsIDOMDOMConstructor
{
protected:
nsDOMConstructor(const PRUnichar *aName,
const nsGlobalNameStruct *aNameStruct,
nsDOMConstructor(const PRUnichar* aName,
PRBool aIsConstructable,
nsPIDOMWindow* aOwner)
: mClassName(aName),
mConstructable(IsConstructable(aNameStruct)),
mConstructable(aIsConstructable),
mWeakOwner(do_GetWeakReference(aOwner))
{
}
@ -5222,6 +5220,7 @@ protected:
public:
static nsresult Create(const PRUnichar* aName,
const nsDOMClassInfoData* aData,
const nsGlobalNameStruct* aNameStruct,
nsPIDOMWindow* aOwner,
nsDOMConstructor** aResult);
@ -5246,7 +5245,7 @@ public:
::JS_DefineUCProperty(cx, target,
reinterpret_cast<const jschar *>(mClassName),
nsCRT::strlen(mClassName), thisAsVal, nsnull,
nsnull, 0);
nsnull, JSPROP_PERMANENT);
sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty;
return ok ? NS_OK : NS_ERROR_UNEXPECTED;
@ -5288,14 +5287,23 @@ private:
return NS_OK;
}
static PRBool IsConstructable(const nsDOMClassInfoData *aData)
{
if (IS_EXTERNAL(aData)) {
const nsExternalDOMClassInfoData* data =
static_cast<const nsExternalDOMClassInfoData*>(aData);
return data->mConstructorCID != nsnull;
}
return FindConstructorContractID(aData) || FindConstructorFunc(aData);
}
static PRBool IsConstructable(const nsGlobalNameStruct *aNameStruct)
{
return
(aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
(FindConstructorContractID(aNameStruct->mDOMClassInfoID) ||
FindConstructorFunc(aNameStruct->mDOMClassInfoID))) ||
IsConstructable(&sClassInfoData[aNameStruct->mDOMClassInfoID])) ||
(aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo &&
aNameStruct->mData->mConstructorCID) ||
IsConstructable(aNameStruct->mData)) ||
aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructor ||
aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias;
}
@ -5308,6 +5316,7 @@ private:
//static
nsresult
nsDOMConstructor::Create(const PRUnichar* aName,
const nsDOMClassInfoData* aData,
const nsGlobalNameStruct* aNameStruct,
nsPIDOMWindow* aOwner,
nsDOMConstructor** aResult)
@ -5327,7 +5336,12 @@ nsDOMConstructor::Create(const PRUnichar* aName,
!(currentInner = aOwner)->IsInnerWindow())) {
return NS_ERROR_DOM_SECURITY_ERR;
}
*aResult = new nsDOMConstructor(aName, aNameStruct, currentInner);
PRBool constructable = aNameStruct ?
IsConstructable(aNameStruct) :
IsConstructable(aData);
*aResult = new nsDOMConstructor(aName, constructable, currentInner);
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
@ -5533,45 +5547,67 @@ nsDOMConstructor::ToString(nsAString &aResult)
static nsresult
ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
JSObject *obj, JSString *str,
const nsGlobalNameStruct *name_struct,
nsScriptNameSpaceManager *nameSpaceManager,
PRBool *did_resolve)
GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin,
const nsGlobalNameStruct *aNameStruct,
nsIXPConnectJSObjectHolder **aProto)
{
NS_ASSERTION(name_struct->mType ==
NS_ASSERTION(aNameStruct->mType ==
nsGlobalNameStruct::eTypeClassConstructor ||
name_struct->mType ==
nsGlobalNameStruct::eTypeExternalClassInfo ||
name_struct->mType == nsGlobalNameStruct::eTypeClassProto ||
name_struct->mType ==
nsGlobalNameStruct::eTypeExternalConstructorAlias,
aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
"Wrong type!");
const nsDOMClassInfoData *ci_data = nsnull;
const nsGlobalNameStruct* alias_struct = nsnull;
nsCOMPtr<nsIClassInfo> ci;
if (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
PRInt32 id = aNameStruct->mDOMClassInfoID;
NS_ABORT_IF_FALSE(id >= 0, "Negative DOM classinfo?!?");
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
name_struct->mDOMClassInfoID >= 0) {
ci_data = &sClassInfoData[name_struct->mDOMClassInfoID];
} else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
ci_data = name_struct->mData;
} else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
alias_struct = nameSpaceManager->GetConstructorProto(name_struct);
NS_ENSURE_TRUE(alias_struct, NS_ERROR_UNEXPECTED);
nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id;
if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
ci_data = &sClassInfoData[alias_struct->mDOMClassInfoID];
} else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
ci_data = alias_struct->mData;
ci = NS_GetDOMClassInfoInstance(ci_id);
// In most cases we want to find the wrapped native prototype in
// aWin's scope and use that prototype for
// ClassName.prototype. But in the case where we're setting up
// "Window.prototype" or "ChromeWindow.prototype" we want to do
// the look up in aWin's outer window's scope since the inner
// window's wrapped native prototype comes from the outer
// window's scope.
if (ci_id == eDOMClassInfo_Window_id ||
ci_id == eDOMClassInfo_ModalContentWindow_id ||
ci_id == eDOMClassInfo_ChromeWindow_id) {
nsGlobalWindow *scopeWindow = aWin->GetOuterWindowInternal();
if (scopeWindow) {
aWin = scopeWindow;
}
}
}
else {
ci = nsDOMClassInfo::GetClassInfoInstance(aNameStruct->mData);
}
NS_ENSURE_TRUE(ci, NS_ERROR_UNEXPECTED);
return aXPConnect->GetWrappedNativePrototype(cx, aWin->GetGlobalJSObject(),
ci, aProto);
}
// Either ci_data must be non-null or name_struct must be non-null and of type
// eTypeClassProto.
static nsresult
ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
JSObject *obj, const PRUnichar *name,
const nsDOMClassInfoData *ci_data,
const nsGlobalNameStruct *name_struct,
nsScriptNameSpaceManager *nameSpaceManager,
JSObject *dot_prototype, PRBool *did_resolve)
{
NS_ASSERTION(ci_data ||
(name_struct &&
name_struct->mType == nsGlobalNameStruct::eTypeClassProto),
"Wrong type or missing ci_data!");
const PRUnichar *name = reinterpret_cast<PRUnichar *>
(::JS_GetStringChars(str));
nsRefPtr<nsDOMConstructor> constructor;
nsresult rv = nsDOMConstructor::Create(name, name_struct,
static_cast<nsPIDOMWindow*>(aWin),
nsresult rv = nsDOMConstructor::Create(name, ci_data, name_struct, aWin,
getter_AddRefs(constructor));
NS_ENSURE_SUCCESS(rv, rv);
@ -5598,9 +5634,10 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
const nsIID *primary_iid = &NS_GET_IID(nsISupports);
if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
if (!ci_data) {
primary_iid = &name_struct->mIID;
} else if (ci_data && ci_data->mProtoChainInterface) {
}
else if (ci_data->mProtoChainInterface) {
primary_iid = ci_data->mProtoChainInterface;
}
@ -5690,77 +5727,7 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
}
}
JSObject *dot_prototype = nsnull;
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
name_struct = alias_struct;
}
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
PRInt32 id = name_struct->mDOMClassInfoID;
NS_ABORT_IF_FALSE(id >= 0, "Negative DOM classinfo?!?");
nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id;
nsCOMPtr<nsIClassInfo> ci(NS_GetDOMClassInfoInstance(ci_id));
NS_ENSURE_TRUE(ci, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
// In most cases we want to find the wrapped native prototype in
// aWin's scope and use that prototype for
// ClassName.prototype. But in the case where we're setting up
// "Window.prototype" or "ChromeWindow.prototype" we want to do
// the look up in aWin's outer window's scope since the inner
// window's wrapped native prototype comes from the outer
// window's scope.
nsGlobalWindow *scopeWindow;
if (ci_id == eDOMClassInfo_Window_id ||
ci_id == eDOMClassInfo_ChromeWindow_id) {
scopeWindow = aWin->GetOuterWindowInternal();
if (!scopeWindow) {
scopeWindow = aWin;
}
} else {
scopeWindow = aWin;
}
rv =
aXPConnect->GetWrappedNativePrototype(cx,
scopeWindow->GetGlobalJSObject(),
ci,
getter_AddRefs(proto_holder));
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
rv = proto_holder->GetJSObject(&dot_prototype);
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
JSObject *xpc_proto_proto = ::JS_GetPrototype(cx, dot_prototype);
if (proto &&
(!xpc_proto_proto ||
JS_GET_CLASS(cx, xpc_proto_proto) == sObjectClass)) {
if (!::JS_SetPrototype(cx, dot_prototype, proto)) {
return NS_ERROR_UNEXPECTED;
}
}
} else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
nsCOMPtr<nsIClassInfo> ci =
nsDOMClassInfo::GetClassInfoInstance(name_struct->mData);
NS_ENSURE_TRUE(ci, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
rv =
aXPConnect->GetWrappedNativePrototype(cx, obj, ci,
getter_AddRefs(proto_holder));
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
rv = proto_holder->GetJSObject(&dot_prototype);
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
if (dot_prototype) {
JSObject *xpc_proto_proto = ::JS_GetPrototype(cx, dot_prototype);
if (proto &&
@ -5828,8 +5795,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
// direct DOM class, create a constructor object...
nsRefPtr<nsDOMConstructor> constructor;
rv = nsDOMConstructor::Create(reinterpret_cast<PRUnichar *>
(::JS_GetStringChars(str)),
rv = nsDOMConstructor::Create(class_name,
nsnull,
name_struct,
static_cast<nsPIDOMWindow*>(aWin),
getter_AddRefs(constructor));
@ -5867,16 +5834,58 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
}
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo ||
name_struct->mType == nsGlobalNameStruct::eTypeClassProto ||
name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
return ResolvePrototype(sXPConnect, aWin, cx, obj, str, name_struct,
nameSpaceManager, did_resolve);
name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
// Create the XPConnect prototype for our classinfo, PostCreateProto will
// set up the prototype chain.
nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
rv = GetXPCProto(sXPConnect, cx, aWin, name_struct,
getter_AddRefs(proto_holder));
*did_resolve = NS_SUCCEEDED(rv);
return rv;
}
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, nsnull,
name_struct, nameSpaceManager, nsnull, did_resolve);
}
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
const nsGlobalNameStruct *alias_struct =
nameSpaceManager->GetConstructorProto(name_struct);
NS_ENSURE_TRUE(alias_struct, NS_ERROR_UNEXPECTED);
// We need to use the XPConnect prototype for the DOM class that this
// constructor is an alias for (for example for Image we need the prototype
// for HTMLImageElement).
nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
rv = GetXPCProto(sXPConnect, cx, aWin, alias_struct,
getter_AddRefs(proto_holder));
NS_ENSURE_SUCCESS(rv, rv);
JSObject* dot_prototype;
rv = proto_holder->GetJSObject(&dot_prototype);
NS_ENSURE_SUCCESS(rv, rv);
const nsDOMClassInfoData *ci_data;
if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
ci_data = &sClassInfoData[alias_struct->mDOMClassInfoID];
} else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
ci_data = alias_struct->mData;
} else {
return NS_ERROR_UNEXPECTED;
}
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data,
name_struct, nameSpaceManager, nsnull, did_resolve);
}
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
nsRefPtr<nsDOMConstructor> constructor;
rv = nsDOMConstructor::Create(class_name, name_struct,
rv = nsDOMConstructor::Create(class_name, nsnull, name_struct,
static_cast<nsPIDOMWindow*>(aWin),
getter_AddRefs(constructor));
NS_ENSURE_SUCCESS(rv, rv);
@ -7502,9 +7511,6 @@ NS_IMETHODIMP
nsElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsresult rv = nsNodeSH::PostCreate(wrapper, cx, obj);
NS_ENSURE_SUCCESS(rv, rv);
nsIContent *content = static_cast<nsIContent*>(wrapper->Native());
#ifdef DEBUG
@ -8187,9 +8193,6 @@ nsDocumentSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_ERROR_UNEXPECTED;
}
nsresult rv = nsNodeSH::PostCreate(wrapper, cx, obj);
NS_ENSURE_SUCCESS(rv, rv);
nsIScriptGlobalObject *sgo = doc->GetScriptGlobalObject();
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(sgo);
if (!win) {
@ -8203,8 +8206,8 @@ nsDocumentSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval winVal;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, win, &NS_GET_IID(nsIDOMWindow), &winVal,
getter_AddRefs(holder));
nsresult rv = WrapNative(cx, obj, win, &NS_GET_IID(nsIDOMWindow), &winVal,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_STRING(doc_str, "document");
@ -9467,11 +9470,8 @@ NS_IMETHODIMP
nsHTMLPluginObjElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj)
{
nsresult rv = nsElementSH::PostCreate(wrapper, cx, obj);
NS_ENSURE_SUCCESS(rv, rv);
if (nsContentUtils::IsSafeToRunScript()) {
rv = SetupProtoChain(wrapper, cx, obj);
nsresult rv = SetupProtoChain(wrapper, cx, obj);
// If SetupProtoChain failed then we're in real trouble. We're about to fail
// PostCreate but it's more than likely that we handed our (now invalid)

View File

@ -46,6 +46,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsIScriptContext.h"
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
#include "nsIScriptGlobalObject.h"
class nsIDOMWindow;
class nsIDOMNSHTMLOptionCollection;
@ -66,6 +67,7 @@ typedef nsresult (*nsDOMConstructorFunc)(nsISupports** aNewObject);
struct nsDOMClassInfoData
{
const char *mName;
const PRUnichar *mNameUTF16;
union {
nsDOMClassInfoConstructorFnc mConstructorFptr;
nsDOMClassInfoExternalConstructorFnc mExternalConstructorFptr;
@ -434,6 +436,28 @@ protected:
public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
#ifdef DEBUG
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj)
{
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
NS_ASSERTION(!sgo || sgo->GetGlobalJSObject() == nsnull,
"Multiple wrappers created for global object!");
return NS_OK;
}
NS_IMETHOD GetScriptableFlags(PRUint32 *aFlags)
{
PRUint32 flags;
nsresult rv = nsEventReceiverSH::GetScriptableFlags(&flags);
if (NS_SUCCEEDED(rv)) {
*aFlags = flags | nsIXPCScriptable::WANT_POSTCREATE;
}
return rv;
}
#endif
NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
@ -1535,6 +1559,10 @@ protected:
}
public:
NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto)
{
return NS_OK;
}
NS_IMETHOD Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 argc, jsval *argv, jsval *vp,
PRBool *_retval);

View File

@ -60,8 +60,7 @@
(DOM_BASE_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_NEWRESOLVE | \
nsIXPCScriptable::WANT_CHECKACCESS | \
nsIXPCScriptable::WANT_PRECREATE | \
nsIXPCScriptable::WANT_POSTCREATE)
nsIXPCScriptable::WANT_PRECREATE)
#define DOM_DEFAULT_SCRIPTABLE_FLAGS \
(DEFAULT_SCRIPTABLE_FLAGS | \

View File

@ -148,7 +148,8 @@ nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
}
nsGlobalNameStruct *
nsScriptNameSpaceManager::AddToHash(const char *aKey)
nsScriptNameSpaceManager::AddToHash(const char *aKey,
const PRUnichar **aClassName)
{
NS_ConvertASCIItoUTF16 key(aKey);
GlobalNameMapEntry *entry =
@ -159,6 +160,10 @@ nsScriptNameSpaceManager::AddToHash(const char *aKey)
return nsnull;
}
if (aClassName) {
*aClassName = entry->mKey.get();
}
return &entry->mGlobalName;
}
@ -571,13 +576,14 @@ nsScriptNameSpaceManager::LookupName(const nsAString& aName,
nsresult
nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
PRInt32 aDOMClassInfoID)
PRInt32 aDOMClassInfoID,
const PRUnichar **aResult)
{
if (!nsCRT::IsAscii(aClassName)) {
NS_ERROR("Trying to register a non-ASCII class name");
return NS_OK;
}
nsGlobalNameStruct *s = AddToHash(aClassName);
nsGlobalNameStruct *s = AddToHash(aClassName, aResult);
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
if (s->mType == nsGlobalNameStruct::eTypeClassConstructor) {
@ -659,7 +665,8 @@ nsScriptNameSpaceManager::RegisterDOMCIData(const char *aName,
PRBool aHasClassInterface,
const nsCID *aConstructorCID)
{
nsGlobalNameStruct *s = AddToHash(aName);
const PRUnichar* className;
nsGlobalNameStruct *s = AddToHash(aName, &className);
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
// If an external constructor is already defined with aClassName we
@ -680,6 +687,7 @@ nsScriptNameSpaceManager::RegisterDOMCIData(const char *aName,
s->mType = nsGlobalNameStruct::eTypeExternalClassInfo;
s->mData->mName = aName;
s->mData->mNameUTF16 = className;
if (aConstructorFptr)
s->mData->u.mExternalConstructorFptr = aConstructorFptr;
else

View File

@ -101,6 +101,7 @@ private:
class nsIScriptContext;
class nsICategoryManager;
class GlobalNameMapEntry;
class nsScriptNameSpaceManager
@ -122,7 +123,8 @@ public:
const PRUnichar **aClassName = nsnull);
nsresult RegisterClassName(const char *aClassName,
PRInt32 aDOMClassInfoID);
PRInt32 aDOMClassInfoID,
const PRUnichar **aResult);
nsresult RegisterClassProto(const char *aClassName,
const nsIID *aConstructorProtoIID,
@ -150,7 +152,8 @@ protected:
// that aKey will be mapped to. If mType in the returned
// nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
// already existed.
nsGlobalNameStruct *AddToHash(const char *aKey);
nsGlobalNameStruct *AddToHash(const char *aKey,
const PRUnichar **aClassName = nsnull);
nsresult FillHash(nsICategoryManager *aCategoryManager,
const char *aCategory,

View File

@ -177,7 +177,5 @@ interface nsIXPCScriptable : nsISupports
JSObjectPtr innerObject(in nsIXPConnectWrappedNative wrapper,
in JSContextPtr cx, in JSObjectPtr obj);
// This method is called if the WANT_POSTCREATE bit is set in
// scriptableFlags.
void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto);
};

View File

@ -143,6 +143,8 @@ XPCWrappedNativeProto::Init(
nsresult rv = callback->PostCreatePrototype(ccx, mJSProtoObject);
if(NS_FAILED(rv))
{
JS_SetPrivate(ccx, mJSProtoObject, nsnull);
mJSProtoObject = nsnull;
XPCThrower::Throw(rv, ccx);
return JS_FALSE;
}