Fix for bug 370098 (Some constructors raise a "XXX is not a function" exception when called (DOMParser, XMLSerializer, XMLHttpRequest, XPathEvaluator, XSLTProcessor). r/sr=jst.

This commit is contained in:
peterv@propagandism.org 2007-05-09 05:04:59 -07:00
parent 5f0f450b28
commit ca51c50cc2
4 changed files with 126 additions and 69 deletions

View File

@ -56,6 +56,7 @@ enum nsDOMClassInfoID {
eDOMClassInfo_BarProp_id,
eDOMClassInfo_History_id,
eDOMClassInfo_Screen_id,
eDOMClassInfo_Prototype_id,
eDOMClassInfo_Constructor_id,
// Core classes

View File

@ -44,14 +44,17 @@
#include "nsDOMClassInfoID.h"
#include "nsIXPCScriptable.h"
#define DEFAULT_SCRIPTABLE_FLAGS \
#define DOM_BASE_SCRIPTABLE_FLAGS \
(nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY | \
nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY | \
nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \
nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE | \
nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE | \
nsIXPCScriptable::DONT_ASK_INSTANCE_FOR_SCRIPTABLE | \
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES | \
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES)
#define DEFAULT_SCRIPTABLE_FLAGS \
(DOM_BASE_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_NEWRESOLVE | \
nsIXPCScriptable::WANT_CHECKACCESS | \
nsIXPCScriptable::WANT_PRECREATE | \

View File

@ -453,7 +453,6 @@ static const char kDOMStringBundleURL[] =
#define NODE_SCRIPTABLE_FLAGS \
((DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_GETPROPERTY | \
nsIXPCScriptable::WANT_PRECREATE | \
nsIXPCScriptable::WANT_ADDPROPERTY | \
nsIXPCScriptable::WANT_SETPROPERTY) & \
~nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY)
@ -564,14 +563,14 @@ static nsDOMClassInfoData sClassInfoData[] = {
ARRAY_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Screen, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(Prototype, nsDOMConstructorSH,
DOM_BASE_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_HASINSTANCE)
NS_DEFINE_CLASSINFO_DATA(Constructor, nsDOMConstructorSH,
(DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_CONSTRUCT |
nsIXPCScriptable::WANT_HASINSTANCE) &
~(nsIXPCScriptable::WANT_PRECREATE |
nsIXPCScriptable::WANT_POSTCREATE |
nsIXPCScriptable::WANT_CHECKACCESS |
nsIXPCScriptable::WANT_NEWRESOLVE))
DOM_BASE_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_HASINSTANCE |
nsIXPCScriptable::WANT_CALL |
nsIXPCScriptable::WANT_CONSTRUCT)
// Core classes
NS_DEFINE_CLASSINFO_DATA(XMLDocument, nsDocumentSH,
@ -1859,6 +1858,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMScreen)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(Prototype, nsIDOMConstructor)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMConstructor)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(Constructor, nsIDOMConstructor)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMConstructor)
DOM_CLASSINFO_MAP_END
@ -4822,13 +4825,13 @@ DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
class nsDOMConstructor : public nsIDOMConstructor
{
public:
nsDOMConstructor(const PRUnichar *aName)
: mClassName(aName)
nsDOMConstructor(const PRUnichar *aName,
const nsGlobalNameStruct *aNameStruct)
: mClassName(aName),
mConstructable(IsConstructable(aNameStruct))
{
}
virtual ~nsDOMConstructor();
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMCONSTRUCTOR
@ -4858,7 +4861,54 @@ public:
}
private:
const nsGlobalNameStruct *GetNameStruct()
{
if (!mClassName) {
NS_ERROR("Can't get name");
return nsnull;
}
const nsGlobalNameStruct *nameStruct;
#ifdef DEBUG
nsresult rv =
#endif
GetNameStruct(nsDependentString(mClassName), &nameStruct);
NS_ASSERTION(NS_FAILED(rv) || nameStruct, "Name isn't in hash.");
return nameStruct;
}
static nsresult GetNameStruct(const nsAString& aName,
const nsGlobalNameStruct **aNameStruct)
{
*aNameStruct = nsnull;
extern nsScriptNameSpaceManager *gNameSpaceManager;
if (!gNameSpaceManager) {
NS_ERROR("Can't get namespace manager.");
return NS_ERROR_UNEXPECTED;
}
gNameSpaceManager->LookupName(aName, aNameStruct);
// Return NS_OK here, aName just isn't a DOM class but nothing failed.
return NS_OK;
}
static PRBool IsConstructable(const nsGlobalNameStruct *aNameStruct)
{
return
(aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
FindConstructorContractID(aNameStruct->mDOMClassInfoID)) ||
(aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo &&
aNameStruct->mData->mConstructorCID) ||
aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructor ||
aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias;
}
const PRUnichar *mClassName;
const PRPackedBool mConstructable;
};
NS_IMPL_ADDREF(nsDOMConstructor)
@ -4866,13 +4916,26 @@ NS_IMPL_RELEASE(nsDOMConstructor)
NS_INTERFACE_MAP_BEGIN(nsDOMConstructor)
NS_INTERFACE_MAP_ENTRY(nsIDOMConstructor)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Constructor)
if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
#ifdef DEBUG
{
const nsGlobalNameStruct *name_struct = GetNameStruct();
NS_ASSERTION(!name_struct ||
mConstructable == IsConstructable(name_struct),
"Can't change constructability dynamically!");
}
#endif
foundInterface =
NS_GetDOMClassInfoInstance(mConstructable ?
eDOMClassInfo_Constructor_id :
eDOMClassInfo_Prototype_id);
if (!foundInterface) {
*aInstancePtr = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
} else
NS_INTERFACE_MAP_END
nsDOMConstructor::~nsDOMConstructor()
{
}
nsresult
nsDOMConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, PRUint32 argc, jsval * argv,
@ -4884,27 +4947,11 @@ nsDOMConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
return NS_ERROR_UNEXPECTED;
}
extern nsScriptNameSpaceManager *gNameSpaceManager;
if (!mClassName || !gNameSpaceManager) {
NS_ERROR("nsDOMConstructor::Construct can't get name or namespace manager");
return NS_ERROR_UNEXPECTED;
}
const nsGlobalNameStruct *name_struct = GetNameStruct();
NS_ENSURE_TRUE(name_struct, NS_ERROR_FAILURE);
const nsGlobalNameStruct *name_struct = nsnull;
gNameSpaceManager->LookupName(nsDependentString(mClassName), &name_struct);
if (!name_struct) {
NS_ERROR("Name isn't in hash.");
return NS_ERROR_UNEXPECTED;
}
if ((name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor ||
!FindConstructorContractID(name_struct->mDOMClassInfoID)) &&
(name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo ||
!name_struct->mData->mConstructorCID) &&
name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructor &&
name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias) {
if (!IsConstructable(name_struct)) {
// ignore return value, we return JS_FALSE anyway
NS_ERROR("object instantiated without constructor");
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
@ -4941,19 +4988,11 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
return NS_ERROR_UNEXPECTED;
}
const nsGlobalNameStruct *name_struct = nsnull;
extern nsScriptNameSpaceManager *gNameSpaceManager;
if (!gNameSpaceManager) {
NS_ERROR("nsDOMConstructor::HasInstance can't get namespace manager.");
return NS_ERROR_UNEXPECTED;
}
gNameSpaceManager->LookupName(NS_ConvertASCIItoUTF16(dom_class->name),
&name_struct);
const nsGlobalNameStruct *name_struct;
nsresult rv = GetNameStruct(NS_ConvertASCIItoUTF16(dom_class->name),
&name_struct);
if (!name_struct) {
// Name isn't in hash, not a DOM object.
return NS_OK;
return rv;
}
if (name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor &&
@ -4963,18 +5002,8 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
return NS_OK;
}
if (!mClassName) {
NS_ERROR("nsDOMConstructor::HasInstance can't get name.");
return NS_ERROR_UNEXPECTED;
}
const nsGlobalNameStruct *class_name_struct = nsnull;
gNameSpaceManager->LookupName(nsDependentString(mClassName),
&class_name_struct);
if (!class_name_struct) {
NS_ERROR("Name isn't in hash.");
return NS_ERROR_UNEXPECTED;
}
const nsGlobalNameStruct *class_name_struct = GetNameStruct();
NS_ENSURE_TRUE(class_name_struct, NS_ERROR_FAILURE);
if (name_struct == class_name_struct) {
*bp = JS_TRUE;
@ -4982,6 +5011,9 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
return NS_OK;
}
extern nsScriptNameSpaceManager *gNameSpaceManager;
NS_ASSERTION(gNameSpaceManager, "Can't get namespace manager?");
const nsIID *class_iid;
if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
@ -5129,7 +5161,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
nsRefPtr<nsDOMConstructor> constructor =
new nsDOMConstructor(NS_REINTERPRET_CAST(PRUnichar *,
::JS_GetStringChars(str)));
::JS_GetStringChars(str)),
name_struct);
if (!constructor) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -5190,7 +5223,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
const PRUnichar *name = NS_REINTERPRET_CAST(PRUnichar *,
::JS_GetStringChars(str));
nsRefPtr<nsDOMConstructor> constructor = new nsDOMConstructor(name);
nsRefPtr<nsDOMConstructor> constructor =
new nsDOMConstructor(name, name_struct);
if (!constructor) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -5406,7 +5440,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
}
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
nsRefPtr<nsDOMConstructor> constructor = new nsDOMConstructor(class_name);
nsRefPtr<nsDOMConstructor> constructor =
new nsDOMConstructor(class_name, name_struct);
if (!constructor) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -9896,6 +9931,24 @@ nsEventListenerThisTranslator::TranslateThis(nsISupports *aInitialThis,
return NS_OK;
}
NS_IMETHODIMP
nsDOMConstructorSH::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 argc, jsval *argv, jsval *vp,
PRBool *_retval)
{
nsDOMConstructor *wrapped =
NS_STATIC_CAST(nsDOMConstructor *, wrapper->Native());
#ifdef DEBUG
{
nsCOMPtr<nsIDOMConstructor> is_constructor(do_QueryWrappedNative(wrapper));
NS_ASSERTION(is_constructor, "How did we not get a constructor?");
}
#endif
return wrapped->Construct(wrapper, cx, obj, argc, argv, vp, _retval);
}
NS_IMETHODIMP
nsDOMConstructorSH::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 argc, jsval *argv,

View File

@ -1519,11 +1519,11 @@ protected:
{
}
virtual ~nsDOMConstructorSH()
{
}
public:
NS_IMETHOD Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 argc, jsval *argv, jsval *vp,
PRBool *_retval);
NS_IMETHOD Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 argc, jsval *argv,
jsval *vp, PRBool *_retval);