Fix for bug 91557 (constructor property of DOM Object instances return incorrect constructor). sr=jst, sr=brendan.

This commit is contained in:
peterv%netscape.com 2003-01-22 03:22:35 +00:00
parent cfdbf03787
commit f88e30a75d
8 changed files with 359 additions and 198 deletions

View File

@ -280,6 +280,7 @@ enum nsDOMClassInfoID {
nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE | \
nsIXPCScriptable::DONT_ASK_INSTANCE_FOR_SCRIPTABLE | \
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES | \
nsIXPCScriptable::WANT_NEWRESOLVE | \
nsIXPCScriptable::WANT_CHECKACCESS | \
nsIXPCScriptable::WANT_POSTCREATE)

View File

@ -320,7 +320,6 @@ static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
#define NODE_SCRIPTABLE_FLAGS \
((DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_PRECREATE | \
nsIXPCScriptable::WANT_NEWRESOLVE | \
nsIXPCScriptable::WANT_ADDPROPERTY | \
nsIXPCScriptable::WANT_SETPROPERTY) & \
~nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY)
@ -396,7 +395,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_GETPROPERTY |
nsIXPCScriptable::WANT_SETPROPERTY |
nsIXPCScriptable::WANT_NEWRESOLVE |
nsIXPCScriptable::WANT_PRECREATE |
nsIXPCScriptable::WANT_FINALIZE |
nsIXPCScriptable::WANT_ADDPROPERTY |
@ -824,6 +822,7 @@ jsval nsDOMClassInfo::sTop_id = JSVAL_VOID;
jsval nsDOMClassInfo::sScrollbars_id = JSVAL_VOID;
jsval nsDOMClassInfo::sLocation_id = JSVAL_VOID;
jsval nsDOMClassInfo::sComponents_id = JSVAL_VOID;
jsval nsDOMClassInfo::sConstructor_id = JSVAL_VOID;
jsval nsDOMClassInfo::s_content_id = JSVAL_VOID;
jsval nsDOMClassInfo::sContent_id = JSVAL_VOID;
jsval nsDOMClassInfo::sSidebar_id = JSVAL_VOID;
@ -920,6 +919,7 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
SET_JSVAL_TO_STRING(sScrollbars_id, cx, "scrollbars");
SET_JSVAL_TO_STRING(sLocation_id, cx, "location");
SET_JSVAL_TO_STRING(sComponents_id, cx, "Components");
SET_JSVAL_TO_STRING(sConstructor_id, cx, "constructor");
SET_JSVAL_TO_STRING(s_content_id, cx, "_content");
SET_JSVAL_TO_STRING(sContent_id, cx, "content");
SET_JSVAL_TO_STRING(sSidebar_id, cx, "sidebar");
@ -2537,14 +2537,45 @@ nsDOMClassInfo::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
return NS_ERROR_UNEXPECTED;
}
nsresult
nsDOMClassInfo::ResolveConstructor(JSContext *cx, JSObject *obj,
JSObject **objp)
{
JSObject *global = GetGlobalJSObject(cx, obj);
jsval val;
if (!::JS_GetProperty(cx, global, mData->mName, &val)) {
return NS_ERROR_UNEXPECTED;
}
if (!JSVAL_IS_PRIMITIVE(val)) {
// If val is not an (non-null) object there either is no
// constructor for this class, or someone messed with
// window.classname, just fall through and let the JS engine
// return the Object constructor.
JSString *str = JSVAL_TO_STRING(sConstructor_id);
if (!::JS_SetUCProperty(cx, obj, ::JS_GetStringChars(str),
::JS_GetStringLength(str), &val)) {
return NS_ERROR_UNEXPECTED;
}
*objp = obj;
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMClassInfo::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, PRUint32 flags,
JSObject **objp, PRBool *_retval)
{
NS_ERROR("Don't call me!");
if (id == sConstructor_id && !(flags & JSRESOLVE_ASSIGNING)) {
return ResolveConstructor(cx, obj, objp);
}
return NS_ERROR_UNEXPECTED;
return NS_OK;
}
NS_IMETHODIMP
@ -2714,6 +2745,7 @@ nsDOMClassInfo::ShutDown()
sScrollbars_id = JSVAL_VOID;
sLocation_id = JSVAL_VOID;
sComponents_id = JSVAL_VOID;
sConstructor_id = JSVAL_VOID;
s_content_id = JSVAL_VOID;
sContent_id = JSVAL_VOID;
sSidebar_id = JSVAL_VOID;
@ -3141,77 +3173,11 @@ nsWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
static JSBool PR_CALLBACK
StubConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
static JSBool
BaseStubConstructor(const nsGlobalNameStruct *name_struct, JSContext *cx,
JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSFunction *fun = ::JS_ValueToFunction(cx, argv[-2]);
if (!fun)
return JS_FALSE;
extern nsScriptNameSpaceManager *gNameSpaceManager;
if (!gNameSpaceManager) {
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_NOT_INITIALIZED);
NS_ERROR("No nsScriptNameSpaceManager!");
return JS_FALSE;
}
const char *name = ::JS_GetFunctionName(fun);
nsAutoString nameStr;
nameStr.AssignWithConversion(name);
const nsGlobalNameStruct *name_struct = nsnull;
nsresult rv = gNameSpaceManager->LookupName(nameStr, &name_struct);
if (NS_FAILED(rv) || !name_struct ||
(name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructor &&
name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias &&
name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfoCreator &&
name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo)) {
return JS_FALSE;
}
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
nsCOMPtr<nsIDOMCIExtension> creator =
do_CreateInstance(name_struct->mCID, &rv);
if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, rv);
NS_ERROR("Couldn't create the DOMCI extender");
return JS_FALSE;
}
nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID));
if (sof) {
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_FAILURE);
NS_ERROR("Couldn't get the DOM script object factory");
return JS_FALSE;
}
rv = creator->RegisterDOMCI(name, sof);
if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, rv);
NS_ERROR("Failed to register the DOM ClassInfo data");
return JS_FALSE;
}
rv = gNameSpaceManager->LookupName(nameStr, &name_struct);
if (NS_FAILED(rv) || !name_struct ||
name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo) {
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_FAILURE);
NS_ERROR("Couldn't get the DOM ClassInfo data");
return JS_FALSE;
}
}
nsresult rv;
nsCOMPtr<nsISupports> native;
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
native = do_CreateInstance(name_struct->mCID, &rv);
@ -3221,8 +3187,8 @@ StubConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
native = do_CreateInstance(*name_struct->mData->mConstructorCID, &rv);
}
if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, rv);
NS_ERROR("Failed to create the object");
nsDOMClassInfo::ThrowJSException(cx, rv);
return JS_FALSE;
}
@ -3232,6 +3198,7 @@ StubConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
rv = initializer->Initialize(cx, obj, argc, argv);
if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_NOT_INITIALIZED);
return JS_FALSE;
}
}
@ -3243,6 +3210,7 @@ StubConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
nsJSUtils::GetStaticScriptContext(cx, obj, getter_AddRefs(context));
if (!context) {
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
@ -3262,67 +3230,6 @@ StubConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return NS_SUCCEEDED(rv) ? JS_TRUE : JS_FALSE;
}
static JSObject *
GetInterfaceObject(JSContext *cx, JSObject *obj, const char *aName)
{
jsval components_val;
if (!::JS_GetProperty(cx, obj, "Components", &components_val)) {
return nsnull;
}
if (JSVAL_IS_PRIMITIVE(components_val)) {
return nsnull;
}
jsval if_val = JSVAL_VOID;
if (!::JS_GetProperty(cx, JSVAL_TO_OBJECT(components_val), "interfaces",
&if_val)) {
return nsnull;
}
if (JSVAL_IS_PRIMITIVE(if_val)) {
return nsnull;
}
jsval val;
if (!::JS_GetProperty(cx, JSVAL_TO_OBJECT(if_val), aName, &val)) {
return nsnull;
}
if (JSVAL_IS_PRIMITIVE(val)) {
return nsnull;
}
return JSVAL_TO_OBJECT(val);
}
// static
nsresult
nsWindowSH::DefineInterfaceProperty(JSContext *cx, JSObject *obj,
JSString *str)
{
nsCAutoString name("nsIDOM");
name.Append(::JS_GetStringBytes(str));
JSObject *if_object = GetInterfaceObject(cx, obj, name.get());
if (!if_object) {
return NS_ERROR_UNEXPECTED;
}
if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
::JS_GetStringLength(str),
OBJECT_TO_JSVAL(if_object), nsnull, nsnull, 0)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
static nsresult
DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
{
@ -3379,17 +3286,258 @@ DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
return NS_OK;
}
static JSBool JS_DLL_CALLBACK
NativeConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
JS_STATIC_DLL_CALLBACK(JSBool)
DOMJSClass_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
*rval = JSVAL_VOID;
JSObject* class_obj = JSVAL_TO_OBJECT(argv[-2]);
if (!class_obj) {
NS_ERROR("DOMJSClass_Construct couldn't get constructor object.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
// ignore return value, we return JS_FALSE anyway
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
NS_ERROR("object instantiated without constructor");
return JS_FALSE;
}
return JS_FALSE;
const PRUnichar* class_name =
NS_CONST_CAST(const PRUnichar*,
NS_STATIC_CAST(PRUnichar*,
::JS_GetPrivate(cx, class_obj)));
extern nsScriptNameSpaceManager *gNameSpaceManager;
if (!class_name || !gNameSpaceManager) {
NS_ERROR("DOMJSClass_Construct can't get name or namespace manager.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
const nsGlobalNameStruct *name_struct = nsnull;
gNameSpaceManager->LookupName(nsDependentString(class_name),
&name_struct);
if (!name_struct) {
NS_ERROR("Name isn't in hash.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
if ((name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo ||
!name_struct->mData->mConstructorCID) &&
name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias) {
// ignore return value, we return JS_FALSE anyway
NS_ERROR("object instantiated without constructor");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return JS_FALSE;
}
return BaseStubConstructor(name_struct, cx, obj, argc, argv, rval);
}
JS_STATIC_DLL_CALLBACK(void)
DOMJSClass_Finalize(JSContext *cx, JSObject *obj)
{
void* class_name = ::JS_GetPrivate(cx, obj);
if (class_name) {
nsMemory::Free(class_name);
}
}
JS_STATIC_DLL_CALLBACK(JSBool)
DOMJSClass_HasInstance(JSContext *cx, JSObject *obj, jsval v,
JSBool *bp)
{
JSObject *dom_obj;
if (!::JS_ValueToObject(cx, v, &dom_obj)) {
NS_ERROR("DOMJSClass_HasInstance called on non-object");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return JS_FALSE;
}
if (!dom_obj) {
return JS_TRUE;
}
JSClass* dom_class = JS_GET_CLASS(cx, dom_obj);
if (!dom_class) {
NS_ERROR("DOMJSClass_HasInstance can't get class.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
if (dom_class != &nsDOMClassInfo::sDOMJSClass) {
return JS_TRUE;
}
const nsGlobalNameStruct *name_struct = nsnull;
extern nsScriptNameSpaceManager *gNameSpaceManager;
if (!gNameSpaceManager) {
NS_ERROR("DOMJSClass_HasInstance can't get namespace manager.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
gNameSpaceManager->LookupName(NS_ConvertASCIItoUCS2(dom_class->name),
&name_struct);
if (!name_struct) {
NS_ERROR("Name isn't in hash.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo ||
name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias,
"The constructor was set up with a struct of the wrong type.");
const PRUnichar* class_name =
NS_CONST_CAST(const PRUnichar*,
NS_STATIC_CAST(PRUnichar*,
::JS_GetPrivate(cx, obj)));
if (!class_name) {
NS_ERROR("DOMJSClass_HasInstance can't get name.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
const nsGlobalNameStruct *class_name_struct = nsnull;
gNameSpaceManager->LookupName(nsDependentString(class_name),
&class_name_struct);
if (!class_name_struct) {
NS_ERROR("Name isn't in hash.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
if (class_name_struct->mType != nsGlobalNameStruct::eTypeClassProto &&
class_name_struct->mType != nsGlobalNameStruct::eTypeInterface) {
*bp = (name_struct == class_name_struct);
return JS_TRUE;
}
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
name_struct = gNameSpaceManager->GetConstructorProto(name_struct);
if (!name_struct) {
NS_ERROR("Couldn't get constructor prototype.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
}
NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
"The constructor was set up with a struct of the wrong type.");
const nsDOMClassInfoData *ci_data = nsnull;
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;
}
nsCOMPtr<nsIInterfaceInfoManager> iim =
dont_AddRef(XPTI_GetInterfaceInfoManager());
if (!iim) {
NS_ERROR("DOMJSClass_HasInstance can't get interface info mgr.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
nsCOMPtr<nsIInterfaceInfo> if_info;
PRUint32 count = 0;
const nsIID* class_interface;
while ((class_interface = ci_data->mInterfaces[count++])) {
if (class_name_struct->mIID.Equals(*class_interface)) {
*bp = JS_TRUE;
return JS_TRUE;
}
iim->GetInfoForIID(class_interface, getter_AddRefs(if_info));
if (!if_info) {
NS_ERROR("DOMJSClass_HasInstance can't get interface info.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
if_info->HasAncestor(&class_name_struct->mIID, bp);
if (*bp) {
return JS_TRUE;
}
}
return JS_TRUE;
}
JS_STATIC_DLL_CALLBACK(JSBool)
DOMJSClass_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
const PRUnichar* class_name =
NS_CONST_CAST(const PRUnichar*,
NS_STATIC_CAST(PRUnichar*,
::JS_GetPrivate(cx, obj)));
if (!class_name) {
NS_ERROR("DOMJSClass_HasInstance can't get name.");
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
return JS_FALSE;
}
nsAutoString resultString('[');
resultString.Append(class_name);
resultString.Append(PRUnichar(']'));
JSString* str = ::JS_NewUCStringCopyN(cx,
NS_REINTERPRET_CAST(const jschar *,
resultString.get()),
resultString.Length());
NS_ENSURE_TRUE(str, JS_FALSE);
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
}
JSClass nsDOMClassInfo::sDOMJSClass = {
"DOM Class", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, DOMJSClass_Finalize,
nsnull, nsnull, nsnull, DOMJSClass_Construct,
nsnull, DOMJSClass_HasInstance
};
JSFunctionSpec nsDOMClassInfo::sDOMJSClass_methods[] = {
{"toString", DOMJSClass_toString, 0, 0, 0},
{0, 0, 0, 0, 0}
};
// static
nsresult
nsDOMClassInfo::InitDOMJSClass(JSContext *cx, JSObject *obj)
{
JSObject *proto = ::JS_InitClass(cx, obj, nsnull, &sDOMJSClass, nsnull, 0,
nsnull, sDOMJSClass_methods, nsnull,
nsnull);
NS_ASSERTION(proto, "Can't initialize DOM class proto.");
if (!proto) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
// static
@ -3437,8 +3585,20 @@ nsWindowSH::GlobalResolve(nsISupports *native, JSContext *cx, JSObject *obj,
}
if (name_struct->mType == nsGlobalNameStruct::eTypeInterface) {
rv = DefineInterfaceProperty(cx, obj, str);
NS_ENSURE_SUCCESS(rv, rv);
JSObject* class_obj = ::JS_DefineObject(cx, obj, ::JS_GetStringBytes(str),
&sDOMJSClass, 0, 0);
if (!class_obj) {
return NS_ERROR_UNEXPECTED;
}
PRUnichar* class_name = ToNewUnicode(name);
NS_ENSURE_TRUE(class_name, NS_ERROR_OUT_OF_MEMORY);
if (!::JS_SetPrivate(cx, class_obj, class_name)) {
nsMemory::Free(class_name);
return NS_ERROR_UNEXPECTED;
}
*did_resolve = PR_TRUE;
@ -3468,25 +3628,18 @@ nsWindowSH::GlobalResolve(nsISupports *native, JSContext *cx, JSObject *obj,
}
}
JSNative native;
if ((name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo &&
name_struct->mData->mConstructorCID) ||
name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
native = StubConstructor;
} else {
native = NativeConstructor;
}
JSFunction *cfnc = ::JS_DefineFunction(cx, obj, ::JS_GetStringBytes(str),
native, 0, 0);
if (!cfnc) {
JSObject* class_obj = ::JS_DefineObject(cx, obj, ::JS_GetStringBytes(str),
&sDOMJSClass, 0, 0);
if (!class_obj) {
return NS_ERROR_UNEXPECTED;
}
JSObject *cfnc_obj = ::JS_GetFunctionObject(cfnc);
PRUnichar* class_name = ToNewUnicode(name);
NS_ENSURE_TRUE(class_name, NS_ERROR_OUT_OF_MEMORY);
if (!::JS_SetPrivate(cx, class_obj, class_name)) {
nsMemory::Free(class_name);
if (!cfnc_obj) {
return NS_ERROR_UNEXPECTED;
}
@ -3501,13 +3654,13 @@ nsWindowSH::GlobalResolve(nsISupports *native, JSContext *cx, JSObject *obj,
nsXPIDLCString class_parent_name;
if (!primary_iid->Equals(NS_GET_IID(nsISupports))) {
rv = DefineInterfaceConstants(cx, cfnc_obj, primary_iid);
rv = DefineInterfaceConstants(cx, class_obj, primary_iid);
NS_ENSURE_SUCCESS(rv, rv);
// Special case for |Event|, Event needs constants from NSEvent
// too for backwards compatibility.
if (primary_iid->Equals(NS_GET_IID(nsIDOMEvent))) {
rv = DefineInterfaceConstants(cx, cfnc_obj,
rv = DefineInterfaceConstants(cx, class_obj,
&NS_GET_IID(nsIDOMNSEvent));
NS_ENSURE_SUCCESS(rv, rv);
}
@ -3640,7 +3793,7 @@ nsWindowSH::GlobalResolve(nsISupports *native, JSContext *cx, JSObject *obj,
jsval v = OBJECT_TO_JSVAL(dot_prototype);
if (!::JS_SetProperty(cx, cfnc_obj, "prototype", &v)) {
if (!::JS_SetProperty(cx, class_obj, "prototype", &v)) {
return NS_ERROR_UNEXPECTED;
}
@ -3653,7 +3806,8 @@ nsWindowSH::GlobalResolve(nsISupports *native, JSContext *cx, JSObject *obj,
// If there was a JS_DefineUCFunction() I could use it here, but
// no big deal...
JSFunction *f = ::JS_DefineFunction(cx, obj, ::JS_GetStringBytes(str),
StubConstructor, 0, JSPROP_READONLY);
DOMJSClass_Construct, 0,
JSPROP_READONLY);
if (!f) {
return NS_ERROR_OUT_OF_MEMORY;
@ -3763,6 +3917,10 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
if (id == sConstructor_id && !(flags & JSRESOLVE_ASSIGNING)) {
return ResolveConstructor(cx, obj, objp);
}
if (JSVAL_IS_STRING(id)) {
JSString *str = JSVAL_TO_STRING(id);
nsCOMPtr<nsISupports> native;
@ -4300,7 +4458,8 @@ nsEventRecieverSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
*objp = obj;
}
return rv;
return nsDOMClassInfo::NewResolve(wrapper, cx, obj, id, flags, objp,
_retval);
}
NS_IMETHODIMP

View File

@ -127,6 +127,10 @@ public:
jsval *vp);
static nsresult ThrowJSException(JSContext *cx, nsresult aResult);
static nsresult InitDOMJSClass(JSContext *cx, JSObject *obj);
static JSClass sDOMJSClass;
protected:
const nsDOMClassInfoData* mData;
@ -134,6 +138,8 @@ protected:
static nsresult RegisterClassName(PRInt32 aDOMClassInfoID);
static nsresult RegisterClassProtos(PRInt32 aDOMClassInfoID);
static nsresult RegisterExternalClasses();
nsresult ResolveConstructor(JSContext *cx, JSObject *obj,
JSObject **objp);
// Checks if id is a number and returns the number, if aIsNumber is
// non-null it's set to true if the id is a number and false if it's
@ -176,6 +182,7 @@ protected:
PRUint32 accessMode, PRBool isWindow);
static JSClass sDOMConstructorProtoClass;
static JSFunctionSpec sDOMJSClass_methods[];
static nsIXPConnect *sXPConnect;
static nsIScriptSecurityManager *sSecMan;
@ -189,6 +196,7 @@ protected:
static jsval sScrollbars_id;
static jsval sLocation_id;
static jsval sComponents_id;
static jsval sConstructor_id;
static jsval s_content_id;
static jsval sContent_id;
static jsval sSidebar_id;
@ -309,8 +317,6 @@ protected:
static nsresult GlobalResolve(nsISupports *aNative, JSContext *cx,
JSObject *obj, JSString *str, PRUint32 flags,
PRBool *did_resolve);
static nsresult DefineInterfaceProperty(JSContext *cx, JSObject *obj,
JSString *str);
public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,

View File

@ -1436,6 +1436,9 @@ nsJSContext::InitClasses()
rv = InitializeLiveConnectClasses();
NS_ENSURE_SUCCESS(rv, rv);
rv = nsDOMClassInfo::InitDOMJSClass(mContext, globalObj);
NS_ENSURE_SUCCESS(rv, rv);
// Initialize the options object and set default options in mContext
JSObject *optionsObj = ::JS_DefineObject(mContext, globalObj, "_options",
&OptionsClass, nsnull, 0);

View File

@ -307,6 +307,7 @@ nsScriptNameSpaceManager::FillHashWithDOMInterfaces()
PRBool found_old;
nsCOMPtr<nsIInterfaceInfo> if_info;
nsXPIDLCString if_name;
const nsIID *iid;
for ( ; domInterfaces->IsDone() == NS_ENUMERATOR_FALSE; domInterfaces->Next()) {
rv = domInterfaces->CurrentItem(getter_AddRefs(entry));
@ -314,9 +315,9 @@ nsScriptNameSpaceManager::FillHashWithDOMInterfaces()
nsCOMPtr<nsIInterfaceInfo> if_info(do_QueryInterface(entry));
if_info->GetName(getter_Copies(if_name));
rv = RegisterInterface(if_info,
if_name.get() + sizeof(NS_DOM_INTERFACE_PREFIX) - 1,
&found_old);
if_info->GetIIDShared(&iid);
rv = RegisterInterface(if_name.get() + sizeof(NS_DOM_INTERFACE_PREFIX) - 1,
iid, &found_old);
#ifdef DEBUG
NS_ASSERTION(!found_old,
@ -406,7 +407,7 @@ nsScriptNameSpaceManager::RegisterExternalInterfaces(PRBool aAsProto)
if (aAsProto) {
RegisterClassProto(name, iid, &found_old);
} else {
RegisterInterface(if_info, name, &found_old);
RegisterInterface(name, iid, &found_old);
}
if (found_old) {
@ -422,16 +423,10 @@ nsScriptNameSpaceManager::RegisterExternalInterfaces(PRBool aAsProto)
}
nsresult
nsScriptNameSpaceManager::RegisterInterface(nsIInterfaceInfo* aIfInfo,
const char* aIfName,
nsScriptNameSpaceManager::RegisterInterface(const char* aIfName,
const nsIID *aIfIID,
PRBool* aFoundOld)
{
NS_ASSERTION(aIfInfo, "Interface info not an nsIInterfaceInfo!");
// With the InterfaceInfo system it is actually cheaper to get the
// interface name than to get the count of constants. The former is
// always cached. The latter might require loading an xpt file!
*aFoundOld = PR_FALSE;
nsGlobalNameStruct *s = AddToHash(NS_ConvertASCIItoUCS2(aIfName));
@ -444,6 +439,7 @@ nsScriptNameSpaceManager::RegisterInterface(nsIInterfaceInfo* aIfInfo,
}
s->mType = nsGlobalNameStruct::eTypeInterface;
s->mIID = *aIfIID;
return NS_OK;
}

View File

@ -68,7 +68,7 @@ struct nsGlobalNameStruct
union {
PRInt32 mDOMClassInfoID; // eTypeClassConstructor
nsIID mIID; // eTypeClassProto
nsIID mIID; // eTypeInterface, eTypeClassProto
nsExternalDOMClassInfoData* mData; // eTypeExternalClassInfo
ConstructorAlias* mAlias; // eTypeExternalConstructorAlias
nsCID mCID; // All other types...
@ -134,8 +134,8 @@ protected:
const char *aCategory,
nsGlobalNameStruct::nametype aType);
nsresult FillHashWithDOMInterfaces();
nsresult RegisterInterface(nsIInterfaceInfo* aIfInfo,
const char* aIfName,
nsresult RegisterInterface(const char* aIfName,
const nsIID *aIfIID,
PRBool* aFoundOld);
// Inline PLDHashTable, init with PL_DHashTableInit() and delete

View File

@ -307,6 +307,7 @@ nsScriptNameSpaceManager::FillHashWithDOMInterfaces()
PRBool found_old;
nsCOMPtr<nsIInterfaceInfo> if_info;
nsXPIDLCString if_name;
const nsIID *iid;
for ( ; domInterfaces->IsDone() == NS_ENUMERATOR_FALSE; domInterfaces->Next()) {
rv = domInterfaces->CurrentItem(getter_AddRefs(entry));
@ -314,9 +315,9 @@ nsScriptNameSpaceManager::FillHashWithDOMInterfaces()
nsCOMPtr<nsIInterfaceInfo> if_info(do_QueryInterface(entry));
if_info->GetName(getter_Copies(if_name));
rv = RegisterInterface(if_info,
if_name.get() + sizeof(NS_DOM_INTERFACE_PREFIX) - 1,
&found_old);
if_info->GetIIDShared(&iid);
rv = RegisterInterface(if_name.get() + sizeof(NS_DOM_INTERFACE_PREFIX) - 1,
iid, &found_old);
#ifdef DEBUG
NS_ASSERTION(!found_old,
@ -406,7 +407,7 @@ nsScriptNameSpaceManager::RegisterExternalInterfaces(PRBool aAsProto)
if (aAsProto) {
RegisterClassProto(name, iid, &found_old);
} else {
RegisterInterface(if_info, name, &found_old);
RegisterInterface(name, iid, &found_old);
}
if (found_old) {
@ -422,16 +423,10 @@ nsScriptNameSpaceManager::RegisterExternalInterfaces(PRBool aAsProto)
}
nsresult
nsScriptNameSpaceManager::RegisterInterface(nsIInterfaceInfo* aIfInfo,
const char* aIfName,
nsScriptNameSpaceManager::RegisterInterface(const char* aIfName,
const nsIID *aIfIID,
PRBool* aFoundOld)
{
NS_ASSERTION(aIfInfo, "Interface info not an nsIInterfaceInfo!");
// With the InterfaceInfo system it is actually cheaper to get the
// interface name than to get the count of constants. The former is
// always cached. The latter might require loading an xpt file!
*aFoundOld = PR_FALSE;
nsGlobalNameStruct *s = AddToHash(NS_ConvertASCIItoUCS2(aIfName));
@ -444,6 +439,7 @@ nsScriptNameSpaceManager::RegisterInterface(nsIInterfaceInfo* aIfInfo,
}
s->mType = nsGlobalNameStruct::eTypeInterface;
s->mIID = *aIfIID;
return NS_OK;
}

View File

@ -68,7 +68,7 @@ struct nsGlobalNameStruct
union {
PRInt32 mDOMClassInfoID; // eTypeClassConstructor
nsIID mIID; // eTypeClassProto
nsIID mIID; // eTypeInterface, eTypeClassProto
nsExternalDOMClassInfoData* mData; // eTypeExternalClassInfo
ConstructorAlias* mAlias; // eTypeExternalConstructorAlias
nsCID mCID; // All other types...
@ -134,8 +134,8 @@ protected:
const char *aCategory,
nsGlobalNameStruct::nametype aType);
nsresult FillHashWithDOMInterfaces();
nsresult RegisterInterface(nsIInterfaceInfo* aIfInfo,
const char* aIfName,
nsresult RegisterInterface(const char* aIfName,
const nsIID *aIfIID,
PRBool* aFoundOld);
// Inline PLDHashTable, init with PL_DHashTableInit() and delete