diff --git a/accessible/public/nsIAccessible.idl b/accessible/public/nsIAccessible.idl index 7ebc94f44ea1..757abf21fb17 100644 --- a/accessible/public/nsIAccessible.idl +++ b/accessible/public/nsIAccessible.idl @@ -103,7 +103,14 @@ interface nsIAccessible : nsISupports readonly attribute long indexInParent; /** - * Accessible name -- the main text equivalent for this node + * Accessible name -- the main text equivalent for this node. The name is + * specified by ARIA or by native markup. Example of ARIA markup is + * aria-labelledby attribute placed on element of this accessible. Example + * of native markup is HTML label linked with HTML element of this accessible. + * + * Value can be string or null. A null value indicates that AT may attempt to + * compute the name. Any string value, including the empty string, should be + * considered author-intentional, and respected. */ attribute AString name; diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index a9c1c74d9192..4947275b67d9 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -308,7 +308,7 @@ nsAccessible::GetName(nsAString& aName) if (content->GetAttr(kNameSpaceID_None, tooltipAttr, name)) { name.CompressWhitespace(); aName = name; - } else { + } else if (rv != NS_OK_EMPTY_NAME) { aName.SetIsVoid(PR_TRUE); } diff --git a/accessible/src/base/nsAccessible.h b/accessible/src/base/nsAccessible.h index 12fa93e89ac4..07247cb587b1 100644 --- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -66,9 +66,14 @@ class nsIDOMNode; class nsIAtom; class nsIView; +// see nsAccessible::GetAttrValue #define NS_OK_NO_ARIA_VALUE \ NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x21) +// see nsAccessible::GetNameInternal +#define NS_OK_EMPTY_NAME \ +NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x23) + // Saves a data member -- if child count equals this value we haven't // cached children or child count yet enum { eChildCountUninitialized = -1 }; @@ -135,7 +140,13 @@ public: /** * Returns the accessible name provided by native markup. It doesn't take - * into account ARIA stuffs used to specify the name. + * into account ARIA markup used to specify the name. + * + * @param aName [out] the accessible name + * + * @return NS_OK_EMPTY_NAME points empty name was specified by native markup + * explicitly (see nsIAccessible::name attribute for + * details) */ virtual nsresult GetNameInternal(nsAString& aName); diff --git a/accessible/src/html/nsHTMLImageAccessible.cpp b/accessible/src/html/nsHTMLImageAccessible.cpp index 36e4942d7de8..980428bd4566 100644 --- a/accessible/src/html/nsHTMLImageAccessible.cpp +++ b/accessible/src/html/nsHTMLImageAccessible.cpp @@ -127,10 +127,6 @@ nsHTMLImageAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState) nsresult nsHTMLImageAccessible::GetNameInternal(nsAString& aName) { - // No alt attribute means AT can repair if there is no accessible name - // alt="" with no title or aria-labelledby means image is presentational and - // AT should leave accessible name empty - nsCOMPtr content(do_QueryInterface(mDOMNode)); PRBool hasAltAttrib = content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::alt, aName); @@ -140,10 +136,12 @@ nsHTMLImageAccessible::GetNameInternal(nsAString& aName) nsresult rv = nsAccessible::GetNameInternal(aName); NS_ENSURE_SUCCESS(rv, rv); - if (aName.IsVoid() && hasAltAttrib) { - // No accessible name but empty alt attribute is present. This means a name - // was provided by author and AT repair of the name isn't allowed. - aName.Truncate(); + if (aName.IsEmpty() && hasAltAttrib) { + // No accessible name but empty 'alt' attribute is present. If further name + // computation algorithm doesn't provide non empty name then it means + // an empty 'alt' attribute was used to indicate a decorative image (see + // nsIAccessible::name attribute for details). + return NS_OK_EMPTY_NAME; } return NS_OK; diff --git a/accessible/tests/mochitest/test_nsIAccessibleImage.html b/accessible/tests/mochitest/test_nsIAccessibleImage.html index 826fba8d12a3..d7ade2158351 100644 --- a/accessible/tests/mochitest/test_nsIAccessibleImage.html +++ b/accessible/tests/mochitest/test_nsIAccessibleImage.html @@ -147,10 +147,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429659 testThis("linkedImageWithTitle", "Link to MoFo", "moz.png", 93, 42); // Test simple image with empty alt attribute -// testThis("nonLinkedImageEmptyAlt", "", "moz.png", 89, 38); + testThis("nonLinkedImageEmptyAlt", "", "moz.png", 89, 38); // Test linked image with empty alt attribute -// testThis("linkedImageEmptyAlt", "", "moz.png", 93, 42); + testThis("linkedImageEmptyAlt", "", "moz.png", 93, 42); // Test simple image with empty alt attribute and title testThis("nonLinkedImageEmptyAltAndTitle", "MozillaFoundation", "moz.png", 89, 38); diff --git a/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js b/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js index 48fca7b9ee42..6e6604b8d250 100644 --- a/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js +++ b/browser/components/privatebrowsing/test/unit/head_privatebrowsing.js @@ -98,6 +98,7 @@ function cleanUp() "places.sqlite", "cookies.sqlite", "signons.sqlite", + "permissions.sqlite" ]; for (let i = 0; i < files.length; i++) { diff --git a/config/rules.mk b/config/rules.mk index 054cfe19e8a9..8c8a9a1befb2 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -2175,6 +2175,9 @@ echo-variable-%: echo-tiers: @echo $(TIERS) +echo-tier-dirs: + @$(foreach tier,$(TIERS),echo '$(tier):'; echo ' dirs: $(tier_$(tier)_dirs)'; echo ' staticdirs: $(tier_$(tier)_staticdirs)'; ) + echo-dirs: @echo $(DIRS) diff --git a/dom/src/base/nsDOMClassInfo.cpp b/dom/src/base/nsDOMClassInfo.cpp index 572543ce8757..9fe800c87b36 100644 --- a/dom/src/base/nsDOMClassInfo.cpp +++ b/dom/src/base/nsDOMClassInfo.cpp @@ -1635,12 +1635,12 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx) // static nsresult nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native, - const nsIID& aIID, jsval *vp, + const nsIID* aIID, jsval *vp, nsIXPConnectJSObjectHolder **aHolder) { - *aHolder = nsnull; - if (!native) { + NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!"); + *vp = JSVAL_NULL; return NS_OK; @@ -1648,19 +1648,8 @@ nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native, NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED); - nsCOMPtr holder; - nsresult rv = sXPConnect->WrapNative(cx, ::JS_GetGlobalForObject(cx, scope), - native, aIID, getter_AddRefs(holder)); - NS_ENSURE_SUCCESS(rv, rv); - - JSObject* obj = nsnull; - rv = holder->GetJSObject(&obj); - NS_ENSURE_SUCCESS(rv, rv); - - *vp = OBJECT_TO_JSVAL(obj); - holder.swap(*aHolder); - - return rv; + return sXPConnect->WrapNativeToJSVal(cx, ::JS_GetGlobalForObject(cx, scope), + native, aIID, vp, aHolder); } // static @@ -1691,7 +1680,7 @@ nsDOMClassInfo::ThrowJSException(JSContext *cx, nsresult aResult) jsval jv; nsCOMPtr holder; rv = WrapNative(cx, ::JS_GetGlobalObject(cx), exception, - NS_GET_IID(nsIException), &jv, getter_AddRefs(holder)); + &NS_GET_IID(nsIException), &jv, getter_AddRefs(holder)); if (NS_FAILED(rv) || JSVAL_IS_NULL(jv)) { break; } @@ -4495,8 +4484,7 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj, if (result) { jsval v; nsCOMPtr holder; - nsresult rv = WrapNative(cx, obj, result, NS_GET_IID(nsISupports), &v, - getter_AddRefs(holder)); + nsresult rv = WrapNative(cx, obj, result, &v, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, JS_FALSE); if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(jsstr), @@ -4690,7 +4678,7 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, nsCOMPtr holder; rv = WrapNative(cx, frameWin->GetGlobalJSObject(), frame, - NS_GET_IID(nsIDOMWindow), vp, + &NS_GET_IID(nsIDOMWindow), vp, getter_AddRefs(holder)); } @@ -4807,7 +4795,7 @@ nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && location, rv); nsCOMPtr holder; - rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp, + rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), vp, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -5062,8 +5050,8 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner, } nsCOMPtr holder; - rv = nsDOMGenericSH::WrapNative(cx, obj, native, NS_GET_IID(nsISupports), - rval, getter_AddRefs(holder)); + rv = nsDOMGenericSH::WrapNative(cx, obj, native, rval, + getter_AddRefs(holder)); return rv; } @@ -5529,7 +5517,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, nsCOMPtr holder; jsval v; - rv = WrapNative(cx, obj, constructor, NS_GET_IID(nsIDOMDOMConstructor), &v, + rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor), &v, getter_AddRefs(holder)); sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty; @@ -5591,7 +5579,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, nsCOMPtr holder; jsval v; - rv = WrapNative(cx, obj, constructor, NS_GET_IID(nsIDOMDOMConstructor), &v, + rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor), &v, getter_AddRefs(holder)); sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty; @@ -5806,7 +5794,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, jsval val; nsCOMPtr holder; - rv = WrapNative(cx, obj, constructor, NS_GET_IID(nsIDOMDOMConstructor), + rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor), &val, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -5854,8 +5842,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, scope = aWin->GetGlobalJSObject(); } - rv = WrapNative(cx, scope, native, NS_GET_IID(nsISupports), &prop_val, - getter_AddRefs(holder)); + rv = WrapNative(cx, scope, native, &prop_val, getter_AddRefs(holder)); } NS_ENSURE_SUCCESS(rv, rv); @@ -6146,7 +6133,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, jsval v; nsCOMPtr holder; rv = WrapNative(cx, wrapperObj, child_win, - NS_GET_IID(nsIDOMWindowInternal), &v, + &NS_GET_IID(nsIDOMWindowInternal), &v, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -6267,7 +6254,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, jsval v; nsCOMPtr holder; - rv = WrapNative(cx, scope, location, NS_GET_IID(nsIDOMLocation), &v, + rv = WrapNative(cx, scope, location, &NS_GET_IID(nsIDOMLocation), &v, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -6324,7 +6311,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, jsval v; nsCOMPtr holder; - rv = WrapNative(cx, obj, navigator, NS_GET_IID(nsIDOMNavigator), &v, + rv = WrapNative(cx, obj, navigator, &NS_GET_IID(nsIDOMNavigator), &v, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -6348,7 +6335,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, jsval v; nsCOMPtr holder; - rv = WrapNative(cx, obj, document, NS_GET_IID(nsIDOMDocument), &v, + rv = WrapNative(cx, obj, document, &NS_GET_IID(nsIDOMDocument), &v, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -6953,8 +6940,7 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, jsval v; nsCOMPtr holder; - nsresult rv = WrapNative(cx, globalObj, native_parent, - NS_GET_IID(nsISupports), &v, + nsresult rv = WrapNative(cx, globalObj, native_parent, &v, getter_AddRefs(holder)); *parentObj = JSVAL_TO_OBJECT(v); @@ -7021,7 +7007,7 @@ nsNodeSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, } nsCOMPtr holder; - nsresult rv = WrapNative(cx, obj, uri, NS_GET_IID(nsIURI), vp, + nsresult rv = WrapNative(cx, obj, uri, &NS_GET_IID(nsIURI), vp, getter_AddRefs(holder)); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } @@ -7032,7 +7018,7 @@ nsNodeSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, nsCOMPtr holder; nsresult rv = WrapNative(cx, obj, node->NodePrincipal(), - NS_GET_IID(nsIPrincipal), vp, + &NS_GET_IID(nsIPrincipal), vp, getter_AddRefs(holder)); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } @@ -7730,9 +7716,7 @@ nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_ENSURE_SUCCESS(rv, rv); if (array_item) { - nsCOMPtr holder; - rv = WrapNative(cx, obj, array_item, NS_GET_IID(nsISupports), vp, - getter_AddRefs(holder)); + rv = WrapNative(cx, obj, array_item, vp); NS_ENSURE_SUCCESS(rv, rv); rv = NS_SUCCESS_I_DID_SOMETHING; @@ -7766,8 +7750,7 @@ nsNodeListSH::PreCreate(nsISupports *nativeObj, JSContext *cx, jsval v; nsCOMPtr holder; - nsresult rv = WrapNative(cx, globalObj, native_parent, - NS_GET_IID(nsISupports), &v, + nsresult rv = WrapNative(cx, globalObj, native_parent, &v, getter_AddRefs(holder)); *parentObj = JSVAL_TO_OBJECT(v); @@ -7867,9 +7850,7 @@ nsNamedArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_ENSURE_SUCCESS(rv, rv); if (item) { - nsCOMPtr holder; - rv = WrapNative(cx, obj, item, NS_GET_IID(nsISupports), vp, - getter_AddRefs(holder)); + rv = WrapNative(cx, obj, item, vp); NS_ENSURE_SUCCESS(rv, rv); rv = NS_SUCCESS_I_DID_SOMETHING; @@ -7981,8 +7962,7 @@ nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx, jsval v; nsCOMPtr holder; - nsresult rv = WrapNative(cx, globalObj, native_parent, - NS_GET_IID(nsISupports), &v, + nsresult rv = WrapNative(cx, globalObj, native_parent, &v, getter_AddRefs(holder)); *parentObj = JSVAL_TO_OBJECT(v); @@ -8098,7 +8078,7 @@ nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, jsval v; nsCOMPtr holder; - rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), &v, + rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), &v, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -8142,7 +8122,7 @@ nsDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE); nsCOMPtr holder; - nsresult rv = WrapNative(cx, obj, uri, NS_GET_IID(nsIURI), vp, + nsresult rv = WrapNative(cx, obj, uri, &NS_GET_IID(nsIURI), vp, getter_AddRefs(holder)); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; @@ -8174,7 +8154,7 @@ nsDocumentSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr holder; - rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp, + rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), vp, getter_AddRefs(holder)); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } @@ -8232,7 +8212,7 @@ nsDocumentSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, jsval winVal; nsCOMPtr holder; - rv = WrapNative(cx, obj, win, NS_GET_IID(nsIDOMWindow), &winVal, + rv = WrapNative(cx, obj, win, &NS_GET_IID(nsIDOMWindow), &winVal, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -8351,7 +8331,7 @@ nsHTMLDocumentSH::DocumentOpen(JSContext *cx, JSObject *obj, uintN argc, } nsCOMPtr holder; - rv = WrapNative(cx, obj, retval, NS_GET_IID(nsIDOMDocument), rval, + rv = WrapNative(cx, obj, retval, &NS_GET_IID(nsIDOMDocument), rval, getter_AddRefs(holder)); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to wrap native!"); @@ -8426,8 +8406,7 @@ nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx, JSObject *obj, rv |= domdoc->GetElementsByTagName(NS_LITERAL_STRING("*"), nodeList); nsCOMPtr holder; - rv |= nsDOMClassInfo::WrapNative(cx, obj, *nodeList, - NS_GET_IID(nsISupports), &collection, + rv |= nsDOMClassInfo::WrapNative(cx, obj, *nodeList, &collection, getter_AddRefs(holder)); // ... and store it in our reserved slot. @@ -8514,9 +8493,7 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSObject *obj, } if (result) { - nsCOMPtr holder; - rv = nsDOMClassInfo::WrapNative(cx, obj, result, NS_GET_IID(nsISupports), - vp, getter_AddRefs(holder)); + rv = WrapNative(cx, obj, result, vp); if (NS_FAILED(rv)) { nsDOMClassInfo::ThrowJSException(cx, rv); @@ -8788,8 +8765,7 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj, if (tags) { jsval v; nsCOMPtr holder; - nsresult rv = nsDOMClassInfo::WrapNative(cx, obj, tags, - NS_GET_IID(nsISupports), &v, + nsresult rv = nsDOMClassInfo::WrapNative(cx, obj, tags, &v, getter_AddRefs(holder)); if (NS_FAILED(rv)) { nsDOMClassInfo::ThrowJSException(cx, rv); @@ -8948,9 +8924,7 @@ nsHTMLDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper, NS_ENSURE_SUCCESS(rv, rv); if (result) { - nsCOMPtr holder; - rv = WrapNative(cx, obj, result, NS_GET_IID(nsISupports), vp, - getter_AddRefs(holder)); + rv = WrapNative(cx, obj, result, vp); if (NS_SUCCEEDED(rv)) { rv = NS_SUCCESS_I_DID_SOMETHING; } @@ -9090,9 +9064,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper, if (result) { // Wrap result, result can be either an element or a list of // elements - nsCOMPtr holder; - nsresult rv = WrapNative(cx, obj, result, NS_GET_IID(nsISupports), vp, - getter_AddRefs(holder)); + nsresult rv = WrapNative(cx, obj, result, vp); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } } @@ -9104,9 +9076,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper, form->GetElementAt(n, getter_AddRefs(control)); if (control) { - nsCOMPtr holder; - nsresult rv = WrapNative(cx, obj, control, NS_GET_IID(nsISupports), vp, - getter_AddRefs(holder)); + nsresult rv = WrapNative(cx, obj, control, vp); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } } @@ -9213,9 +9183,7 @@ nsHTMLSelectElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper, options->Item(n, getter_AddRefs(node)); - nsCOMPtr holder; - rv = WrapNative(cx, obj, node, NS_GET_IID(nsIDOMNode), vp, - getter_AddRefs(holder)); + rv = WrapNative(cx, obj, node, &NS_GET_IID(nsIDOMNode), vp); if (NS_SUCCEEDED(rv)) { rv = NS_SUCCESS_I_DID_SOMETHING; } diff --git a/dom/src/base/nsDOMClassInfo.h b/dom/src/base/nsDOMClassInfo.h index 65212b71d6bc..cbeec2af03f4 100644 --- a/dom/src/base/nsDOMClassInfo.h +++ b/dom/src/base/nsDOMClassInfo.h @@ -130,11 +130,22 @@ public: } static nsresult WrapNative(JSContext *cx, JSObject *scope, - nsISupports *native, const nsIID& aIID, + nsISupports *native, const nsIID* aIID, jsval *vp, - // aHolder keeps the jsval alive while - // there's a ref to it - nsIXPConnectJSObjectHolder** aHolder); + // If non-null aHolder will keep the jsval alive + // while there's a ref to it + nsIXPConnectJSObjectHolder** aHolder = nsnull); + + // Same as the WrapNative above, but use this one if aIID is nsISupports' IID. + static nsresult WrapNative(JSContext *cx, JSObject *scope, + nsISupports *native, jsval *vp, + // If non-null aHolder will keep the jsval alive + // while there's a ref to it + nsIXPConnectJSObjectHolder** aHolder = nsnull) + { + return WrapNative(cx, scope, native, nsnull, vp, aHolder); + } + static nsresult ThrowJSException(JSContext *cx, nsresult aResult); static nsresult InitDOMJSClass(JSContext *cx, JSObject *obj); diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index 054cfe19e8a9..8c8a9a1befb2 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -2175,6 +2175,9 @@ echo-variable-%: echo-tiers: @echo $(TIERS) +echo-tier-dirs: + @$(foreach tier,$(TIERS),echo '$(tier):'; echo ' dirs: $(tier_$(tier)_dirs)'; echo ' staticdirs: $(tier_$(tier)_staticdirs)'; ) + echo-dirs: @echo $(DIRS) diff --git a/js/src/xpconnect/idl/nsIXPConnect.idl b/js/src/xpconnect/idl/nsIXPConnect.idl index 3726a8a8ad69..146e0f8b5284 100644 --- a/js/src/xpconnect/idl/nsIXPConnect.idl +++ b/js/src/xpconnect/idl/nsIXPConnect.idl @@ -405,7 +405,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(d4c6bc06-2a4f-4315-90ec-d12904aca046)] +[uuid(f8bf005e-3700-411c-ba0c-e018075f22a4)] interface nsIXPConnect : nsISupports { %{ C++ @@ -468,6 +468,23 @@ interface nsIXPConnect : nsISupports in nsISupports aCOMObj, in nsIIDRef aIID); + /** + * Same as wrapNative, but also returns the JSObject in aVal. C++ callers + * can pass in null for the aHolder argument, but in that case they must + * ensure that aVal is rooted. + * aIID may be null, it means the same as passing in + * &NS_GET_IID(nsISupports) but when passing in null certain shortcuts + * can be taken because we know without comparing IIDs that the caller is + * asking for an nsISupports wrapper. + */ + void + wrapNativeToJSVal(in JSContextPtr aJSContext, + in JSObjectPtr aScope, + in nsISupports aCOMObj, + in nsIIDPtr aIID, + out JSVal aVal, + out nsIXPConnectJSObjectHolder aHolder); + /** * wrapJS will yield a new or previously existing xpcom interface pointer * to represent the JSObject passed in. diff --git a/js/src/xpconnect/src/Makefile.in b/js/src/xpconnect/src/Makefile.in index 6e3e308a14a3..dba9458d8f6a 100644 --- a/js/src/xpconnect/src/Makefile.in +++ b/js/src/xpconnect/src/Makefile.in @@ -176,6 +176,8 @@ endif nsXPConnect.$(OBJ_SUFFIX): dom_quickstubs.h +xpcjsruntime.$(OBJ_SUFFIX): dom_quickstubs.h + dom_quickstubs.h dom_quickstubs.cpp: $(srcdir)/dom_quickstubs.qsconf \ $(srcdir)/qsgen.py \ $(topsrcdir)/xpcom/idl-parser/header.py \ diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 8279a050a70a..bcfe3130c65b 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -1099,6 +1099,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, !JS_SetPrototype(aJSContext, tempGlobal, nsnull)) return UnexpectedFailure(NS_ERROR_FAILURE); + jsval v; nsCOMPtr holder; { // Scope for our auto-marker; it just needs to keep tempGlobal alive @@ -1109,16 +1110,18 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, return UnexpectedFailure(NS_ERROR_FAILURE); nsresult rv; - if(!XPCConvert::NativeInterface2JSObject(ccx, getter_AddRefs(holder), - aCOMObj, &aIID, tempGlobal, - PR_FALSE, OBJ_IS_GLOBAL, &rv)) + if(!XPCConvert::NativeInterface2JSObject(ccx, &v, + getter_AddRefs(holder), + aCOMObj, &aIID, nsnull, + tempGlobal, PR_FALSE, + OBJ_IS_GLOBAL, &rv)) return UnexpectedFailure(rv); NS_ASSERTION(NS_SUCCEEDED(rv) && holder, "Didn't wrap properly"); } - JSObject* globalJSObj; - if(NS_FAILED(holder->GetJSObject(&globalJSObj)) || !globalJSObj) + JSObject* globalJSObj = JSVAL_TO_OBJECT(v); + if(!globalJSObj) return UnexpectedFailure(NS_ERROR_FAILURE); if(aFlags & nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT) @@ -1180,29 +1183,42 @@ nsXPConnect::WrapNative(JSContext * aJSContext, JSObject * aScope, nsISupports *aCOMObj, const nsIID & aIID, - nsIXPConnectJSObjectHolder **_retval) + nsIXPConnectJSObjectHolder **aHolder) +{ + NS_ASSERTION(aHolder, "bad param"); + + jsval v; + return WrapNativeToJSVal(aJSContext, aScope, aCOMObj, &aIID, &v, aHolder); +} + +/* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out JSVal aVal, out nsIXPConnectJSObjectHolder aHolder); */ +NS_IMETHODIMP +nsXPConnect::WrapNativeToJSVal(JSContext * aJSContext, + JSObject * aScope, + nsISupports *aCOMObj, + const nsIID * aIID, + jsval *aVal, + nsIXPConnectJSObjectHolder **aHolder) { NS_ASSERTION(aJSContext, "bad param"); NS_ASSERTION(aScope, "bad param"); NS_ASSERTION(aCOMObj, "bad param"); - NS_ASSERTION(_retval, "bad param"); - *_retval = nsnull; + if(aHolder) + *aHolder = nsnull; XPCCallContext ccx(NATIVE_CALLER, aJSContext); if(!ccx.IsValid()) return UnexpectedFailure(NS_ERROR_FAILURE); nsresult rv; - if(!XPCConvert::NativeInterface2JSObject(ccx, _retval, aCOMObj, &aIID, - aScope, PR_FALSE, + if(!XPCConvert::NativeInterface2JSObject(ccx, aVal, aHolder, aCOMObj, aIID, + nsnull, aScope, PR_FALSE, OBJ_IS_NOT_GLOBAL, &rv)) return rv; #ifdef DEBUG - JSObject* returnObj; - (*_retval)->GetJSObject(&returnObj); - NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(returnObj), + NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(JSVAL_TO_OBJECT(*aVal)), "Shouldn't be returning a native wrapper here"); #endif diff --git a/js/src/xpconnect/src/qsgen.py b/js/src/xpconnect/src/qsgen.py index 7c4a5775433f..0cf5c273eaea 100644 --- a/js/src/xpconnect/src/qsgen.py +++ b/js/src/xpconnect/src/qsgen.py @@ -330,10 +330,16 @@ def writeHeaderFile(filename, name): try: f.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n" "#ifndef " + headerMacro + "\n" - "#define " + headerMacro + "\n" + "#define " + headerMacro + "\n\n" "JSBool " + name + "_DefineQuickStubs(" "JSContext *cx, JSObject *proto, uintN flags, " - "PRUint32 count, const nsID **iids);\n" + "PRUint32 count, const nsID **iids);\n\n" + "void " + name + "_MarkInterfaces();\n\n" + "void " + name + "_ClearInterfaces();\n\n" + "inline void " + name + "_InitInterfaces()\n" + "{\n" + " " + name + "_ClearInterfaces();\n" + "}\n\n" "#endif\n") finally: f.close() @@ -598,8 +604,10 @@ def writeResultConv(f, type, paramNum, jsvalPtr, jsvalRef): % (paramNum, jsvalPtr)) return else: + f.write(" AutoMarkingNativeInterfacePtr resultiface(ccx, " + "%s_Interface(ccx));\n" % type.name) f.write(" return xpc_qsXPCOMObjectToJsval(ccx, result, " - "NS_GET_IID(%s), %s);\n" % (type.name, jsvalPtr)) + "resultiface, %s);\n" % jsvalPtr) return warn("Unable to convert result of type %s" % type.name) @@ -819,6 +827,32 @@ def hashIID(iid): uuid_re = re.compile(r'^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})$') +def writeResultXPCInterfacesArray(f, conf, resulttypes): + f.write("// === XPCNativeInterface cache \n\n") + count = len(resulttypes) + if count > 0: + f.write("static XPCNativeInterface* interfaces[%d];\n\n" % count) + f.write("void %s_MarkInterfaces()\n" + "{\n" % conf.name) + if count > 0: + f.write(" for (PRUint32 i = 0; i < %d; ++i)\n" + " if (interfaces[i])\n" + " interfaces[i]->Mark();\n" % count) + f.write("}\n") + f.write("void %s_ClearInterfaces()\n" + "{\n" % conf.name) + if count > 0: + f.write(" memset(interfaces, 0, %d * " + "sizeof(XPCNativeInterface*));\n" % count) + f.write("}\n\n") + i = 0 + for type in resulttypes: + f.write("XPC_QS_DEFINE_XPCNATIVEINTERFACE_GETTER(%s, interfaces[%d])\n" + % (type, i)) + i += 1 + if count > 0: + f.write("\n\n") + def writeDefiner(f, conf, interfaces): f.write("// === Definer\n\n") @@ -937,31 +971,41 @@ def writeStubFile(filename, headerFilename, conf, interfaces): def includeType(type): type = unaliasType(type) if type.kind in ('builtin', 'native'): - return + return None file = conf.irregularFilenames.get(type.name, type.name) + '.h' if file not in filesIncluded: f.write('#include "%s"\n' % file) filesIncluded.add(file) + return type def writeIncludesForMember(member): assert member.kind in ('attribute', 'method') - includeType(member.realtype) + resulttype = includeType(member.realtype) if member.kind == 'method': for p in member.params: includeType(p.realtype) + return resulttype def writeIncludesForInterface(iface): assert iface.kind == 'interface' + resulttypes = [] for member in iface.stubMembers: - writeIncludesForMember(member) + resulttype = writeIncludesForMember(member) + if resulttype is not None and not isVariantType(resulttype): + resulttypes.append(resulttype.name) + includeType(iface) + return resulttypes + try: f.write(stubTopTemplate % os.path.basename(headerFilename)) N = 256 + resulttypes = [] for iface in interfaces: - writeIncludesForInterface(iface) + resulttypes.extend(writeIncludesForInterface(iface)) f.write("\n\n") + writeResultXPCInterfacesArray(f, conf, sets.ImmutableSet(resulttypes)) for iface in interfaces: writeStubsForInterface(f, iface) writeDefiner(f, conf, interfaces) diff --git a/js/src/xpconnect/src/xpcconvert.cpp b/js/src/xpconnect/src/xpcconvert.cpp index 00a86e73493f..b304c7a13071 100644 --- a/js/src/xpconnect/src/xpcconvert.cpp +++ b/js/src/xpconnect/src/xpcconvert.cpp @@ -467,24 +467,17 @@ XPCConvert::NativeData2JS(XPCCallContext& ccx, jsval* d, const void* s, // global object will not have been collected, and // therefore this NativeInterface2JSObject will not end up // creating a new XPCNativeScriptableShared. - nsCOMPtr holder; - if(!NativeInterface2JSObject(ccx, getter_AddRefs(holder), - iface, iid, scope, PR_TRUE, + if(!NativeInterface2JSObject(ccx, d, nsnull, iface, iid, + nsnull, scope, PR_TRUE, OBJ_IS_NOT_GLOBAL, pErr)) return JS_FALSE; - if(holder) - { - JSObject* jsobj; - if(NS_FAILED(holder->GetJSObject(&jsobj))) - return JS_FALSE; #ifdef DEBUG - if(!STOBJ_GET_PARENT(jsobj)) - NS_ASSERTION(STOBJ_GET_CLASS(jsobj)->flags & JSCLASS_IS_GLOBAL, - "Why did we recreate this wrapper?"); + JSObject* jsobj = JSVAL_TO_OBJECT(*d); + if(jsobj && !STOBJ_GET_PARENT(jsobj)) + NS_ASSERTION(STOBJ_GET_CLASS(jsobj)->flags & JSCLASS_IS_GLOBAL, + "Why did we recreate this wrapper?"); #endif - *d = OBJECT_TO_JSVAL(jsobj); - } } break; } @@ -1033,15 +1026,20 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s, return JS_TRUE; } -JSBool -CreateHolderIfNeeded(XPCCallContext& ccx, JSObject* obj, +inline JSBool +CreateHolderIfNeeded(XPCCallContext& ccx, JSObject* obj, jsval* d, nsIXPConnectJSObjectHolder** dest) { - XPCJSObjectHolder* objHolder = XPCJSObjectHolder::newHolder(ccx, obj); - if(!objHolder) - return JS_FALSE; - - NS_ADDREF(*dest = objHolder); + if(dest) + { + XPCJSObjectHolder* objHolder = XPCJSObjectHolder::newHolder(ccx, obj); + if(!objHolder) + return JS_FALSE; + + NS_ADDREF(*dest = objHolder); + } + + *d = OBJECT_TO_JSVAL(obj); return JS_TRUE; } @@ -1050,19 +1048,21 @@ CreateHolderIfNeeded(XPCCallContext& ccx, JSObject* obj, // static JSBool XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx, + jsval* d, nsIXPConnectJSObjectHolder** dest, nsISupports* src, const nsID* iid, + XPCNativeInterface* Interface, JSObject* scope, PRBool allowNativeWrapper, PRBool isGlobal, nsresult* pErr) { - NS_ASSERTION(dest, "bad param"); - NS_ASSERTION(iid, "bad param"); NS_ASSERTION(scope, "bad param"); - *dest = nsnull; + *d = JSVAL_NULL; + if(dest) + *dest = nsnull; if(!src) return JS_TRUE; if(pErr) @@ -1086,11 +1086,23 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx, // verify that this wrapper is for the right interface nsCOMPtr wrapper; - if(NS_FAILED(src->QueryInterface(*iid,(void**)getter_AddRefs(wrapper)))) + if(Interface) + src->QueryInterface(*Interface->GetIID(), + (void**)getter_AddRefs(wrapper)); + else if(iid) + src->QueryInterface(*iid, (void**)getter_AddRefs(wrapper)); + else + wrapper = do_QueryInterface(src); + nsCOMPtr holder = + do_QueryInterface(wrapper); + JSObject* flat; + if(!holder || !(flat = holder->GetFlatJSObject())) return JS_FALSE; - return NS_SUCCEEDED(wrapper->QueryInterface( - NS_GET_IID(nsIXPConnectJSObjectHolder), - (void**) dest)); + + *d = OBJECT_TO_JSVAL(flat); + if(dest) + holder.swap(*dest); + return JS_TRUE; } else #endif /* XPC_DO_DOUBLE_WRAP */ @@ -1100,27 +1112,39 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx, if(!xpcscope) return JS_FALSE; - AutoMarkingNativeInterfacePtr iface(ccx); - iface = XPCNativeInterface::GetNewOrUsed(ccx, iid); - if(!iface) - return JS_FALSE; + AutoMarkingNativeInterfacePtr iface(ccx, Interface); + if(!iface && iid) + { + iface = XPCNativeInterface::GetNewOrUsed(ccx, iid); + if(!iface) + return JS_FALSE; + } nsresult rv; XPCWrappedNative* wrapper; + nsRefPtr strongWrapper; nsWrapperCache* cache = nsnull; CallQueryInterface(src, &cache); if(cache && (wrapper = static_cast(cache->GetWrapper()))) { - NS_ADDREF(wrapper); - wrapper->FindTearOff(ccx, iface, JS_FALSE, &rv); - if(NS_FAILED(rv)) - NS_RELEASE(wrapper); + // If asked to return the wrapper we'll return a strong reference, + // otherwise we'll just return its JSObject in rval (which should be + // rooted in that case). + if(dest) + strongWrapper = wrapper; + if(iface) + wrapper->FindTearOff(ccx, iface, JS_FALSE, &rv); + else + rv = NS_OK; } else { rv = XPCWrappedNative::GetNewOrUsed(ccx, src, xpcscope, iface, - isGlobal, &wrapper); + isGlobal, + getter_AddRefs(strongWrapper)); + + wrapper = strongWrapper; } if(pErr) @@ -1185,6 +1209,11 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx, if(!JS_IsSystemObject(ccx, flat)) { + // From here on we might create new JSObjects, so we need to + // make sure that wrapper stays alive. + if(!strongWrapper) + strongWrapper = wrapper; + JSObject *destObj = nsnull; if(flags & JSFILENAME_PROTECTED) { @@ -1243,11 +1272,8 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx, destObj = JSVAL_TO_OBJECT(v); } - PRBool ok = destObj && - CreateHolderIfNeeded(ccx, destObj, dest); - - NS_RELEASE(wrapper); - return ok; + return destObj && + CreateHolderIfNeeded(ccx, destObj, d, dest); } } @@ -1257,14 +1283,18 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx, !JS_IsSystemObject(ccx, flat) && XPC_XOW_ClassNeedsXOW(name)) { - PRBool ok = XPC_XOW_WrapObject(ccx, scope, &v) && - CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(v), dest); + // From here on we might create new JSObjects, so we need to + // make sure that wrapper stays alive. + if(!strongWrapper) + strongWrapper = wrapper; - NS_RELEASE(wrapper); - return ok; + return XPC_XOW_WrapObject(ccx, scope, &v) && + CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(v), d, dest); } - *dest = static_cast(wrapper); + *d = v; + if(dest) + *dest = strongWrapper.forget().get(); return JS_TRUE; } } diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index 1acdcee616d8..8e438c21ca83 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -41,6 +41,7 @@ /* Per JSRuntime object */ #include "xpcprivate.h" +#include "dom_quickstubs.h" /***************************************************************************/ @@ -559,6 +560,8 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status) self->mDetachedWrappedNativeProtoMap-> Enumerate(DetachedWrappedNativeProtoMarker, nsnull); + DOM_MarkInterfaces(); + // Mark the sets used in the call contexts. There is a small // chance that a wrapper's set will change *while* a call is // happening which uses that wrapper's old interfface set. So, @@ -813,6 +816,8 @@ DetachedWrappedNativeProtoShutdownMarker(JSDHashTable *table, JSDHashEntryHdr *h void XPCJSRuntime::SystemIsBeingShutDown(JSContext* cx) { + DOM_ClearInterfaces(); + if(mDetachedWrappedNativeProtoMap) mDetachedWrappedNativeProtoMap-> Enumerate(DetachedWrappedNativeProtoShutdownMarker, cx); @@ -1001,6 +1006,8 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) sizeof(JSDHashEntryStub), 128); #endif + DOM_InitInterfaces(); + // these jsids filled in later when we have a JSContext to work with. mStrIDs[0] = 0; diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 7333c8b30f1a..0bf205e45086 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -2759,9 +2759,11 @@ public: * @param pErr [out] relevant error code, if any. */ static JSBool NativeInterface2JSObject(XPCCallContext& ccx, + jsval* d, nsIXPConnectJSObjectHolder** dest, nsISupports* src, const nsID* iid, + XPCNativeInterface* Interface, JSObject* scope, PRBool allowNativeWrapper, PRBool isGlobal, diff --git a/js/src/xpconnect/src/xpcquickstubs.cpp b/js/src/xpconnect/src/xpcquickstubs.cpp index 4537d1802eb4..67b36a78d24e 100644 --- a/js/src/xpconnect/src/xpcquickstubs.cpp +++ b/js/src/xpconnect/src/xpcquickstubs.cpp @@ -743,7 +743,7 @@ xpc_qsStringToJsval(JSContext *cx, const nsAString &str, jsval *rval) JSBool xpc_qsXPCOMObjectToJsval(XPCCallContext &ccx, nsISupports *p, - const nsIID &iid, jsval *rval) + XPCNativeInterface *iface, jsval *rval) { // From the T_INTERFACE case in XPCConvert::NativeData2JS. // This is one of the slowest things quick stubs do. @@ -751,16 +751,18 @@ xpc_qsXPCOMObjectToJsval(XPCCallContext &ccx, nsISupports *p, JSObject *scope = ccx.GetCurrentJSObject(); NS_ASSERTION(scope, "bad ccx"); + if(!iface) + return xpc_qsThrow(ccx, NS_ERROR_XPC_BAD_CONVERT_NATIVE); + // XXX The OBJ_IS_NOT_GLOBAL here is not really right. In // fact, this code is depending on the fact that the // global object will not have been collected, and // therefore this NativeInterface2JSObject will not end up // creating a new XPCNativeScriptableShared. - nsCOMPtr holder; nsresult rv; - if(!XPCConvert::NativeInterface2JSObject(ccx, getter_AddRefs(holder), - p, &iid, scope, PR_TRUE, - OBJ_IS_NOT_GLOBAL, &rv)) + if(!XPCConvert::NativeInterface2JSObject(ccx, rval, nsnull, p, nsnull, + iface, scope, PR_TRUE, + OBJ_IS_NOT_GLOBAL, &rv)) { // I can't tell if NativeInterface2JSObject throws JS exceptions // or not. This is a sloppy stab at the right semantics; the @@ -770,22 +772,13 @@ xpc_qsXPCOMObjectToJsval(XPCCallContext &ccx, nsISupports *p, return JS_FALSE; } - if(holder) - { - JSObject* jsobj; - if(NS_FAILED(holder->GetJSObject(&jsobj))) - return JS_FALSE; #ifdef DEBUG - if(!STOBJ_GET_PARENT(jsobj)) - NS_ASSERTION(STOBJ_GET_CLASS(jsobj)->flags & JSCLASS_IS_GLOBAL, - "Why did we recreate this wrapper?"); + JSObject* jsobj = JSVAL_TO_OBJECT(*rval); + if(jsobj && !STOBJ_GET_PARENT(jsobj)) + NS_ASSERTION(STOBJ_GET_CLASS(jsobj)->flags & JSCLASS_IS_GLOBAL, + "Why did we recreate this wrapper?"); #endif - *rval = OBJECT_TO_JSVAL(jsobj); - } - else - { - *rval = JSVAL_NULL; - } + return JS_TRUE; } diff --git a/js/src/xpconnect/src/xpcquickstubs.h b/js/src/xpconnect/src/xpcquickstubs.h index 99379b36dd79..0a0761f93c84 100644 --- a/js/src/xpconnect/src/xpcquickstubs.h +++ b/js/src/xpconnect/src/xpcquickstubs.h @@ -398,7 +398,7 @@ xpc_qsUnwrapArg(JSContext *cx, jsval v, T **ppArg) JSBool xpc_qsXPCOMObjectToJsval(XPCCallContext &ccx, nsISupports *p, - const nsIID &iid, + XPCNativeInterface *iface, jsval *rval); /** @@ -432,4 +432,14 @@ xpc_qsAssertContextOK(JSContext *cx); #define XPC_QS_ASSERT_CONTEXT_OK(cx) ((void) 0) #endif +#define XPC_QS_DEFINE_XPCNATIVEINTERFACE_GETTER(_iface, _iface_cache) \ +inline XPCNativeInterface* \ +_iface##_Interface(XPCCallContext& ccx) \ +{ \ + if(!(_iface_cache)) \ + (_iface_cache) = \ + XPCNativeInterface::GetNewOrUsed(ccx, &NS_GET_IID(_iface)); \ + return (_iface_cache); \ +} + #endif /* xpcquickstubs_h___ */ diff --git a/js/src/xpconnect/src/xpcwrappedjsclass.cpp b/js/src/xpconnect/src/xpcwrappedjsclass.cpp index f6a3baf2496f..c4447ebd7f8c 100644 --- a/js/src/xpconnect/src/xpcwrappedjsclass.cpp +++ b/js/src/xpconnect/src/xpcwrappedjsclass.cpp @@ -1342,23 +1342,19 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, } if(newThis) { - if(!newWrapperIID) - newWrapperIID = - const_cast - (&NS_GET_IID(nsISupports)); - nsCOMPtr holder; + jsval v; JSBool ok = XPCConvert::NativeInterface2JSObject(ccx, - getter_AddRefs(holder), newThis, - newWrapperIID, obj, PR_FALSE, PR_FALSE, + &v, nsnull, newThis, newWrapperIID, + nsnull, obj, PR_FALSE, PR_FALSE, nsnull); - if(newWrapperIID != &NS_GET_IID(nsISupports)) + if(newWrapperIID) nsMemory::Free(newWrapperIID); - if(!ok || - NS_FAILED(holder->GetJSObject(&thisObj))) + if(!ok) { goto pre_call_clean_up; } + thisObj = JSVAL_TO_OBJECT(v); } } } diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index 9509b75f2b7b..057f443c5453 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -302,7 +302,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx, // in a pointer that hasn't been QI'd to IDispatch properly this could // create multiple wrappers for the same object, creating a fair bit of // confusion. - PRBool isIDispatch = Interface->GetIID()->Equals(NSID_IDISPATCH); + PRBool isIDispatch = Interface && + Interface->GetIID()->Equals(NSID_IDISPATCH); if(isIDispatch) identity = Object; else @@ -333,7 +334,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx, if(wrapper) { - if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) + if(Interface && !wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) { NS_RELEASE(wrapper); NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure"); @@ -356,7 +357,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx, // If we are making a wrapper for the nsIClassInfo interface then // We *don't* want to have it use the prototype meant for instances // of that class. - JSBool isClassInfo = Interface->GetIID()->Equals(NS_GET_IID(nsIClassInfo)); + JSBool isClassInfo = Interface && + Interface->GetIID()->Equals(NS_GET_IID(nsIClassInfo)); nsCOMPtr info; @@ -429,7 +431,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx, if(wrapper) { - if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) + if(Interface && !wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) { NS_RELEASE(wrapper); NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure"); @@ -488,7 +490,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx, return NS_ERROR_FAILURE; } - if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) + if(Interface && !wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) { // Second reference will be released by the FlatJSObject's finializer. wrapper->Release(); @@ -636,7 +638,7 @@ XPCWrappedNative::GetUsedOnly(XPCCallContext& ccx, } nsresult rv; - if(!wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) + if(Interface && !wrapper->FindTearOff(ccx, Interface, JS_FALSE, &rv)) { NS_RELEASE(wrapper); NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure"); diff --git a/widget/src/cocoa/nsAppShell.mm b/widget/src/cocoa/nsAppShell.mm index 7c8961147743..02f9bab4422e 100644 --- a/widget/src/cocoa/nsAppShell.mm +++ b/widget/src/cocoa/nsAppShell.mm @@ -62,6 +62,7 @@ // defined in nsChildView.mm extern nsIRollupListener * gRollupListener; extern nsIWidget * gRollupWidget; +extern PRUint32 gLastModifierState; // defined in nsCocoaWindow.mm extern PRInt32 gXULModalLevel; @@ -816,6 +817,10 @@ nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread, selector:@selector(applicationWillTerminate:) name:NSApplicationWillTerminateNotification object:NSApp]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(applicationDidBecomeActive:) + name:NSApplicationDidBecomeActiveNotification + object:NSApp]; [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(beginMenuTracking:) name:@"com.apple.HIToolbox.beginMenuTrackingNotification" @@ -850,6 +855,25 @@ nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread, NS_OBJC_END_TRY_ABORT_BLOCK; } +// applicationDidBecomeActive +// +// Make sure gLastModifierState is updated when we become active (since we +// won't have received [ChildView flagsChanged:] messages while inactive). +- (void)applicationDidBecomeActive:(NSNotification*)aNotification +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + // [NSEvent modifierFlags] is valid on every kind of event, so we don't need + // to worry about getting an NSInternalInconsistencyException here. + NSEvent* currentEvent = [NSApp currentEvent]; + if (currentEvent) { + gLastModifierState = + nsCocoaUtils::GetCocoaEventModifierFlags(currentEvent) & NSDeviceIndependentModifierFlagsMask; + } + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + // beginMenuTracking // // Roll up our context menu (if any) when some other app (or the OS) opens diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index c23eb8e4125d..f6ad2d203587 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -174,8 +174,6 @@ enum { // when handling |draggingUpdated:| messages. nsIDragService* mDragService; - PRUint32 mLastModifierState; - // For use with plugins, so that we can support IME in them. We can't use // Cocoa TSM documents (those created and managed by the NSTSMInputContext // class) -- for some reason TSMProcessRawKeyEvent() doesn't work with them. diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 45253d72112a..9a4eb8af1bb4 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -136,6 +136,8 @@ static void blinkRgn(RgnHandle rgn); nsIRollupListener * gRollupListener = nsnull; nsIWidget * gRollupWidget = nsnull; +PRUint32 gLastModifierState = 0; + @interface ChildView(Private) @@ -6021,10 +6023,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; // CapsLock state and other modifier states are different: // CapsLock state does not revert when the CapsLock key goes up, as the - // modifier state does for other modifier keys on key up. Also, - // mLastModifierState is set only when this view is the first responder. We - // cannot trust mLastModifierState to accurately reflect the state of CapsLock - // since CapsLock maybe have been toggled when another window was active. + // modifier state does for other modifier keys on key up. if ([theEvent keyCode] == kCapsLockKeyCode) { // Fire key down event for caps lock. [self fireKeyEventForFlagsChanged:theEvent keyDown:YES]; @@ -6043,7 +6042,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; for (PRUint32 i = 0; i < kModifierCount; i++) { PRUint32 modifierBit = kModifierMaskTable[i]; - if ((modifiers & modifierBit) != (mLastModifierState & modifierBit)) { + if ((modifiers & modifierBit) != (gLastModifierState & modifierBit)) { BOOL isKeyDown = (modifiers & modifierBit) != 0 ? YES : NO; [self fireKeyEventForFlagsChanged:theEvent keyDown:isKeyDown]; @@ -6058,7 +6057,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; } } - mLastModifierState = modifiers; + gLastModifierState = modifiers; } // check if the hand scroll cursor needs to be set/unset