зеркало из https://github.com/mozilla/pjs.git
Make XPCNativeWrapper call the wrapped native's classinfo resolve/get/set
hooks. Makes native wrappers work in lots of nasty DOM0 corner cases. Bug 296967, r=mrbkap, sr=jst, a=asa
This commit is contained in:
Родитель
9526108fcc
Коммит
31c1cac564
|
@ -637,7 +637,7 @@ calDateTime::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
|||
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
*_retval = PR_TRUE;
|
||||
return NS_OK;
|
||||
return NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -675,7 +675,7 @@ calDateTime::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
|||
}
|
||||
|
||||
*_retval = PR_TRUE;
|
||||
return NS_OK;
|
||||
return NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
}
|
||||
*_retval = PR_TRUE;
|
||||
|
|
|
@ -1098,9 +1098,21 @@ jsval nsDOMClassInfo::sTags_id = JSVAL_VOID;
|
|||
jsval nsDOMClassInfo::sAddEventListener_id= JSVAL_VOID;
|
||||
|
||||
const JSClass *nsDOMClassInfo::sObjectClass = nsnull;
|
||||
const JSClass *nsDOMClassInfo::sXPCNativeWrapperClass = nsnull;
|
||||
|
||||
PRBool nsDOMClassInfo::sDoSecurityCheckInAddProperty = PR_TRUE;
|
||||
|
||||
const JSClass*
|
||||
NS_DOMClassInfo_GetXPCNativeWrapperClass()
|
||||
{
|
||||
return nsDOMClassInfo::GetXPCNativeWrapperClass();
|
||||
}
|
||||
|
||||
void
|
||||
NS_DOMClassInfo_SetXPCNativeWrapperClass(JSClass* aClass)
|
||||
{
|
||||
nsDOMClassInfo::SetXPCNativeWrapperClass(aClass);
|
||||
}
|
||||
|
||||
static void
|
||||
PrintWarningOnConsole(JSContext *cx, const char *stringBundleProperty)
|
||||
|
@ -3794,7 +3806,7 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
NS_GET_IID(nsIDOMWindow), vp);
|
||||
}
|
||||
|
||||
return rv;
|
||||
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
|
||||
if (needsSecurityCheck(cx, wrapper)) {
|
||||
|
@ -3820,7 +3832,7 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
// Yup, *vp is a window object, return early (*vp is already
|
||||
// the window, so no need to wrap it again).
|
||||
|
||||
return NS_OK;
|
||||
return NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3877,7 +3889,8 @@ nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
rv = location->SetHref(nsDependentJSString(val));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp);
|
||||
rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp);
|
||||
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
|
||||
return nsEventReceiverSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
|
||||
|
@ -5754,6 +5767,10 @@ nsEventReceiverSH::RegisterCompileHandler(nsIXPConnectWrappedNative *wrapper,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (ObjectIsNativeWrapper(cx, obj)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsIScriptContext *script_cx = nsJSUtils::GetStaticScriptContext(cx, obj);
|
||||
NS_ENSURE_TRUE(script_cx, NS_ERROR_UNEXPECTED);
|
||||
|
||||
|
@ -5778,7 +5795,7 @@ nsEventReceiverSH::RegisterCompileHandler(nsIXPConnectWrappedNative *wrapper,
|
|||
rv = manager->RegisterScriptEventListener(script_cx, receiver, atom);
|
||||
}
|
||||
|
||||
return rv;
|
||||
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -5990,6 +6007,8 @@ nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
PRBool is_number = PR_FALSE;
|
||||
PRInt32 n = GetArrayIndexFromId(cx, id, &is_number);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (is_number) {
|
||||
if (n < 0) {
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
|
@ -5997,17 +6016,19 @@ nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
|
||||
nsCOMPtr<nsISupports> array_item;
|
||||
|
||||
nsresult rv = GetItemAt(wrapper->Native(), n, getter_AddRefs(array_item));
|
||||
rv = GetItemAt(wrapper->Native(), n, getter_AddRefs(array_item));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (array_item) {
|
||||
rv = WrapNative(cx, ::JS_GetGlobalObject(cx), array_item,
|
||||
NS_GET_IID(nsISupports), vp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
@ -6041,9 +6062,11 @@ nsNamedArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
rv = WrapNative(cx, ::JS_GetGlobalObject(cx), item,
|
||||
NS_GET_IID(nsISupports), vp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
|
||||
return NS_OK; // Don't fall through to nsArraySH::GetProperty() here
|
||||
return rv; // Don't fall through to nsArraySH::GetProperty() here
|
||||
}
|
||||
|
||||
return nsArraySH::GetProperty(wrapper, cx, obj, id, vp, _retval);
|
||||
|
@ -6410,7 +6433,8 @@ nsDocumentSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
rv = location->SetHref(nsDependentJSString(val));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp);
|
||||
rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp);
|
||||
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7074,7 +7098,8 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
return fnc ? NS_OK : NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (id == sAll_id && !sDisableDocumentAllSupport) {
|
||||
if (id == sAll_id && !sDisableDocumentAllSupport &&
|
||||
!ObjectIsNativeWrapper(cx, obj)) {
|
||||
nsCOMPtr<nsIHTMLDocument> doc(do_QueryWrappedNative(wrapper));
|
||||
|
||||
if (doc->GetCompatibilityMode() == eCompatibility_NavQuirks) {
|
||||
|
@ -7164,11 +7189,14 @@ nsHTMLDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (result) {
|
||||
return WrapNative(cx, ::JS_GetGlobalObject(cx), result,
|
||||
NS_GET_IID(nsISupports), vp);
|
||||
rv = WrapNative(cx, ::JS_GetGlobalObject(cx), result,
|
||||
NS_GET_IID(nsISupports), vp);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// HTMLElement helper
|
||||
|
@ -7297,8 +7325,9 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
if (result) {
|
||||
// Wrap result, result can be either an element or a list of
|
||||
// elements
|
||||
return WrapNative(cx, ::JS_GetGlobalObject(cx), result,
|
||||
NS_GET_IID(nsISupports), vp);
|
||||
nsresult rv = WrapNative(cx, ::JS_GetGlobalObject(cx), result,
|
||||
NS_GET_IID(nsISupports), vp);
|
||||
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
|
||||
return NS_OK; // Don't fall through
|
||||
|
@ -7311,8 +7340,9 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
form->GetElementAt(n, getter_AddRefs(control));
|
||||
|
||||
if (control) {
|
||||
return WrapNative(cx, ::JS_GetGlobalObject(cx), control,
|
||||
NS_GET_IID(nsISupports), vp);
|
||||
nsresult rv = WrapNative(cx, ::JS_GetGlobalObject(cx), control,
|
||||
NS_GET_IID(nsISupports), vp);
|
||||
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7404,6 +7434,7 @@ nsHTMLSelectElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
{
|
||||
PRInt32 n = GetArrayIndexFromId(cx, id);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (n >= 0) {
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> s(do_QueryWrappedNative(wrapper));
|
||||
|
||||
|
@ -7415,12 +7446,15 @@ nsHTMLSelectElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
|
||||
options->Item(n, getter_AddRefs(node));
|
||||
|
||||
return WrapNative(cx, ::JS_GetGlobalObject(cx), node,
|
||||
NS_GET_IID(nsIDOMNode), vp);
|
||||
rv = WrapNative(cx, ::JS_GetGlobalObject(cx), node,
|
||||
NS_GET_IID(nsIDOMNode), vp);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -7473,7 +7507,8 @@ nsHTMLSelectElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
nsCOMPtr<nsIDOMNSHTMLOptionCollection> oc(do_QueryInterface(options));
|
||||
NS_ENSURE_TRUE(oc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
return SetOption(cx, vp, n, oc);
|
||||
nsresult rv = SetOption(cx, vp, n, oc);
|
||||
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
|
||||
return nsElementSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
|
||||
|
@ -7692,21 +7727,23 @@ nsHTMLExternalObjSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
const jschar *id_chars = nsnull;
|
||||
size_t id_length = 0;
|
||||
|
||||
JSBool found;
|
||||
JSBool found = PR_FALSE;
|
||||
|
||||
if (JSVAL_IS_STRING(id)) {
|
||||
JSString *id_str = JSVAL_TO_STRING(id);
|
||||
if (!ObjectIsNativeWrapper(cx, obj)) {
|
||||
if (JSVAL_IS_STRING(id)) {
|
||||
JSString *id_str = JSVAL_TO_STRING(id);
|
||||
|
||||
id_chars = ::JS_GetStringChars(id_str);
|
||||
id_length = ::JS_GetStringLength(id_str);
|
||||
id_chars = ::JS_GetStringChars(id_str);
|
||||
id_length = ::JS_GetStringLength(id_str);
|
||||
|
||||
*_retval = ::JS_HasUCProperty(cx, pi_obj, id_chars, id_length, &found);
|
||||
} else {
|
||||
*_retval = JS_HasElement(cx, pi_obj, JSVAL_TO_INT(id), &found);
|
||||
}
|
||||
*_retval = ::JS_HasUCProperty(cx, pi_obj, id_chars, id_length, &found);
|
||||
} else {
|
||||
*_retval = JS_HasElement(cx, pi_obj, JSVAL_TO_INT(id), &found);
|
||||
}
|
||||
|
||||
if (!*_retval) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
if (!*_retval) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
|
@ -7716,7 +7753,7 @@ nsHTMLExternalObjSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
*_retval = ::JS_GetElement(cx, pi_obj, JSVAL_TO_INT(id), vp);
|
||||
}
|
||||
|
||||
return *_retval ? NS_OK : NS_ERROR_FAILURE;
|
||||
return *_retval ? NS_SUCCESS_I_DID_SOMETHING : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return nsElementSH::GetProperty(wrapper, cx, obj, id, vp, _retval);
|
||||
|
@ -7732,21 +7769,23 @@ nsHTMLExternalObjSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
const jschar *id_chars = nsnull;
|
||||
size_t id_length = 0;
|
||||
|
||||
JSBool found;
|
||||
JSBool found = PR_FALSE;
|
||||
|
||||
if (JSVAL_IS_STRING(id)) {
|
||||
JSString *id_str = JSVAL_TO_STRING(id);
|
||||
if (!ObjectIsNativeWrapper(cx, obj)) {
|
||||
if (JSVAL_IS_STRING(id)) {
|
||||
JSString *id_str = JSVAL_TO_STRING(id);
|
||||
|
||||
id_chars = ::JS_GetStringChars(id_str);
|
||||
id_length = ::JS_GetStringLength(id_str);
|
||||
id_chars = ::JS_GetStringChars(id_str);
|
||||
id_length = ::JS_GetStringLength(id_str);
|
||||
|
||||
*_retval = ::JS_HasUCProperty(cx, pi_obj, id_chars, id_length, &found);
|
||||
} else {
|
||||
*_retval = JS_HasElement(cx, pi_obj, JSVAL_TO_INT(id), &found);
|
||||
}
|
||||
*_retval = ::JS_HasUCProperty(cx, pi_obj, id_chars, id_length, &found);
|
||||
} else {
|
||||
*_retval = JS_HasElement(cx, pi_obj, JSVAL_TO_INT(id), &found);
|
||||
}
|
||||
|
||||
if (!*_retval) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
if (!*_retval) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
|
@ -7756,7 +7795,7 @@ nsHTMLExternalObjSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
*_retval = ::JS_SetElement(cx, pi_obj, JSVAL_TO_INT(id), vp);
|
||||
}
|
||||
|
||||
return *_retval ? NS_OK : NS_ERROR_FAILURE;
|
||||
return *_retval ? NS_SUCCESS_I_DID_SOMETHING : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return nsElementSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
|
||||
|
@ -8050,7 +8089,11 @@ nsHTMLOptionsCollectionSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
nsCOMPtr<nsIDOMNSHTMLOptionCollection> oc(do_QueryWrappedNative(wrapper));
|
||||
NS_ENSURE_TRUE(oc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
return nsHTMLSelectElementSH::SetOption(cx, vp, n, oc);
|
||||
nsresult rv = nsHTMLSelectElementSH::SetOption(cx, vp, n, oc);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -8280,7 +8323,7 @@ nsStringArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
|
||||
return NS_OK;
|
||||
return NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -135,6 +135,29 @@ public:
|
|||
|
||||
static JSClass sDOMJSClass;
|
||||
|
||||
/**
|
||||
* Get our JSClass pointer for the XPCNativeWrapper class
|
||||
*/
|
||||
static const JSClass* GetXPCNativeWrapperClass() {
|
||||
return sXPCNativeWrapperClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set our JSClass pointer for the XPCNativeWrapper class
|
||||
*/
|
||||
static void SetXPCNativeWrapperClass(JSClass* aClass) {
|
||||
NS_ASSERTION(!sXPCNativeWrapperClass,
|
||||
"Double set of sXPCNativeWrapperClass");
|
||||
sXPCNativeWrapperClass = aClass;
|
||||
}
|
||||
|
||||
static PRBool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
NS_PRECONDITION(sXPCNativeWrapperClass,
|
||||
"Must know what the XPCNativeWrapper class is!");
|
||||
return ::JS_GetClass(cx, obj) == sXPCNativeWrapperClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that the XPConnect wrapper should be preserved. This will only
|
||||
* preserve aWrapper if its native QIs to nsIDOMNode; otherwise it'll just
|
||||
|
@ -306,6 +329,7 @@ protected:
|
|||
static jsval sAddEventListener_id;
|
||||
|
||||
static const JSClass *sObjectClass;
|
||||
static const JSClass *sXPCNativeWrapperClass;
|
||||
|
||||
static PRBool sDoSecurityCheckInAddProperty;
|
||||
};
|
||||
|
|
|
@ -1511,6 +1511,8 @@ nsJSContext::GetNativeContext()
|
|||
return mContext;
|
||||
}
|
||||
|
||||
const JSClass* NS_DOMClassInfo_GetXPCNativeWrapperClass();
|
||||
void NS_DOMClassInfo_SetXPCNativeWrapperClass(JSClass* aClass);
|
||||
|
||||
nsresult
|
||||
nsJSContext::InitContext(nsIScriptGlobalObject *aGlobalObject)
|
||||
|
@ -1571,6 +1573,13 @@ nsJSContext::InitContext(nsIScriptGlobalObject *aGlobalObject)
|
|||
flags,
|
||||
getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now check whether we need to grab a pointer to the
|
||||
// XPCNativeWrapper class
|
||||
if (!NS_DOMClassInfo_GetXPCNativeWrapperClass()) {
|
||||
rv = FindXPCNativeWrapperClass(holder);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
} else {
|
||||
// If there's already a global object in mContext we're called
|
||||
// after ::JS_ClearScope() was called. We'll have to tell XPConnect
|
||||
|
@ -1645,6 +1654,51 @@ nsJSContext::InitializeLiveConnectClasses()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSContext::FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder)
|
||||
{
|
||||
NS_ASSERTION(!NS_DOMClassInfo_GetXPCNativeWrapperClass(),
|
||||
"Why was this called?");
|
||||
|
||||
JSObject *globalObj;
|
||||
aHolder->GetJSObject(&globalObj);
|
||||
NS_ASSERTION(globalObj, "Must have global by now!");
|
||||
|
||||
const char* arg = "arg";
|
||||
NS_NAMED_LITERAL_STRING(body, "return new XPCNativeWrapper(arg);");
|
||||
|
||||
// Can't use CompileFunction() here because our principal isn't
|
||||
// inited yet and a null principal makes it fail.
|
||||
JSFunction *fun =
|
||||
::JS_CompileUCFunction(mContext,
|
||||
globalObj,
|
||||
"_XPCNativeWrapperCtor",
|
||||
1, &arg,
|
||||
(jschar*)body.get(),
|
||||
body.Length(),
|
||||
"javascript:return new XPCNativeWrapper(arg);",
|
||||
1 // lineno
|
||||
);
|
||||
NS_ENSURE_TRUE(fun, NS_ERROR_FAILURE);
|
||||
|
||||
jsval globalVal = OBJECT_TO_JSVAL(globalObj);
|
||||
jsval wrapper;
|
||||
|
||||
JSBool ok = ::JS_CallFunction(mContext, globalObj, fun,
|
||||
1, &globalVal, &wrapper);
|
||||
if (!ok) {
|
||||
// No need to notify about pending exceptions here; we don't
|
||||
// expect any other than out of memory, really.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(JSVAL_IS_OBJECT(wrapper), "This should be an object!");
|
||||
|
||||
NS_DOMClassInfo_SetXPCNativeWrapperClass(
|
||||
::JS_GetClass(mContext, JSVAL_TO_OBJECT(wrapper)));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static JSPropertySpec OptionsProperties[] = {
|
||||
{"strict", JSOPTION_STRICT, JSPROP_ENUMERATE | JSPROP_PERMANENT},
|
||||
{"werror", JSOPTION_WERROR, JSPROP_ENUMERATE | JSPROP_PERMANENT},
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "nsIXPCScriptNotify.h"
|
||||
#include "nsITimer.h"
|
||||
#include "prtime.h"
|
||||
|
||||
class nsIXPConnectJSObjectHolder;
|
||||
|
||||
class nsJSContext : public nsIScriptContext,
|
||||
public nsIXPCScriptNotify,
|
||||
|
@ -138,6 +138,8 @@ protected:
|
|||
nsresult InitClasses();
|
||||
nsresult InitializeExternalClasses();
|
||||
nsresult InitializeLiveConnectClasses();
|
||||
// aHolder should be holding our global object
|
||||
nsresult FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder);
|
||||
|
||||
void FireGCTimer();
|
||||
|
||||
|
|
|
@ -137,6 +137,7 @@ nsSOAPPropertyBag::GetProperty(nsIXPConnectWrappedNative * wrapper,
|
|||
JSContext * cx, JSObject * obj,
|
||||
jsval id, jsval * vp, PRBool * _retval)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (JSVAL_IS_STRING(id)) {
|
||||
JSString *str = JSVAL_TO_STRING(id);
|
||||
const PRUnichar *name = NS_REINTERPRET_CAST(const PRUnichar *,
|
||||
|
@ -144,13 +145,14 @@ nsSOAPPropertyBag::GetProperty(nsIXPConnectWrappedNative * wrapper,
|
|||
nsCOMPtr<nsIVariant> value;
|
||||
mProperties.Get(nsDependentString(name), getter_AddRefs(value));
|
||||
if (!value)
|
||||
return NS_OK;
|
||||
return rv;
|
||||
rv = NS_SUCCESS_I_DID_SOMETHING;
|
||||
void *mark;
|
||||
jsval *argv = JS_PushArguments(cx, &mark, "%iv", value.get());
|
||||
*vp = *argv;
|
||||
JS_PopArguments(cx, mark);
|
||||
}
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
PLDHashOperator PR_CALLBACK
|
||||
|
|
|
@ -41,7 +41,19 @@
|
|||
#include "nsISupports.idl"
|
||||
#include "nsIXPConnect.idl"
|
||||
|
||||
[uuid(fa2c3b80-0e9d-11d5-9092-0010a4e73d9a)]
|
||||
%{ C++
|
||||
#define NS_SUCCESS_I_DID_SOMETHING \
|
||||
(NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,1))
|
||||
%}
|
||||
|
||||
/**
|
||||
* Note: This is not really an XPCOM interface. For example, callers must
|
||||
* guarantee that they set the *_retval of the various methods that return a
|
||||
* boolean to PR_TRUE before making the call. Implementations may skip writing
|
||||
* to *_retval unless they want to return PR_FALSE.
|
||||
*/
|
||||
|
||||
[uuid(3a592a93-bf40-4ca1-9025-ef05dc2b0cd9)]
|
||||
interface nsIXPCScriptable : nsISupports
|
||||
{
|
||||
/* bitflags used for 'flags' (only 32 bits available!) */
|
||||
|
@ -100,10 +112,14 @@ interface nsIXPCScriptable : nsISupports
|
|||
in JSContextPtr cx, in JSObjectPtr obj, in JSVal id,
|
||||
in JSValPtr vp);
|
||||
|
||||
// The returnCode should be set to NS_SUCCESS_I_DID_SOMETHING if
|
||||
// this method does something.
|
||||
PRBool getProperty(in nsIXPConnectWrappedNative wrapper,
|
||||
in JSContextPtr cx, in JSObjectPtr obj, in JSVal id,
|
||||
in JSValPtr vp);
|
||||
|
||||
// The returnCode should be set to NS_SUCCESS_I_DID_SOMETHING if
|
||||
// this method does something.
|
||||
PRBool setProperty(in nsIXPConnectWrappedNative wrapper,
|
||||
in JSContextPtr cx, in JSObjectPtr obj, in JSVal id,
|
||||
in JSValPtr vp);
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
|
||||
#include "xpcprivate.h"
|
||||
#include "XPCNativeWrapper.h"
|
||||
#include "jsdbgapi.h"
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
XPC_NW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
XPC_NW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
@ -83,6 +87,13 @@ XPC_NW_Mark(JSContext *cx, JSObject *obj, void *arg);
|
|||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
XPC_NW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
|
||||
static JSBool
|
||||
RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval);
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
// JS class for XPCNativeWrapper (and this doubles as the constructor
|
||||
// for XPCNativeWrapper for the moment too...)
|
||||
|
||||
|
@ -93,7 +104,7 @@ JSExtendedClass XPCNativeWrapper::sXPC_NW_JSClass = {
|
|||
// Our one reserved slot holds a jsint of flag bits
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) |
|
||||
JSCLASS_IS_EXTENDED,
|
||||
JS_PropertyStub, XPC_NW_DelProperty,
|
||||
XPC_NW_AddProperty, XPC_NW_DelProperty,
|
||||
XPC_NW_GetProperty, XPC_NW_SetProperty,
|
||||
XPC_NW_Enumerate, (JSResolveOp)XPC_NW_NewResolve,
|
||||
XPC_NW_Convert, XPC_NW_Finalize,
|
||||
|
@ -108,9 +119,16 @@ JSExtendedClass XPCNativeWrapper::sXPC_NW_JSClass = {
|
|||
|
||||
#define FLAG_DEEP 0x1
|
||||
#define FLAG_EXPLICIT 0x2
|
||||
// FLAG_RESOLVING is used to tag an XPCNativeWrapper when while it's calling
|
||||
// the newResolve hook on the XPCWrappedNative's scriptable info.
|
||||
#define FLAG_RESOLVING 0x4
|
||||
|
||||
#define HAS_FLAGS(_val, _flags) \
|
||||
((JSVAL_TO_INT(_val) & (_flags)) != 0)
|
||||
((PRUint32(JSVAL_TO_INT(_val)) & (_flags)) != 0)
|
||||
|
||||
#define NATIVE_HAS_FLAG(_wn, _flag) \
|
||||
((_wn)->GetScriptableInfo() && \
|
||||
(_wn)->GetScriptableInfo()->GetFlags()._flag())
|
||||
|
||||
// If one of our class hooks is ever called from a non-system script, bypass
|
||||
// the hook by calling the same hook on our wrapped native, with obj reset to
|
||||
|
@ -197,6 +215,45 @@ GetStringByIndex(JSContext *cx, uintN index)
|
|||
return ID_TO_VALUE(rt->GetStringID(index));
|
||||
}
|
||||
|
||||
static JSBool
|
||||
WrapFunction(JSContext* cx, JSObject* funobj, jsval *rval)
|
||||
{
|
||||
// If funobj is already a wrapped function, just return it.
|
||||
if (JS_GetFunctionNative(cx,
|
||||
JS_ValueToFunction(cx, OBJECT_TO_JSVAL(funobj))) ==
|
||||
XPC_NW_FunctionWrapper) {
|
||||
*rval = OBJECT_TO_JSVAL(funobj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Create a new function that'll call our given function. This new
|
||||
// function's parent will be the original function and that's how we
|
||||
// get the right thing to call when this function is called.
|
||||
JSFunction *funWrapper =
|
||||
::JS_NewFunction(cx, XPC_NW_FunctionWrapper, 0, 0, funobj,
|
||||
"XPCNativeWrapper function wrapper");
|
||||
if (!funWrapper) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*rval = OBJECT_TO_JSVAL(::JS_GetFunctionObject(funWrapper));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
XPC_NW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
jsval flags;
|
||||
::JS_GetReservedSlot(cx, obj, 0, &flags);
|
||||
if (!HAS_FLAGS(flags, FLAG_RESOLVING)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Note: no need to protect *vp from GC here, since it's already in the slot
|
||||
// on |obj|.
|
||||
return RewrapIfDeepWrapper(cx, obj, *vp, vp);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
XPC_NW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
|
@ -223,12 +280,29 @@ RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval)
|
|||
{
|
||||
NS_ASSERTION(XPCNativeWrapper::IsNativeWrapper(cx, obj),
|
||||
"Unexpected object");
|
||||
|
||||
JSBool primitive = JSVAL_IS_PRIMITIVE(v);
|
||||
JSObject* nativeObj = primitive ? nsnull : JSVAL_TO_OBJECT(v);
|
||||
|
||||
// We always want to wrap function objects, no matter whether we're deep.
|
||||
if (!primitive && JS_ObjectIsFunction(cx, nativeObj)) {
|
||||
return WrapFunction(cx, nativeObj, rval);
|
||||
}
|
||||
|
||||
jsval flags;
|
||||
::JS_GetReservedSlot(cx, obj, 0, &flags);
|
||||
|
||||
// Re-wrap non-primitive values if this is a deep wrapper, i.e.
|
||||
// if (HAS_FLAGS(flags, FLAG_DEEP).
|
||||
if (HAS_FLAGS(flags, FLAG_DEEP) && !JSVAL_IS_PRIMITIVE(v)) {
|
||||
if (HAS_FLAGS(flags, FLAG_DEEP) && !primitive) {
|
||||
|
||||
XPCWrappedNative* wrappedNative =
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, nativeObj);
|
||||
if (!wrappedNative) {
|
||||
// Not something we can protect... just make it JSVAL_NULL
|
||||
*rval = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (HAS_FLAGS(flags, FLAG_EXPLICIT)) {
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
|
@ -248,13 +322,6 @@ RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval)
|
|||
// Just using GetNewOrUsed on the return value of
|
||||
// GetWrappedNativeOfJSObject will give the right thing -- the unique deep
|
||||
// implicit wrapper associated with wrappedNative.
|
||||
JSObject *nativeObj = JSVAL_TO_OBJECT(v);
|
||||
XPCWrappedNative* wrappedNative =
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, nativeObj);
|
||||
if (!wrappedNative) {
|
||||
return ThrowException(NS_ERROR_INVALID_ARG, cx);
|
||||
}
|
||||
|
||||
JSObject* wrapperObj = XPCNativeWrapper::GetNewOrUsed(cx, wrappedNative);
|
||||
if (!wrapperObj) {
|
||||
return JS_FALSE;
|
||||
|
@ -355,24 +422,54 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
jsval methodName;
|
||||
// This will do verification and the method lookup for us.
|
||||
XPCCallContext ccx(JS_CALLER, cx, nativeObj, nsnull, id);
|
||||
|
||||
if (JSVAL_IS_STRING(id)) {
|
||||
methodName = id;
|
||||
} else if (JSVAL_IS_INT(id)) {
|
||||
// Map wrapper[n] to wrapper.item(n) for get. For set, throw an
|
||||
// error as we don't support that.
|
||||
if (aIsSet ? NATIVE_HAS_FLAG(wrappedNative, WantSetProperty) :
|
||||
NATIVE_HAS_FLAG(wrappedNative, WantGetProperty)) {
|
||||
|
||||
jsval v = *vp;
|
||||
// Note that some sets return random DOM objects (setting
|
||||
// document.location, say), so we want to rewrap for sets too if v != *vp.
|
||||
JSBool retval = JS_TRUE;
|
||||
nsresult rv;
|
||||
if (aIsSet) {
|
||||
return ThrowException(NS_ERROR_UNEXPECTED, cx);
|
||||
rv = wrappedNative->GetScriptableCallback()->
|
||||
SetProperty(wrappedNative, cx, obj, id, &v, &retval);
|
||||
} else {
|
||||
rv = wrappedNative->GetScriptableCallback()->
|
||||
GetProperty(wrappedNative, cx, obj, id, &v, &retval);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return ThrowException(rv, cx);
|
||||
}
|
||||
if (!retval) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
methodName = GetStringByIndex(cx, XPCJSRuntime::IDX_ITEM);
|
||||
} else {
|
||||
return ThrowException(NS_ERROR_INVALID_ARG, cx);
|
||||
}
|
||||
if (rv == NS_SUCCESS_I_DID_SOMETHING) {
|
||||
// Make sure v doesn't get collected while we're re-wrapping it.
|
||||
AUTO_MARK_JSVAL(ccx, v);
|
||||
|
||||
// This will do verification and the method lookup for us.
|
||||
XPCCallContext ccx(JS_CALLER, cx, nativeObj, nsnull, methodName);
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
JSString* strId = ::JS_ValueToString(cx, id);
|
||||
if (strId) {
|
||||
NS_ConvertUTF16toUTF8 propName((PRUnichar*)::JS_GetStringChars(strId),
|
||||
::JS_GetStringLength(strId));
|
||||
printf("%s via scriptable hooks for '%s'\n",
|
||||
aIsSet ? "Set" : "Got", propName.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
return RewrapIfDeepWrapper(cx, obj, v, vp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_STRING(id)) {
|
||||
// Not going to be found here
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Verify that our jsobject really is a wrapped native.
|
||||
XPCWrappedNative* wrapper = ccx.GetWrapper();
|
||||
|
@ -385,45 +482,6 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||
// interface :)
|
||||
XPCNativeInterface* iface = ccx.GetInterface();
|
||||
if (!iface) {
|
||||
// No interface, no IDL property. Check whet her we're getting an indexed
|
||||
// property such as frames[0]. Handle that as a special case here, now
|
||||
// that we know there's no XPConnected .item() method.
|
||||
|
||||
if (methodName != id) {
|
||||
jsid index_id;
|
||||
JSObject *pobj;
|
||||
JSProperty *prop;
|
||||
|
||||
// Look up the property for the id being indexed in nativeObj.
|
||||
if (!::JS_ValueToId(cx, id, &index_id) ||
|
||||
!OBJ_LOOKUP_PROPERTY(cx, nativeObj, index_id, &pobj, &prop)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (prop) {
|
||||
JSBool safe = JS_FALSE;
|
||||
|
||||
if (OBJ_IS_NATIVE(pobj)) {
|
||||
// At this point we know we have a native JS object (one that
|
||||
// has a JSScope for its map, containing refs to the runtime's
|
||||
// JSScopeProperty tree nodes. Compare that property's getter
|
||||
// to the class default getter to decide whether this element
|
||||
// is safe to get -- i.e., it is not overridden, possibly by a
|
||||
// user-defined getter.
|
||||
|
||||
JSScopeProperty *sprop = (JSScopeProperty *) prop;
|
||||
JSClass *nativeObjClass = JS_GET_CLASS(cx, nativeObj);
|
||||
|
||||
safe = (sprop->getter == nativeObjClass->getProperty);
|
||||
}
|
||||
|
||||
OBJ_DROP_PROPERTY(cx, pobj, prop);
|
||||
|
||||
if (safe) {
|
||||
return ::JS_GetElement(cx, nativeObj, JSVAL_TO_INT(id), vp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -456,11 +514,9 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (!member->IsAttribute() && methodName == id) {
|
||||
if (!member->IsAttribute()) {
|
||||
// Getting the value of a method. Just return and let the value
|
||||
// from XPC_NW_NewResolve() be used. Note that if methodName != id
|
||||
// then we fully expect that member is not an attribute and we need
|
||||
// to keep going and handle this case below.
|
||||
// from XPC_NW_NewResolve() be used.
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -479,24 +535,7 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||
jsval *argv = nsnull;
|
||||
uintN argc = 0;
|
||||
|
||||
if (methodName != id) {
|
||||
// wrapper[n] to wrapper.item(n) mapping case.
|
||||
|
||||
if (member->IsAttribute()) {
|
||||
// Uh oh, somehow wrapper.item is an attribute, not a function.
|
||||
// Throw an error since we don't know how to deal with this case.
|
||||
|
||||
return ThrowException(NS_ERROR_UNEXPECTED, cx);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
printf("Mapping wrapper[%d] to wrapper.item(%d)\n", JSVAL_TO_INT(id),
|
||||
JSVAL_TO_INT(id));
|
||||
#endif
|
||||
|
||||
argv = &id;
|
||||
argc = 1;
|
||||
} else if (aIsSet) {
|
||||
if (aIsSet) {
|
||||
if (member->IsReadOnlyAttribute()) {
|
||||
// Trying to set a property for which there is no setter!
|
||||
return ThrowException(NS_ERROR_NOT_AVAILABLE, cx);
|
||||
|
@ -516,8 +555,7 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||
#endif
|
||||
}
|
||||
|
||||
// Call the getter (or method if an id access was mapped to
|
||||
// .item(n)).
|
||||
// Call the getter
|
||||
jsval v;
|
||||
if (!::JS_CallFunctionValue(cx, wrapper->GetFlatJSObject(),
|
||||
OBJECT_TO_JSVAL(funobj), argc, argv, &v)) {
|
||||
|
@ -575,8 +613,10 @@ JS_STATIC_DLL_CALLBACK(JSBool)
|
|||
XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSObject **objp)
|
||||
{
|
||||
// No need to preserve on sets of wrappedJSObject or toString, since
|
||||
// callers couldn't get at those values anyway.
|
||||
// No need to preserve on sets of wrappedJSObject or toString, since callers
|
||||
// couldn't get at those values anyway. Also, we always deal with
|
||||
// wrappedJSObject and toString before looking at our scriptable hooks, so no
|
||||
// need to mess with our flags yet.
|
||||
if (id == GetStringByIndex(cx, XPCJSRuntime::IDX_WRAPPED_JSOBJECT) ||
|
||||
id == GetStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
|
||||
return JS_TRUE;
|
||||
|
@ -632,35 +672,74 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_INT(id)) {
|
||||
// An index is being resolved. Define the property and deal with
|
||||
// the value in the get/set property hooks.
|
||||
|
||||
// Note that we don't have to worry about preserving here, since
|
||||
// numeric ids can't be assigned to.
|
||||
|
||||
if (!::JS_DefineElement(cx, obj, JSVAL_TO_INT(id), JSVAL_VOID, nsnull,
|
||||
nsnull, 0)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*objp = obj;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_STRING(id)) {
|
||||
// A non-int and non-string id is being resolved. Won't be found
|
||||
// here, return early.
|
||||
|
||||
return MaybePreserveWrapper(cx, wrappedNative, flags);
|
||||
}
|
||||
|
||||
JSObject *nativeObj = wrappedNative->GetFlatJSObject();
|
||||
|
||||
// This will do verification and the method lookup for us.
|
||||
XPCCallContext ccx(JS_CALLER, cx, nativeObj, nsnull, id);
|
||||
|
||||
// For "constructor" we don't want to call into the resolve hooks on the
|
||||
// wrapped native, since that would give the wrong constructor.
|
||||
if (NATIVE_HAS_FLAG(wrappedNative, WantNewResolve) &&
|
||||
id != GetStringByIndex(cx, XPCJSRuntime::IDX_CONSTRUCTOR)) {
|
||||
|
||||
// Mark ourselves as resolving so our AddProperty hook can do the
|
||||
// right thing here.
|
||||
jsval oldFlags;
|
||||
::JS_GetReservedSlot(cx, obj, 0, &oldFlags);
|
||||
if (!::JS_SetReservedSlot(cx, obj, 0,
|
||||
INT_TO_JSVAL(JSVAL_TO_INT(oldFlags) |
|
||||
FLAG_RESOLVING))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
XPCWrappedNative* oldResolvingWrapper;
|
||||
JSBool allowPropMods =
|
||||
NATIVE_HAS_FLAG(wrappedNative, AllowPropModsDuringResolve);
|
||||
if (allowPropMods) {
|
||||
oldResolvingWrapper = ccx.SetResolvingWrapper(wrappedNative);
|
||||
}
|
||||
|
||||
JSBool retval = JS_TRUE;
|
||||
JSObject* newObj = nsnull;
|
||||
nsresult rv = wrappedNative->GetScriptableInfo()->
|
||||
GetCallback()->NewResolve(wrappedNative, cx, obj, id, flags,
|
||||
&newObj, &retval);
|
||||
|
||||
if (allowPropMods) {
|
||||
ccx.SetResolvingWrapper(oldResolvingWrapper);
|
||||
}
|
||||
|
||||
if (!::JS_SetReservedSlot(cx, obj, 0, oldFlags)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return ThrowException(rv, cx);
|
||||
}
|
||||
|
||||
if (newObj) {
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
JSString* strId = ::JS_ValueToString(cx, id);
|
||||
if (strId) {
|
||||
NS_ConvertUTF16toUTF8 propName((PRUnichar*)::JS_GetStringChars(strId),
|
||||
::JS_GetStringLength(strId));
|
||||
printf("Resolved via scriptable hooks for '%s'\n", propName.get());
|
||||
}
|
||||
#endif
|
||||
// Note that we don't need to preserve the wrapper here, since this is
|
||||
// not an "expando" property if the scriptable newResolve hook found it.
|
||||
*objp = newObj;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_STRING(id)) {
|
||||
// A non-string id is being resolved. Won't be found here, return
|
||||
// early.
|
||||
|
||||
return MaybePreserveWrapper(cx, wrappedNative, flags);
|
||||
}
|
||||
|
||||
// Verify that our jsobject really is a wrapped native.
|
||||
XPCWrappedNative* wrapper = ccx.GetWrapper();
|
||||
if (wrapper != wrappedNative || !wrapper->IsValid()) {
|
||||
|
@ -727,18 +806,9 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
::JS_GetStringBytes(JSVAL_TO_STRING(id)));
|
||||
#endif
|
||||
|
||||
// Create a new function that'll call the method we got from the
|
||||
// member. This new function's parent will be the method to call from
|
||||
// the function, and that's how we get the method when this function
|
||||
// is called.
|
||||
JSFunction *funWrapper =
|
||||
::JS_NewFunction(cx, XPC_NW_FunctionWrapper, 0, 0, funobj,
|
||||
"Components.lookupMethod function wrapper");
|
||||
if (!funWrapper) {
|
||||
if (!WrapFunction(cx, funobj, &v)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
v = OBJECT_TO_JSVAL(::JS_GetFunctionObject(funWrapper));
|
||||
}
|
||||
|
||||
if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
|
||||
|
|
|
@ -2438,13 +2438,15 @@ nsXPCComponents::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
doResult = JS_TRUE;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if(doResult)
|
||||
{
|
||||
if(!JS_NewNumberValue(cx, (jsdouble) res, vp))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* PRBool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
|
||||
|
@ -2468,7 +2470,7 @@ nsXPCComponents::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
|||
{
|
||||
xpcc->SetPendingResult(rv);
|
||||
xpcc->SetLastResult(rv);
|
||||
return NS_OK;
|
||||
return NS_SUCCESS_I_DID_SOMETHING;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче