merge mozilla-central to tracemonkey

This commit is contained in:
Robert Sayre 2010-11-19 15:54:33 -08:00
Родитель 86c0a8c1ac b4e4b26fa9
Коммит cc61a33126
717 изменённых файлов: 12832 добавлений и 5343 удалений

Просмотреть файл

@ -37,10 +37,12 @@
#include "AccIterator.h" #include "AccIterator.h"
#include "nsAccessibilityService.h"
#include "nsAccessible.h" #include "nsAccessible.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// nsAccIterator // AccIterator
////////////////////////////////////////////////////////////////////////////////
AccIterator::AccIterator(nsAccessible *aAccessible, AccIterator::AccIterator(nsAccessible *aAccessible,
filters::FilterFuncPtr aFilterFunc, filters::FilterFuncPtr aFilterFunc,
@ -93,3 +95,45 @@ AccIterator::IteratorState::IteratorState(nsAccessible *aParent,
mParent(aParent), mIndex(0), mParentState(mParentState) mParent(aParent), mIndex(0), mParentState(mParentState)
{ {
} }
////////////////////////////////////////////////////////////////////////////////
// RelatedAccIterator
////////////////////////////////////////////////////////////////////////////////
RelatedAccIterator::
RelatedAccIterator(nsDocAccessible* aDocument, nsIContent* aDependentContent,
nsIAtom* aRelAttr) :
mRelAttr(aRelAttr), mProviders(nsnull), mBindingParent(nsnull), mIndex(0)
{
mBindingParent = aDependentContent->GetBindingParent();
nsIAtom* IDAttr = mBindingParent ?
nsAccessibilityAtoms::anonid : aDependentContent->GetIDAttributeName();
nsAutoString id;
if (aDependentContent->GetAttr(kNameSpaceID_None, IDAttr, id))
mProviders = aDocument->mDependentIDsHash.Get(id);
}
nsAccessible*
RelatedAccIterator::Next()
{
if (!mProviders)
return nsnull;
while (mIndex < mProviders->Length()) {
nsDocAccessible::AttrRelProvider* provider = (*mProviders)[mIndex++];
// Return related accessible for the given attribute and if the provider
// content is in the same binding in the case of XBL usage.
if (provider->mRelAttr == mRelAttr &&
(!mBindingParent ||
mBindingParent == provider->mContent->GetBindingParent())) {
nsAccessible* related = GetAccService()->GetAccessible(provider->mContent);
if (related)
return related;
}
}
return nsnull;
}

Просмотреть файл

@ -40,6 +40,7 @@
#include "filters.h" #include "filters.h"
#include "nscore.h" #include "nscore.h"
#include "nsDocAccessible.h"
/** /**
* Allows to iterate through accessible children or subtree complying with * Allows to iterate through accessible children or subtree complying with
@ -93,4 +94,41 @@ private:
IteratorState *mState; IteratorState *mState;
}; };
/**
* Allows to traverse through related accessibles that are pointing to the given
* dependent accessible by relation attribute.
*/
class RelatedAccIterator
{
public:
/**
* Constructor.
*
* @param aDocument [in] the document accessible the related
* & accessibles belong to.
* @param aDependentContent [in] the content of dependent accessible that
* relations were requested for
* @param aRelAttr [in] relation attribute that relations are
* pointed by
*/
RelatedAccIterator(nsDocAccessible* aDocument, nsIContent* aDependentContent,
nsIAtom* aRelAttr);
/**
* Return next related accessible for the given dependent accessible.
*/
nsAccessible* Next();
private:
RelatedAccIterator();
RelatedAccIterator(const RelatedAccIterator&);
RelatedAccIterator& operator = (const RelatedAccIterator&);
nsIAtom* mRelAttr;
nsDocAccessible::AttrRelProviderArray* mProviders;
nsIContent* mBindingParent;
PRUint32 mIndex;
};
#endif #endif

Просмотреть файл

@ -844,15 +844,11 @@ static PRBool HasRelatedContent(nsIContent *aContent)
return PR_FALSE; return PR_FALSE;
} }
nsIAtom *relationAttrs[] = {nsAccessibilityAtoms::aria_labelledby, // If the given ID is referred by relation attribute then create an accessible
nsAccessibilityAtoms::aria_describedby, // for it. Take care of HTML elements only for now.
nsAccessibilityAtoms::aria_owns, if (aContent->IsHTML() &&
nsAccessibilityAtoms::aria_controls, nsAccUtils::GetDocAccessibleFor(aContent)->IsDependentID(id))
nsAccessibilityAtoms::aria_flowto};
if (nsCoreUtils::FindNeighbourPointingToNode(aContent, relationAttrs,
NS_ARRAY_LENGTH(relationAttrs))) {
return PR_TRUE; return PR_TRUE;
}
nsIContent *ancestorContent = aContent; nsIContent *ancestorContent = aContent;
while ((ancestorContent = ancestorContent->GetParent()) != nsnull) { while ((ancestorContent = ancestorContent->GetParent()) != nsnull) {

Просмотреть файл

@ -2037,25 +2037,28 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType,
// Relationships are defined on the same content node that the role would be // Relationships are defined on the same content node that the role would be
// defined on. // defined on.
nsresult rv; nsresult rv = NS_OK_NO_RELATION_TARGET;
switch (aRelationType) switch (aRelationType)
{ {
case nsIAccessibleRelation::RELATION_LABEL_FOR: case nsIAccessibleRelation::RELATION_LABEL_FOR:
{ {
RelatedAccIterator iter(GetDocAccessible(), mContent,
nsAccessibilityAtoms::aria_labelledby);
nsAccessible* related = nsnull;
while ((related = iter.Next())) {
rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
NS_ENSURE_SUCCESS(rv, rv);
}
if (mContent->Tag() == nsAccessibilityAtoms::label) { if (mContent->Tag() == nsAccessibilityAtoms::label) {
nsIAtom *IDAttr = mContent->IsHTML() ? nsIAtom *IDAttr = mContent->IsHTML() ?
nsAccessibilityAtoms::_for : nsAccessibilityAtoms::control; nsAccessibilityAtoms::_for : nsAccessibilityAtoms::control;
rv = nsRelUtils:: rv = nsRelUtils::
AddTargetFromIDRefAttr(aRelationType, aRelation, mContent, IDAttr); AddTargetFromIDRefAttr(aRelationType, aRelation, mContent, IDAttr);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (rv != NS_OK_NO_RELATION_TARGET)
return NS_OK; // XXX bug 381599, avoid performance problems
} }
return rv;
return nsRelUtils::
AddTargetFromNeighbour(aRelationType, aRelation, mContent,
nsAccessibilityAtoms::aria_labelledby);
} }
case nsIAccessibleRelation::RELATION_LABELLED_BY: case nsIAccessibleRelation::RELATION_LABELLED_BY:
@ -2091,13 +2094,14 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType,
case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR: case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR:
{ {
rv = nsRelUtils:: RelatedAccIterator iter(GetDocAccessible(), mContent,
AddTargetFromNeighbour(aRelationType, aRelation, mContent,
nsAccessibilityAtoms::aria_describedby); nsAccessibilityAtoms::aria_describedby);
NS_ENSURE_SUCCESS(rv, rv);
if (rv != NS_OK_NO_RELATION_TARGET) nsAccessible* related = nsnull;
return NS_OK; // XXX bug 381599, avoid performance problems while ((related = iter.Next())) {
rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
NS_ENSURE_SUCCESS(rv, rv);
}
if (mContent->Tag() == nsAccessibilityAtoms::description && if (mContent->Tag() == nsAccessibilityAtoms::description &&
mContent->IsXUL()) { mContent->IsXUL()) {
@ -2109,18 +2113,23 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType,
nsAccessibilityAtoms::control); nsAccessibilityAtoms::control);
} }
return NS_OK; return rv;
} }
case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: case nsIAccessibleRelation::RELATION_NODE_CHILD_OF:
{ {
rv = nsRelUtils:: RelatedAccIterator iter(GetDocAccessible(), mContent,
AddTargetFromNeighbour(aRelationType, aRelation, mContent,
nsAccessibilityAtoms::aria_owns); nsAccessibilityAtoms::aria_owns);
NS_ENSURE_SUCCESS(rv, rv);
nsAccessible* related = nsnull;
while ((related = iter.Next())) {
rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
NS_ENSURE_SUCCESS(rv, rv);
}
// Got relation from aria-owns, don't calculate it from native markup.
if (rv != NS_OK_NO_RELATION_TARGET) if (rv != NS_OK_NO_RELATION_TARGET)
return NS_OK; // XXX bug 381599, avoid performance problems return NS_OK;
// This is an ARIA tree or treegrid that doesn't use owns, so we need to // This is an ARIA tree or treegrid that doesn't use owns, so we need to
// get the parent the hard way. // get the parent the hard way.
@ -2153,14 +2162,20 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType,
} }
} }
return NS_OK; return rv;
} }
case nsIAccessibleRelation::RELATION_CONTROLLED_BY: case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
{ {
return nsRelUtils:: RelatedAccIterator iter(GetDocAccessible(), mContent,
AddTargetFromNeighbour(aRelationType, aRelation, mContent,
nsAccessibilityAtoms::aria_controls); nsAccessibilityAtoms::aria_controls);
nsAccessible* related = nsnull;
while ((related = iter.Next())) {
rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
NS_ENSURE_SUCCESS(rv, rv);
}
return rv;
} }
case nsIAccessibleRelation::RELATION_CONTROLLER_FOR: case nsIAccessibleRelation::RELATION_CONTROLLER_FOR:
@ -2188,9 +2203,15 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType,
case nsIAccessibleRelation::RELATION_FLOWS_FROM: case nsIAccessibleRelation::RELATION_FLOWS_FROM:
{ {
return nsRelUtils:: RelatedAccIterator iter(GetDocAccessible(), mContent,
AddTargetFromNeighbour(aRelationType, aRelation, mContent,
nsAccessibilityAtoms::aria_flowto); nsAccessibilityAtoms::aria_flowto);
nsAccessible* related = nsnull;
while ((related = iter.Next())) {
rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
NS_ENSURE_SUCCESS(rv, rv);
}
return rv;
} }
case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON: case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON:
@ -3169,8 +3190,17 @@ nsAccessible::EnsureChildren()
// State is embedded children until text leaf accessible is appended. // State is embedded children until text leaf accessible is appended.
mChildrenFlags = eEmbeddedChildren; // Prevent reentry mChildrenFlags = eEmbeddedChildren; // Prevent reentry
// Notify the document about caching status.
nsDocAccessible* document = GetDocAccessible();
if (document)
document->NotifyOfCachingStart(this);
CacheChildren(); CacheChildren();
if (document)
document->NotifyOfCachingEnd(this);
return PR_FALSE; return PR_FALSE;
} }

Просмотреть файл

@ -51,7 +51,6 @@
#include "nsStringGlue.h" #include "nsStringGlue.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsRefPtrHashtable.h" #include "nsRefPtrHashtable.h"
#include "nsDataHashtable.h"
class AccGroupInfo; class AccGroupInfo;
class EmbeddedObjCollector; class EmbeddedObjCollector;
@ -67,8 +66,6 @@ class nsIView;
typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsAccessible> typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsAccessible>
nsAccessibleHashtable; nsAccessibleHashtable;
typedef nsDataHashtable<nsPtrHashKey<const nsINode>, nsAccessible*>
NodeToAccessibleMap;
// see nsAccessible::GetAttrValue // see nsAccessible::GetAttrValue
#define NS_OK_NO_ARIA_VALUE \ #define NS_OK_NO_ARIA_VALUE \

Просмотреть файл

@ -47,7 +47,6 @@
#include "nsIDOM3Node.h" #include "nsIDOM3Node.h"
#include "nsIDOMDocument.h" #include "nsIDOMDocument.h"
#include "nsIDOMDocumentView.h" #include "nsIDOMDocumentView.h"
#include "nsIDOMDocumentXBL.h"
#include "nsIDOMHTMLDocument.h" #include "nsIDOMHTMLDocument.h"
#include "nsIDOMHTMLElement.h" #include "nsIDOMHTMLElement.h"
#include "nsIDOMNodeList.h" #include "nsIDOMNodeList.h"
@ -805,67 +804,6 @@ nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
walkUp = walkUp->GetParent(); walkUp = walkUp->GetParent();
} }
void
nsCoreUtils::GetElementsByIDRefsAttr(nsIContent *aContent, nsIAtom *aAttr,
nsIArray **aRefElements)
{
*aRefElements = nsnull;
nsAutoString ids;
if (!aContent->GetAttr(kNameSpaceID_None, aAttr, ids))
return;
ids.CompressWhitespace(PR_TRUE, PR_TRUE);
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(aContent->GetOwnerDoc());
NS_ASSERTION(document, "The given node is not in document!");
if (!document)
return;
nsCOMPtr<nsIDOMDocumentXBL> xblDocument;
if (aContent->IsInAnonymousSubtree())
xblDocument = do_QueryInterface(document);
nsCOMPtr<nsIMutableArray> refElms = do_CreateInstance(NS_ARRAY_CONTRACTID);
while (!ids.IsEmpty()) {
nsAutoString id;
PRInt32 idLength = ids.FindChar(' ');
NS_ASSERTION(idLength != 0,
"Should not be 0 because of CompressWhitespace() call above");
if (idLength == kNotFound) {
id = ids;
ids.Truncate();
} else {
id = Substring(ids, 0, idLength);
ids.Cut(0, idLength + 1);
}
// If content is anonymous subtree then use "anonid" attribute to get
// elements, otherwise search elements in DOM by ID attribute.
nsCOMPtr<nsIDOMElement> refElement;
if (xblDocument) {
nsCOMPtr<nsIDOMElement> elm =
do_QueryInterface(aContent->GetBindingParent());
xblDocument->GetAnonymousElementByAttribute(elm,
NS_LITERAL_STRING("anonid"),
id,
getter_AddRefs(refElement));
} else {
document->GetElementById(id, getter_AddRefs(refElement));
}
if (!refElement)
continue;
refElms->AppendElement(refElement, PR_FALSE);
}
NS_ADDREF(*aRefElements = refElms);
return;
}
void void
nsCoreUtils::GetElementsHavingIDRefsAttr(nsIContent *aRootContent, nsCoreUtils::GetElementsHavingIDRefsAttr(nsIContent *aRootContent,
nsIContent *aContent, nsIContent *aContent,
@ -1165,3 +1103,78 @@ nsAccessibleDOMStringList::Contains(const nsAString& aString, PRBool *aResult)
return NS_OK; return NS_OK;
} }
////////////////////////////////////////////////////////////////////////////////
// IDRefsIterator
////////////////////////////////////////////////////////////////////////////////
IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) :
mCurrIdx(0)
{
if (!aContent->IsInDoc() ||
!aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs))
return;
if (aContent->IsInAnonymousSubtree()) {
mXBLDocument = do_QueryInterface(aContent->GetOwnerDoc());
mBindingParent = do_QueryInterface(aContent->GetBindingParent());
} else {
mDocument = aContent->GetOwnerDoc();
}
}
const nsDependentSubstring
IDRefsIterator::NextID()
{
for (; mCurrIdx < mIDs.Length(); mCurrIdx++) {
if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
break;
}
if (mCurrIdx >= mIDs.Length())
return nsDependentSubstring();
nsAString::index_type idStartIdx = mCurrIdx;
while (++mCurrIdx < mIDs.Length()) {
if (NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
break;
}
return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx);
}
nsIContent*
IDRefsIterator::NextElem()
{
while (true) {
const nsDependentSubstring id = NextID();
if (id.IsEmpty())
break;
nsIContent* refContent = GetElem(id);
if (refContent)
return refContent;
}
return nsnull;
}
nsIContent*
IDRefsIterator::GetElem(const nsDependentSubstring& aID)
{
if (mXBLDocument) {
// If content is anonymous subtree then use "anonid" attribute to get
// elements, otherwise search elements in DOM by ID attribute.
nsCOMPtr<nsIDOMElement> refElm;
mXBLDocument->GetAnonymousElementByAttribute(mBindingParent,
NS_LITERAL_STRING("anonid"),
aID,
getter_AddRefs(refElm));
nsCOMPtr<nsIContent> refContent = do_QueryInterface(refElm);
return refContent;
}
return mDocument->GetElementById(aID);
}

Просмотреть файл

@ -41,6 +41,7 @@
#include "nsAccessibilityAtoms.h" #include "nsAccessibilityAtoms.h"
#include "nsIDOMDocumentXBL.h"
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsIBoxObject.h" #include "nsIBoxObject.h"
@ -304,17 +305,6 @@ public:
static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent, static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
nsAString& aLanguage); nsAString& aLanguage);
/**
* Return the array of elements the given node is referred to by its
* IDRefs attribute.
*
* @param aContent [in] the given node
* @param aAttr [in] IDRefs attribute on the given node
* @param aRefElements [out] result array of elements
*/
static void GetElementsByIDRefsAttr(nsIContent *aContent, nsIAtom *aAttr,
nsIArray **aRefElements);
/** /**
* Return the array of elements having IDRefs that points to the given node. * Return the array of elements having IDRefs that points to the given node.
* *
@ -515,5 +505,39 @@ private:
nsTArray<nsString> mNames; nsTArray<nsString> mNames;
}; };
/**
* Used to iterate through IDs or elements pointed by IDRefs attribute. Note,
* any method used to iterate through IDs or elements moves iterator to next
* position.
*/
class IDRefsIterator
{
public:
IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr);
/**
* Return next ID.
*/
const nsDependentSubstring NextID();
/**
* Return next element.
*/
nsIContent* NextElem();
/**
* Return the element with the given ID.
*/
nsIContent* GetElem(const nsDependentSubstring& aID);
private:
nsString mIDs;
nsAString::index_type mCurrIdx;
nsIDocument* mDocument;
nsCOMPtr<nsIDOMDocumentXBL> mXBLDocument;
nsCOMPtr<nsIDOMElement> mBindingParent;
};
#endif #endif

Просмотреть файл

@ -85,6 +85,16 @@ namespace dom = mozilla::dom;
PRUint32 nsDocAccessible::gLastFocusedAccessiblesState = 0; PRUint32 nsDocAccessible::gLastFocusedAccessiblesState = 0;
static nsIAtom** kRelationAttrs[] =
{
&nsAccessibilityAtoms::aria_labelledby,
&nsAccessibilityAtoms::aria_describedby,
&nsAccessibilityAtoms::aria_owns,
&nsAccessibilityAtoms::aria_controls,
&nsAccessibilityAtoms::aria_flowto
};
static const PRUint32 kRelationAttrsLen = NS_ARRAY_LENGTH(kRelationAttrs);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Constructor/desctructor // Constructor/desctructor
@ -93,8 +103,10 @@ nsDocAccessible::
nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent, nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
nsIWeakReference *aShell) : nsIWeakReference *aShell) :
nsHyperTextAccessibleWrap(aRootContent, aShell), nsHyperTextAccessibleWrap(aRootContent, aShell),
mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE) mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE),
mCacheRoot(nsnull), mIsPostCacheProcessing(PR_FALSE)
{ {
mDependentIDsHash.Init();
// XXX aaronl should we use an algorithm for the initial cache size? // XXX aaronl should we use an algorithm for the initial cache size?
mAccessibleCache.Init(kDefaultCacheSize); mAccessibleCache.Init(kDefaultCacheSize);
mNodeToAccessibleMap.Init(kDefaultCacheSize); mNodeToAccessibleMap.Init(kDefaultCacheSize);
@ -134,6 +146,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDocAccessible, nsAccessible) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEventQueue) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEventQueue)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mChildDocuments) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mChildDocuments)
tmp->mDependentIDsHash.Clear();
tmp->mNodeToAccessibleMap.Clear(); tmp->mNodeToAccessibleMap.Clear();
ClearCache(tmp->mAccessibleCache); ClearCache(tmp->mAccessibleCache);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -155,8 +168,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDocAccessible)
// However at some point we may push <body> to implement the interfaces and // However at some point we may push <body> to implement the interfaces and
// return nsDocAccessible to inherit from nsAccessibleWrap. // return nsDocAccessible to inherit from nsAccessibleWrap.
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(mDocument)); if (mDocument && mDocument->IsXUL())
if (xulDoc)
status = nsAccessible::QueryInterface(aIID, (void**)&foundInterface); status = nsAccessible::QueryInterface(aIID, (void**)&foundInterface);
else else
status = nsHyperTextAccessible::QueryInterface(aIID, status = nsHyperTextAccessible::QueryInterface(aIID,
@ -664,6 +676,7 @@ nsDocAccessible::Shutdown()
mWeakShell = nsnull; // Avoid reentrancy mWeakShell = nsnull; // Avoid reentrancy
mDependentIDsHash.Clear();
mNodeToAccessibleMap.Clear(); mNodeToAccessibleMap.Clear();
ClearCache(mAccessibleCache); ClearCache(mAccessibleCache);
@ -929,10 +942,19 @@ nsDocAccessible::AttributeWillChange(nsIDocument *aDocument,
PRInt32 aNameSpaceID, PRInt32 aNameSpaceID,
nsIAtom* aAttribute, PRInt32 aModType) nsIAtom* aAttribute, PRInt32 aModType)
{ {
// XXX TODO: bugs 381599 467143 472142 472143 // XXX TODO: bugs 381599 (partially fixed by 573469), 467143, 472142, 472143.
// Here we will want to cache whatever state we are potentially interested in, // Here we will want to cache whatever state we are potentially interested in,
// such as the existence of aria-pressed for button (so we know if we need to // such as the existence of aria-pressed for button (so we know if we need to
// newly expose it as a toggle button) etc. // newly expose it as a toggle button) etc.
// Update dependent IDs cache.
if (aModType == nsIDOMMutationEvent::MODIFICATION ||
aModType == nsIDOMMutationEvent::REMOVAL) {
nsAccessible* accessible =
GetAccService()->GetAccessibleInWeakShell(aElement, mWeakShell);
if (accessible)
RemoveDependentIDsFor(accessible, aAttribute);
}
} }
void void
@ -943,6 +965,16 @@ nsDocAccessible::AttributeChanged(nsIDocument *aDocument,
{ {
AttributeChangedImpl(aElement, aNameSpaceID, aAttribute); AttributeChangedImpl(aElement, aNameSpaceID, aAttribute);
// Update dependent IDs cache.
if (aModType == nsIDOMMutationEvent::MODIFICATION ||
aModType == nsIDOMMutationEvent::ADDITION) {
nsAccessible* accessible =
GetAccService()->GetAccessibleInWeakShell(aElement, mWeakShell);
if (accessible)
AddDependentIDsFor(accessible, aAttribute);
}
// If it was the focused node, cache the new state // If it was the focused node, cache the new state
if (aElement == gLastFocusedNode) { if (aElement == gLastFocusedNode) {
nsAccessible *focusedAccessible = GetAccService()->GetAccessible(aElement); nsAccessible *focusedAccessible = GetAccService()->GetAccessible(aElement);
@ -1362,6 +1394,7 @@ nsDocAccessible::BindToDocument(nsAccessible* aAccessible,
} }
aAccessible->SetRoleMapEntry(aRoleMapEntry); aAccessible->SetRoleMapEntry(aRoleMapEntry);
AddDependentIDsFor(aAccessible);
return true; return true;
} }
@ -1373,6 +1406,8 @@ nsDocAccessible::UnbindFromDocument(nsAccessible* aAccessible)
mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible) mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible)
mNodeToAccessibleMap.Remove(aAccessible->GetNode()); mNodeToAccessibleMap.Remove(aAccessible->GetNode());
RemoveDependentIDsFor(aAccessible);
#ifdef DEBUG #ifdef DEBUG
NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()), NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()),
"Unbinding the unbound accessible!"); "Unbinding the unbound accessible!");
@ -1554,9 +1589,130 @@ nsDocAccessible::RecreateAccessible(nsINode* aNode)
} }
} }
void
nsDocAccessible::NotifyOfCachingStart(nsAccessible* aAccessible)
{
if (!mCacheRoot)
mCacheRoot = aAccessible;
}
void
nsDocAccessible::NotifyOfCachingEnd(nsAccessible* aAccessible)
{
if (mCacheRoot == aAccessible && !mIsPostCacheProcessing) {
// Allow invalidation list insertions while container children are recached.
mIsPostCacheProcessing = PR_TRUE;
// Invalidate children of container accessible for each element in
// invalidation list.
for (PRUint32 idx = 0; idx < mInvalidationList.Length(); idx++) {
nsIContent* content = mInvalidationList[idx];
nsAccessible* container =
GetAccService()->GetCachedContainerAccessible(content);
container->InvalidateChildren();
// Make sure we keep children updated. While we're inside of caching loop
// then we must exist it with cached children.
container->EnsureChildren();
}
mInvalidationList.Clear();
mCacheRoot = nsnull;
mIsPostCacheProcessing = PR_FALSE;
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Protected members // Protected members
void
nsDocAccessible::AddDependentIDsFor(nsAccessible* aRelProvider,
nsIAtom* aRelAttr)
{
for (PRUint32 idx = 0; idx < kRelationAttrsLen; idx++) {
nsIAtom* relAttr = *kRelationAttrs[idx];
if (aRelAttr && aRelAttr != relAttr)
continue;
IDRefsIterator iter(aRelProvider->GetContent(), relAttr);
while (true) {
const nsDependentSubstring id = iter.NextID();
if (id.IsEmpty())
break;
AttrRelProviderArray* providers = mDependentIDsHash.Get(id);
if (!providers) {
providers = new AttrRelProviderArray();
if (providers) {
if (!mDependentIDsHash.Put(id, providers)) {
delete providers;
providers = nsnull;
}
}
}
if (providers) {
AttrRelProvider* provider =
new AttrRelProvider(relAttr, aRelProvider->GetContent());
if (provider) {
providers->AppendElement(provider);
// We've got here during the children caching. If the referenced
// content is not accessible then store it to pend its container
// children invalidation (this happens immediately after the caching
// is finished).
nsIContent* dependentContent = iter.GetElem(id);
if (dependentContent && !GetCachedAccessible(dependentContent)) {
mInvalidationList.AppendElement(dependentContent);
}
}
}
}
// If the relation attribute is given then we don't have anything else to
// check.
if (aRelAttr)
break;
}
}
void
nsDocAccessible::RemoveDependentIDsFor(nsAccessible* aRelProvider,
nsIAtom* aRelAttr)
{
for (PRUint32 idx = 0; idx < kRelationAttrsLen; idx++) {
nsIAtom* relAttr = *kRelationAttrs[idx];
if (aRelAttr && aRelAttr != *kRelationAttrs[idx])
continue;
IDRefsIterator iter(aRelProvider->GetContent(), relAttr);
while (true) {
const nsDependentSubstring id = iter.NextID();
if (id.IsEmpty())
break;
AttrRelProviderArray* providers = mDependentIDsHash.Get(id);
if (providers) {
for (PRUint32 jdx = 0; jdx < providers->Length(); ) {
AttrRelProvider* provider = (*providers)[jdx];
if (provider->mRelAttr == relAttr &&
provider->mContent == aRelProvider->GetContent())
providers->RemoveElement(provider);
else
jdx++;
}
if (providers->Length() == 0)
mDependentIDsHash.Remove(id);
}
}
// If the relation attribute is given then we don't have anything else to
// check.
if (aRelAttr)
break;
}
}
void void
nsDocAccessible::FireValueChangeForTextFields(nsAccessible *aAccessible) nsDocAccessible::FireValueChangeForTextFields(nsAccessible *aAccessible)
{ {

Просмотреть файл

@ -44,6 +44,8 @@
#include "nsHyperTextAccessibleWrap.h" #include "nsHyperTextAccessibleWrap.h"
#include "nsEventShell.h" #include "nsEventShell.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIDocumentObserver.h" #include "nsIDocumentObserver.h"
#include "nsIEditor.h" #include "nsIEditor.h"
@ -210,6 +212,16 @@ public:
*/ */
nsAccessible* GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID); nsAccessible* GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID);
/**
* Return true if the given ID is referred by relation attribute.
*
* @note Different elements may share the same ID if they are hosted inside
* XBL bindings. Be careful the result of this method may be senseless
* while it's called for XUL elements (where XBL is used widely).
*/
PRBool IsDependentID(const nsAString& aID) const
{ return mDependentIDsHash.Get(aID, nsnull); }
/** /**
* Initialize the newly created accessible and put it into document caches. * Initialize the newly created accessible and put it into document caches.
* *
@ -241,6 +253,17 @@ public:
*/ */
void RecreateAccessible(nsINode* aNode); void RecreateAccessible(nsINode* aNode);
/**
* Used to notify the document that the accessible caching is started or
* finished.
*
* While children are cached we may encounter the case there's no accessible
* for referred content by related accessible. Keep the caching root and
* these related nodes to invalidate their containers after root caching.
*/
void NotifyOfCachingStart(nsAccessible* aAccessible);
void NotifyOfCachingEnd(nsAccessible* aAccessible);
protected: protected:
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame); virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
@ -267,6 +290,28 @@ protected:
mChildDocuments.RemoveElement(aChildDocument); mChildDocuments.RemoveElement(aChildDocument);
} }
/**
* Add dependent IDs pointed by accessible element by relation attribute to
* cache. If the relation attribute is missed then all relation attributes
* are checked.
*
* @param aRelProvider [in] accessible that element has relation attribute
* @param aRelAttr [in, optional] relation attribute
*/
void AddDependentIDsFor(nsAccessible* aRelProvider,
nsIAtom* aRelAttr = nsnull);
/**
* Remove dependent IDs pointed by accessible element by relation attribute
* from cache. If the relation attribute is absent then all relation
* attributes are checked.
*
* @param aRelProvider [in] accessible that element has relation attribute
* @param aRelAttr [in, optional] relation attribute
*/
void RemoveDependentIDsFor(nsAccessible* aRelProvider,
nsIAtom* aRelAttr = nsnull);
static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure); static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
/** /**
@ -299,14 +344,6 @@ protected:
CharacterDataChangeInfo* aInfo, CharacterDataChangeInfo* aInfo,
PRBool aIsInserted); PRBool aIsInserted);
/**
* Used to define should the event be fired on a delay.
*/
enum EEventFiringType {
eNormalEvent,
eDelayedEvent
};
/** /**
* Fire a value change event for the the given accessible if it is a text * Fire a value change event for the the given accessible if it is a text
* field (has a ROLE_ENTRY). * field (has a ROLE_ENTRY).
@ -347,7 +384,8 @@ protected:
* Cache of accessibles within this document accessible. * Cache of accessibles within this document accessible.
*/ */
nsAccessibleHashtable mAccessibleCache; nsAccessibleHashtable mAccessibleCache;
NodeToAccessibleMap mNodeToAccessibleMap; nsDataHashtable<nsPtrHashKey<const nsINode>, nsAccessible*>
mNodeToAccessibleMap;
nsCOMPtr<nsIDocument> mDocument; nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsITimer> mScrollWatchTimer; nsCOMPtr<nsITimer> mScrollWatchTimer;
@ -366,6 +404,43 @@ protected:
static nsIAtom *gLastFocusedFrameType; static nsIAtom *gLastFocusedFrameType;
nsTArray<nsRefPtr<nsDocAccessible> > mChildDocuments; nsTArray<nsRefPtr<nsDocAccessible> > mChildDocuments;
/**
* A storage class for pairing content with one of its relation attributes.
*/
class AttrRelProvider
{
public:
AttrRelProvider(nsIAtom* aRelAttr, nsIContent* aContent) :
mRelAttr(aRelAttr), mContent(aContent) { }
nsIAtom* mRelAttr;
nsIContent* mContent;
private:
AttrRelProvider();
AttrRelProvider(const AttrRelProvider&);
AttrRelProvider& operator =(const AttrRelProvider&);
};
/**
* The cache of IDs pointed by relation attributes.
*/
typedef nsTArray<nsAutoPtr<AttrRelProvider> > AttrRelProviderArray;
nsClassHashtable<nsStringHashKey, AttrRelProviderArray> mDependentIDsHash;
friend class RelatedAccIterator;
/**
* Used for our caching algorithm. We store the root of the tree that needs
* caching, the list of nodes that should be invalidated, and whether we are
* processing the invalidation list.
*
* @see NotifyOfCachingStart/NotifyOfCachingEnd
*/
nsAccessible* mCacheRoot;
nsTArray<nsIContent*> mInvalidationList;
PRBool mIsPostCacheProcessing;
}; };
NS_DEFINE_STATIC_IID_ACCESSOR(nsDocAccessible, NS_DEFINE_STATIC_IID_ACCESSOR(nsDocAccessible,

Просмотреть файл

@ -134,27 +134,16 @@ nsRelUtils::AddTargetFromIDRefsAttr(PRUint32 aRelationType,
nsIAccessibleRelation **aRelation, nsIAccessibleRelation **aRelation,
nsIContent *aContent, nsIAtom *aAttr) nsIContent *aContent, nsIAtom *aAttr)
{ {
nsCOMPtr<nsIArray> refElms; nsresult rv = NS_OK_NO_RELATION_TARGET;
nsCoreUtils::GetElementsByIDRefsAttr(aContent, aAttr, getter_AddRefs(refElms));
if (!refElms) nsIContent* refElm = nsnull;
return NS_OK_NO_RELATION_TARGET; IDRefsIterator iter(aContent, aAttr);
while ((refElm = iter.NextElem())) {
PRUint32 count = 0; rv = AddTargetFromContent(aRelationType, aRelation, refElm);
nsresult rv = refElms->GetLength(&count);
if (NS_FAILED(rv) || count == 0)
return NS_OK_NO_RELATION_TARGET;
nsCOMPtr<nsIContent> content;
for (PRUint32 idx = 0; idx < count; idx++) {
content = do_QueryElementAt(refElms, idx, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = AddTargetFromContent(aRelationType, aRelation, content);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
return NS_OK; return rv;
} }
nsresult nsresult

Просмотреть файл

@ -92,26 +92,14 @@ nsTextEquivUtils::GetTextEquivFromIDRefs(nsAccessible *aAccessible,
if (!content) if (!content)
return NS_OK; return NS_OK;
nsCOMPtr<nsIArray> refElms; nsIContent* refContent = nsnull;
nsCoreUtils::GetElementsByIDRefsAttr(content, aIDRefsAttr, IDRefsIterator iter(content, aIDRefsAttr);
getter_AddRefs(refElms)); while ((refContent = iter.NextElem())) {
if (!refElms)
return NS_OK;
PRUint32 count = 0;
nsresult rv = refElms->GetLength(&count);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> refContent;
for (PRUint32 idx = 0; idx < count; idx++) {
refContent = do_QueryElementAt(refElms, idx, &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (!aTextEquiv.IsEmpty()) if (!aTextEquiv.IsEmpty())
aTextEquiv += ' '; aTextEquiv += ' ';
rv = AppendTextEquivFromContent(aAccessible, refContent, &aTextEquiv); nsresult rv = AppendTextEquivFromContent(aAccessible, refContent,
&aTextEquiv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }

Просмотреть файл

@ -308,34 +308,27 @@ nsHTMLTableCellAccessible::GetHeaderCells(PRInt32 aRowOrColumnHeaderCell,
nsIArray **aHeaderCells) nsIArray **aHeaderCells)
{ {
// Get header cells from @header attribute. // Get header cells from @header attribute.
nsCOMPtr<nsIArray> headerCellElms; IDRefsIterator iter(mContent, nsAccessibilityAtoms::headers);
nsCoreUtils::GetElementsByIDRefsAttr(mContent, nsAccessibilityAtoms::headers, nsIContent* headerCellElm = iter.NextElem();
getter_AddRefs(headerCellElms)); if (headerCellElm) {
if (headerCellElms) {
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsCOMPtr<nsIMutableArray> headerCells = nsCOMPtr<nsIMutableArray> headerCells =
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
PRUint32 count = 0; do {
rv = headerCellElms->GetLength(&count); nsAccessible* headerCell =
if (NS_SUCCEEDED(rv) && count > 0) { GetAccService()->GetAccessibleInWeakShell(headerCellElm, mWeakShell);
nsCOMPtr<nsIContent> headerCellContent;
for (PRUint32 idx = 0; idx < count; idx++) {
headerCellContent = do_QueryElementAt(headerCellElms, idx, &rv);
nsAccessible *headerCell =
GetAccService()->GetAccessibleInWeakShell(headerCellContent, mWeakShell);
if (headerCell && if (headerCell &&
(aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells && (aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells &&
headerCell->Role() == nsIAccessibleRole::ROLE_ROWHEADER || headerCell->Role() == nsIAccessibleRole::ROLE_ROWHEADER ||
aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells && aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells &&
headerCell->Role() == nsIAccessibleRole::ROLE_COLUMNHEADER)) headerCell->Role() == nsIAccessibleRole::ROLE_COLUMNHEADER)) {
headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell), headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell),
PR_FALSE); PR_FALSE);
} }
} } while ((headerCellElm = iter.NextElem()));
NS_ADDREF(*aHeaderCells = headerCells); NS_ADDREF(*aHeaderCells = headerCells);
return NS_OK; return NS_OK;

Просмотреть файл

@ -50,6 +50,7 @@ _TEST_FILES =\
test_general.xul \ test_general.xul \
test_tabbrowser.xul \ test_tabbrowser.xul \
test_tree.xul \ test_tree.xul \
test_update.html \
$(NULL) $(NULL)
libs:: $(_TEST_FILES) libs:: $(_TEST_FILES)

Просмотреть файл

@ -65,6 +65,9 @@
testRelation(iframeDocAcc, RELATION_NODE_CHILD_OF, iframeAcc); testRelation(iframeDocAcc, RELATION_NODE_CHILD_OF, iframeAcc);
// aria-controls // aria-controls
getAccessible("tab");
todo(false,
"Getting an accessible tab, otherwise relations for tabpanel aren't cached. Bug 606924 will fix that.");
testRelation("tabpanel", RELATION_CONTROLLED_BY, "tab"); testRelation("tabpanel", RELATION_CONTROLLED_BY, "tab");
testRelation("tab", RELATION_CONTROLLER_FOR, "tabpanel"); testRelation("tab", RELATION_CONTROLLER_FOR, "tabpanel");

Просмотреть файл

@ -66,6 +66,9 @@
testRelation(iframeDocAcc, RELATION_NODE_CHILD_OF, iframeAcc); testRelation(iframeDocAcc, RELATION_NODE_CHILD_OF, iframeAcc);
// aria-controls // aria-controls
getAccessible("tab");
todo(false,
"Getting an accessible tab, otherwise relations for tabpanel aren't cached. Bug 606924 will fix that.");
testRelation("tabpanel", RELATION_CONTROLLED_BY, "tab"); testRelation("tabpanel", RELATION_CONTROLLED_BY, "tab");
testRelation("tab", RELATION_CONTROLLER_FOR, "tabpanel"); testRelation("tab", RELATION_CONTROLLER_FOR, "tabpanel");

Просмотреть файл

@ -0,0 +1,162 @@
<html>
<head>
<title>Test updating of accessible relations</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../relations.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
function testRelated(aRelAttr, aHostRelation, aDependentRelation)
{
// no attribute
testRelation("dependent1", aDependentRelation, null);
testRelation("dependent2", aDependentRelation, null);
if (aHostRelation)
testRelation("host", aHostRelation, null);
// set attribute
getNode("host").setAttribute(aRelAttr, "dependent1");
testRelation("dependent1", aDependentRelation, "host");
testRelation("dependent2", aDependentRelation, null);
if (aHostRelation)
testRelation("host", aHostRelation, "dependent1");
// change attribute
getNode("host").setAttribute(aRelAttr, "dependent2");
testRelation("dependent1", aDependentRelation, null);
testRelation("dependent2", aDependentRelation, "host");
if (aHostRelation)
testRelation("host", aHostRelation, "dependent2");
// remove attribute
getNode("host").removeAttribute(aRelAttr);
testRelation("dependent1", aDependentRelation, null);
testRelation("dependent2", aDependentRelation, null);
if (aHostRelation)
testRelation("host", aHostRelation, null);
}
function insertRelated(aHostRelAttr, aDependentID, aInsertHostFirst,
aHostRelation, aDependentRelation)
{
this.eventSeq = [
new invokerChecker(EVENT_REORDER, document)
];
this.invoke = function insertRelated_invoke()
{
this.hostNode = document.createElement("div");
this.hostNode.setAttribute(aHostRelAttr, aDependentID);
this.dependentNode = document.createElement("div");
this.dependentNode.setAttribute("id", aDependentID);
if (aInsertHostFirst) {
document.body.appendChild(this.hostNode);
document.body.appendChild(this.dependentNode);
} else {
document.body.appendChild(this.dependentNode);
document.body.appendChild(this.hostNode);
}
}
this.finalCheck = function insertRelated_finalCheck()
{
testRelation(this.dependentNode, aDependentRelation, this.hostNode);
if (aHostRelation)
testRelation(this.hostNode, aHostRelation, this.dependentNode);
}
this.getID = function insertRelated_getID()
{
return "Insert " + aHostRelAttr + "='" + aDependentID + "' node" +
(aInsertHostFirst ? " before" : "after") + " dependent node";
}
}
var gQueue = null;
function doTest()
{
// Relation updates on ARIA attribute changes.
testRelated("aria-labelledby", RELATION_LABELLED_BY, RELATION_LABEL_FOR);
testRelated("aria-describedby",
RELATION_DESCRIBED_BY, RELATION_DESCRIPTION_FOR);
testRelated("aria-owns", null, RELATION_NODE_CHILD_OF);
testRelated("aria-controls",
RELATION_CONTROLLER_FOR, RELATION_CONTROLLED_BY);
testRelated("aria-flowto", RELATION_FLOWS_TO, RELATION_FLOWS_FROM);
// Insert related accessibles into tree.
gQueue = new eventQueue();
gQueue.push(new insertRelated("aria-labelledby", "dependent3", true,
RELATION_LABELLED_BY, RELATION_LABEL_FOR));
gQueue.push(new insertRelated("aria-labelledby", "dependent4", false,
RELATION_LABELLED_BY, RELATION_LABEL_FOR));
gQueue.push(new insertRelated("aria-describedby", "dependent5", true,
RELATION_DESCRIBED_BY,
RELATION_DESCRIPTION_FOR));
gQueue.push(new insertRelated("aria-describedby", "dependent6", false,
RELATION_DESCRIBED_BY,
RELATION_DESCRIPTION_FOR));
gQueue.push(new insertRelated("aria-owns", "dependent7", true,
null, RELATION_NODE_CHILD_OF));
gQueue.push(new insertRelated("aria-owns", "dependent8", false,
null, RELATION_NODE_CHILD_OF));
gQueue.push(new insertRelated("aria-controls", "dependent9", true,
RELATION_CONTROLLER_FOR,
RELATION_CONTROLLED_BY));
gQueue.push(new insertRelated("aria-controls", "dependent10", false,
RELATION_CONTROLLER_FOR,
RELATION_CONTROLLED_BY));
gQueue.push(new insertRelated("aria-flowto", "dependent11", true,
RELATION_FLOWS_TO, RELATION_FLOWS_FROM));
gQueue.push(new insertRelated("aria-flowto", "dependent12", false,
RELATION_FLOWS_TO, RELATION_FLOWS_FROM));
gQueue.invoke(); // will call SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=573469"
title="Cache relations defined by ARIA attributes">
Mozilla Bug 573469
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="dependent1">label</div>
<div id="dependent2">label2</div>
<div role="checkbox" id="host"></div>
</body>
</html>

Просмотреть файл

@ -166,35 +166,46 @@ html|*.urlbar-input {
/* over-link in location bar */ /* over-link in location bar */
.urlbar-over-link-layer[overlinkstate="fade-in"],
.urlbar-textbox-container:not([overlinkstate]) {
-moz-transition-property: color;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: cubic-bezier(0.0, 0.6, 1.0, 1.0);
}
.urlbar-textbox-container[overlinkstate="fade-in"], .urlbar-textbox-container[overlinkstate="fade-in"],
.urlbar-over-link-layer:not([overlinkstate]) { .urlbar-over-link-layer[overlinkstate="fade-out"] {
-moz-transition-property: color; -moz-transition-property: color;
-moz-transition-duration: 150ms; -moz-transition-duration: 150ms;
-moz-transition-timing-function: linear;
color: transparent; color: transparent;
} }
.urlbar-over-link-box[overlinkstate="fade-in"], .urlbar-over-link-layer[overlinkstate="fade-in"],
.urlbar-textbox-container-children:not([overlinkstate]) { .urlbar-textbox-container[overlinkstate="fade-out"] {
-moz-transition-property: color;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: cubic-bezier(0.0, 1.0, 1.0, 1.0);
}
.urlbar-over-link-box[overlinkstate="fade-in"] {
-moz-transition-property: opacity; -moz-transition-property: opacity;
-moz-transition-duration: 150ms; -moz-transition-duration: 150ms;
opacity: 1; opacity: 1;
} }
.urlbar-textbox-container-children[overlinkstate="fade-in"], .urlbar-over-link-box[overlinkstate="fade-out"] {
.urlbar-over-link-box:not([overlinkstate]) { -moz-transition-property: opacity;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: cubic-bezier(0.0, 1.0, 1.0, 1.0);
opacity: 0;
}
.urlbar-textbox-container-children[overlinkstate="fade-in"] {
-moz-transition-property: opacity; -moz-transition-property: opacity;
-moz-transition-duration: 150ms; -moz-transition-duration: 150ms;
opacity: 0; opacity: 0;
} }
.urlbar-textbox-container-children[overlinkstate="fade-out"] {
-moz-transition-property: opacity;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: cubic-bezier(0.0, 1.0, 1.0, 1.0);
opacity: 1;
}
.urlbar-textbox-container[overlinkstate="showing"] { .urlbar-textbox-container[overlinkstate="showing"] {
color: transparent; color: transparent;
} }
@ -207,6 +218,14 @@ html|*.urlbar-input {
opacity: 0; opacity: 0;
} }
.urlbar-over-link-layer:not([overlinkstate]) {
color: transparent;
}
.urlbar-over-link-box:not([overlinkstate]) {
opacity: 0;
}
/* For results that are actions, their description text is shown instead of /* For results that are actions, their description text is shown instead of
the URL - this needs to follow the locale's direction, unlike URLs. */ the URL - this needs to follow the locale's direction, unlike URLs. */
richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box { richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box {

Просмотреть файл

@ -3994,12 +3994,14 @@ var XULBrowserWindow = {
this.defaultStatus = status; this.defaultStatus = status;
}, },
setOverLink: function (link) { setOverLink: function (url, anchorElt) {
if (gURLBar) {
// Encode bidirectional formatting characters. // Encode bidirectional formatting characters.
// (RFC 3987 sections 3.2 and 4.1 paragraph 6) // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
link = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g, url = url.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
encodeURIComponent); encodeURIComponent);
gURLBar.setOverLink(link); gURLBar.setOverLink(url);
}
}, },
// Called before links are navigated to to allow us to retarget them if needed. // Called before links are navigated to to allow us to retarget them if needed.
@ -4198,7 +4200,9 @@ var XULBrowserWindow = {
else else
this.isImage.setAttribute('disabled', 'true'); this.isImage.setAttribute('disabled', 'true');
this.hideOverLinkImmediately = true;
this.setOverLink("", null); this.setOverLink("", null);
this.hideOverLinkImmediately = false;
// We should probably not do this if the value has changed since the user // We should probably not do this if the value has changed since the user
// searched // searched

Просмотреть файл

@ -444,12 +444,14 @@
</button> </button>
</hbox> </hbox>
<spacer id="titlebar-spacer" flex="1"/> <spacer id="titlebar-spacer" flex="1"/>
<hbox id="titlebar-buttonbox" align="start"> <hbox id="titlebar-buttonbox-container" align="start">
<hbox id="titlebar-buttonbox">
<toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/> <toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
<toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/> <toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
<toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/> <toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/>
</hbox> </hbox>
</hbox> </hbox>
</hbox>
</vbox> </vbox>
#endif #endif

Просмотреть файл

@ -43,9 +43,17 @@
// The Drag that's currently in process. // The Drag that's currently in process.
var drag = { var drag = {
info: null, info: null,
zIndex: 100 zIndex: 100,
lastMoveTime: 0
}; };
//----------
//Variable: resize
//The resize (actually a Drag) that is currently in process
var resize = {
info: null,
lastMoveTime: 0
};
// ########## // ##########
// Class: Drag (formerly DragInfo) // Class: Drag (formerly DragInfo)

Просмотреть файл

@ -564,6 +564,14 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
this._sendToSubscribers("close"); this._sendToSubscribers("close");
this.removeTrenches(); this.removeTrenches();
if (this.hidden) {
iQ(this.container).remove();
if (this.$undoContainer) {
this.$undoContainer.remove();
this.$undoContainer = null;
}
Items.unsquish();
} else {
iQ(this.container).animate({ iQ(this.container).animate({
opacity: 0, opacity: 0,
"-moz-transform": "scale(.3)", "-moz-transform": "scale(.3)",
@ -574,7 +582,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
Items.unsquish(); Items.unsquish();
} }
}); });
}
this.deleteData(); this.deleteData();
}, },
@ -607,10 +615,107 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
UI.setActiveTab( UI.getClosestTab(closeCenter) ); UI.setActiveTab( UI.getClosestTab(closeCenter) );
}, },
// ----------
// Function: _unhide
// Shows the hidden group.
_unhide: function GroupItem__unhide() {
let self = this;
this._cancelFadeAwayUndoButtonTimer();
this.hidden = false;
this.$undoContainer.remove();
this.$undoContainer = null;
iQ(this.container).show().animate({
"-moz-transform": "scale(1)",
"opacity": 1
}, {
duration: 170,
complete: function() {
self._children.forEach(function(child) {
iQ(child.container).show();
});
}
});
self._sendToSubscribers("groupShown", { groupItemId: self.id });
},
// ----------
// Function: closeHidden
// Removes the group item, its children and its container.
closeHidden: function GroupItem_closeHidden() {
let self = this;
this._cancelFadeAwayUndoButtonTimer();
// when "TabClose" event is fired, the browser tab is about to close and our
// item "close" event is fired. And then, the browser tab gets closed.
// In other words, the group "close" event is fired before all browser
// tabs in the group are closed. The below code would fire the group "close"
// event only after all browser tabs in that group are closed.
let shouldRemoveTabItems = [];
let toClose = this._children.concat();
toClose.forEach(function(child) {
child.removeSubscriber(self, "close");
let removed = child.close();
if (removed) {
shouldRemoveTabItems.push(child);
} else {
// child.removeSubscriber() must be called before child.close(),
// therefore we call child.addSubscriber() if the tab is not removed.
child.addSubscriber(self, "close", function() {
self.remove(child);
});
}
});
if (shouldRemoveTabItems.length != toClose.length) {
// remove children without the assiciated tab and show the group item
shouldRemoveTabItems.forEach(function(child) {
self.remove(child, { dontArrange: true });
});
this.$undoContainer.fadeOut(function() { self._unhide() });
} else {
this.close();
}
},
// ----------
// Function: _fadeAwayUndoButton
// Fades away the undo button
_fadeAwayUndoButton: function GroupItem__fadeAwayUdoButton() {
let self = this;
if (this.$undoContainer) {
// if there is one or more orphan tabs or there is more than one group
// and other groupS are not empty, fade away the undo button.
let shouldFadeAway = GroupItems.getOrphanedTabs().length > 0;
if (!shouldFadeAway && GroupItems.groupItems.length > 1) {
shouldFadeAway =
GroupItems.groupItems.some(function(groupItem) {
return (groupItem != self && groupItem.getChildren().length > 0);
});
}
if (shouldFadeAway) {
self.$undoContainer.animate({
color: "transparent",
opacity: 0
}, {
duration: this._fadeAwayUndoButtonDuration,
complete: function() { self.closeHidden(); }
});
}
}
},
// ---------- // ----------
// Function: _createUndoButton // Function: _createUndoButton
// Makes the affordance for undo a close group action // Makes the affordance for undo a close group action
_createUndoButton: function() { _createUndoButton: function GroupItem__createUndoButton() {
let self = this; let self = this;
this.$undoContainer = iQ("<div/>") this.$undoContainer = iQ("<div/>")
.addClass("undo") .addClass("undo")
@ -629,6 +734,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}); });
this.hidden = true; this.hidden = true;
// hide group item and show undo container.
setTimeout(function() { setTimeout(function() {
self.$undoContainer.animate({ self.$undoContainer.animate({
"-moz-transform": "scale(1)", "-moz-transform": "scale(1)",
@ -642,36 +748,17 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}); });
}, 50); }, 50);
// add click handlers
this.$undoContainer.click(function(e) { this.$undoContainer.click(function(e) {
// Only do this for clicks on this actual element. // Only do this for clicks on this actual element.
if (e.target.nodeName != self.$undoContainer[0].nodeName) if (e.target.nodeName != self.$undoContainer[0].nodeName)
return; return;
self.$undoContainer.fadeOut(function() { self.$undoContainer.fadeOut(function() { self._unhide(); });
iQ(this).remove();
self.hidden = false;
self._cancelFadeAwayUndoButtonTimer();
self.$undoContainer = null;
iQ(self.container).show().animate({
"-moz-transform": "scale(1)",
"opacity": 1
}, {
duration: 170,
complete: function() {
self._children.forEach(function(child) {
iQ(child.container).show();
});
}
});
self._sendToSubscribers("groupShown", { groupItemId: self.id });
});
}); });
undoClose.click(function() { undoClose.click(function() {
self._cancelFadeAwayUndoButtonTimer(); self.$undoContainer.fadeOut(function() { self.closeHidden(); });
self.$undoContainer.fadeOut(function() { self._removeHiddenGroupItem(); });
}); });
this.setupFadeAwayUndoButtonTimer(); this.setupFadeAwayUndoButtonTimer();
@ -704,60 +791,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
this._undoButtonTimeoutId = null; this._undoButtonTimeoutId = null;
}, },
// ----------
// Fades away the undo button
_fadeAwayUndoButton: function() {
let self = this;
if (this.$undoContainer) {
// if there is one or more orphan tabs or there is more than one group
// and other groupS are not empty, fade away the undo button.
let shouldFadeAway = GroupItems.getOrphanedTabs().length > 0;
if (!shouldFadeAway && GroupItems.groupItems.length > 1) {
shouldFadeAway =
GroupItems.groupItems.some(function(groupItem) {
return (groupItem != self && groupItem.getChildren().length > 0);
});
}
if (shouldFadeAway) {
self.$undoContainer.animate({
color: "transparent",
opacity: 0
}, {
duration: this.fadeAwayUndoButtonDuration,
complete: function() { self._removeHiddenGroupItem(); }
});
}
}
},
// ----------
// Removes the group item, its children and its container.
_removeHiddenGroupItem: function() {
let self = this;
// close all children
let toClose = this._children.concat();
toClose.forEach(function(child) {
child.removeSubscriber(self, "close");
child.close();
});
// remove all children
this.removeAll();
GroupItems.unregister(this);
this._sendToSubscribers("close");
this.removeTrenches();
iQ(this.container).remove();
this.$undoContainer.remove();
this.$undoContainer = null;
Items.unsquish();
this.deleteData();
},
// ---------- // ----------
// Function: add // Function: add
// Adds an item to the groupItem. // Adds an item to the groupItem.
@ -1047,6 +1080,10 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// Parameters: // Parameters:
// options - passed to <Items.arrange> or <_stackArrange> // options - passed to <Items.arrange> or <_stackArrange>
arrange: function GroupItem_arrange(options) { arrange: function GroupItem_arrange(options) {
if (GroupItems._arrangePaused) {
GroupItems.pushArrange(this, options);
return;
}
if (this.expanded) { if (this.expanded) {
this.topChild = null; this.topChild = null;
var box = new Rect(this.expanded.bounds); var box = new Rect(this.expanded.bounds);
@ -1490,6 +1527,9 @@ let GroupItems = {
_activeGroupItem: null, _activeGroupItem: null,
_activeOrphanTab: null, _activeOrphanTab: null,
_cleanupFunctions: [], _cleanupFunctions: [],
_arrangePaused: false,
_arrangesPending: [],
_removingHiddenGroups: false,
// ---------- // ----------
// Function: init // Function: init
@ -1521,6 +1561,51 @@ let GroupItems = {
this.groupItems = null; this.groupItems = null;
}, },
// ----------
// Function: pauseArrange
// Bypass arrange() calls and collect for resolution in
// resumeArrange()
pauseArrange: function GroupItems_pauseArrange() {
Utils.assert(this._arrangePaused == false,
"pauseArrange has been called while already paused");
Utils.assert(this._arrangesPending.length == 0,
"There are bypassed arrange() calls that haven't been resolved");
this._arrangePaused = true;
},
// ----------
// Function: pushArrange
// Push an arrange() call and its arguments onto an array
// to be resolved in resumeArrange()
pushArrange: function GroupItems_pushArrange(groupItem, options) {
Utils.assert(this._arrangePaused,
"Ensure pushArrange() called while arrange()s aren't paused");
let i;
for (i = 0; i < this._arrangesPending.length; i++)
if (this._arrangesPending[i].groupItem === groupItem)
break;
let arrangeInfo = {
groupItem: groupItem,
options: options
};
if (i < this._arrangesPending.length)
this._arrangesPending[i] = arrangeInfo;
else
this._arrangesPending.push(arrangeInfo);
},
// ----------
// Function: resumeArrange
// Resolve bypassed and collected arrange() calls
resumeArrange: function GroupItems_resumeArrange() {
for (let i = 0; i < this._arrangesPending.length; i++) {
let g = this._arrangesPending[i];
g.groupItem.arrange(g.options);
}
this._arrangesPending = [];
this._arrangePaused = false;
},
// ---------- // ----------
// Function: _handleAttrModified // Function: _handleAttrModified
// watch for icon changes on app tabs // watch for icon changes on app tabs
@ -2107,19 +2192,16 @@ let GroupItems = {
// Function: removeHiddenGroups // Function: removeHiddenGroups
// Removes all hidden groups' data and its browser tabs. // Removes all hidden groups' data and its browser tabs.
removeHiddenGroups: function GroupItems_removeHiddenGroups() { removeHiddenGroups: function GroupItems_removeHiddenGroups() {
iQ(".undo").remove(); if (this._removingHiddenGroups)
return;
this._removingHiddenGroups = true;
// ToDo: encapsulate this in the group item. bug 594863 let groupItems = this.groupItems.concat();
this.groupItems.forEach(function(groupItem) { groupItems.forEach(function(groupItem) {
if (groupItem.hidden) { if (groupItem.hidden)
let toClose = groupItem._children.concat(); groupItem.closeHidden();
toClose.forEach(function(child) {
child.removeSubscriber(groupItem, "close");
child.close();
}); });
groupItem.deleteData(); this._removingHiddenGroups = false;
}
});
} }
}; };

Просмотреть файл

@ -699,6 +699,7 @@ iQClass.prototype = {
let events = [ let events = [
'keyup', 'keyup',
'keydown', 'keydown',
'keypress',
'mouseup', 'mouseup',
'mousedown', 'mousedown',
'mouseover', 'mouseover',

Просмотреть файл

@ -216,7 +216,6 @@ Item.prototype = {
// ___ resize // ___ resize
var self = this; var self = this;
var resizeInfo = null;
this.resizeOptions = { this.resizeOptions = {
aspectRatio: self.keepProportional, aspectRatio: self.keepProportional,
minWidth: 90, minWidth: 90,
@ -224,16 +223,16 @@ Item.prototype = {
start: function(e,ui) { start: function(e,ui) {
if (this.isAGroupItem) if (this.isAGroupItem)
GroupItems.setActiveGroupItem(this); GroupItems.setActiveGroupItem(this);
resizeInfo = new Drag(this, e, true); // true = isResizing resize.info = new Drag(this, e, true); // true = isResizing
}, },
resize: function(e,ui) { resize: function(e,ui) {
resizeInfo.snap(UI.rtl ? 'topright' : 'topleft', false, self.keepProportional); resize.info.snap(UI.rtl ? 'topright' : 'topleft', false, self.keepProportional);
}, },
stop: function() { stop: function() {
self.setUserSize(); self.setUserSize();
self.pushAway(); self.pushAway();
resizeInfo.stop(); resize.info.stop();
resizeInfo = null; resize.info = null;
} }
}; };
}, },
@ -599,6 +598,9 @@ Item.prototype = {
// ___ mousemove // ___ mousemove
var handleMouseMove = function(e) { var handleMouseMove = function(e) {
// global drag tracking
drag.lastMoveTime = Date.now();
// positioning // positioning
var mouse = new Point(e.pageX, e.pageY); var mouse = new Point(e.pageX, e.pageY);
if (!startSent) { if (!startSent) {
@ -766,6 +768,9 @@ Item.prototype = {
// ___ mousemove // ___ mousemove
var handleMouseMove = function(e) { var handleMouseMove = function(e) {
// global resize tracking
resize.lastMoveTime = Date.now();
var mouse = new Point(e.pageX, e.pageY); var mouse = new Point(e.pageX, e.pageY);
var box = self.getBounds(); var box = self.getBounds();
if (UI.rtl) { if (UI.rtl) {

Просмотреть файл

@ -132,7 +132,7 @@ var TabUtils = {
// Function: favURLOf // Function: favURLOf
// Given a <TabItem> or a <xul:tab> returns the URL of tab's favicon. // Given a <TabItem> or a <xul:tab> returns the URL of tab's favicon.
faviconURLOf: function TabUtils_faviconURLOf(tab) { faviconURLOf: function TabUtils_faviconURLOf(tab) {
return tab.image != undefined ? tab.image : tab.favEl.src; return tab.image != undefined ? tab.image : tab.favImgEl.src;
}, },
// --------- // ---------
@ -335,9 +335,9 @@ SearchEventHandlerClass.prototype = {
// Handles all keypresses before the search interface is brought up. // Handles all keypresses before the search interface is brought up.
beforeSearchKeyHandler: function (event) { beforeSearchKeyHandler: function (event) {
// Only match reasonable text-like characters for quick search. // Only match reasonable text-like characters for quick search.
var key = String.fromCharCode(event.which);
// TODO: Also include funky chars. Bug 593904 // TODO: Also include funky chars. Bug 593904
if (!key.match(/[A-Z0-9]/) || event.altKey || event.ctrlKey || event.metaKey) if (!String.fromCharCode(event.which).match(/[a-zA-Z0-9]/) || event.altKey ||
event.ctrlKey || event.metaKey)
return; return;
// If we are already in an input field, allow typing as normal. // If we are already in an input field, allow typing as normal.
@ -354,15 +354,16 @@ SearchEventHandlerClass.prototype = {
inSearchKeyHandler: function (event) { inSearchKeyHandler: function (event) {
var term = iQ("#searchbox").val(); var term = iQ("#searchbox").val();
if (event.which == event.DOM_VK_ESCAPE) if ((event.keyCode == event.DOM_VK_ESCAPE) ||
hideSearch(event); (event.keyCode == event.DOM_VK_BACK_SPACE && term.length <= 1)) {
if (event.which == event.DOM_VK_BACK_SPACE && term.length <= 1)
hideSearch(event); hideSearch(event);
return;
}
var matcher = new TabMatcher(term); var matcher = new TabMatcher(term);
var matches = matcher.matched(); var matches = matcher.matched();
var others = matcher.matchedTabsFromOtherWindows(); var others = matcher.matchedTabsFromOtherWindows();
if (event.which == event.DOM_VK_RETURN && (matches.length > 0 || others.length > 0)) { if (event.keyCode == event.DOM_VK_RETURN && (matches.length > 0 || others.length > 0)) {
hideSearch(event); hideSearch(event);
if (matches.length > 0) if (matches.length > 0)
matches[0].zoomIn(); matches[0].zoomIn();
@ -378,9 +379,9 @@ SearchEventHandlerClass.prototype = {
switchToBeforeMode: function switchToBeforeMode() { switchToBeforeMode: function switchToBeforeMode() {
var self = this; var self = this;
if (this.currentHandler) if (this.currentHandler)
iQ(document).unbind("keydown", this.currentHandler); iQ(window).unbind("keypress", this.currentHandler);
this.currentHandler = function(event) self.beforeSearchKeyHandler(event); this.currentHandler = function(event) self.beforeSearchKeyHandler(event);
iQ(document).keydown(self.currentHandler); iQ(window).keypress(this.currentHandler);
}, },
// ---------- // ----------
@ -390,9 +391,9 @@ SearchEventHandlerClass.prototype = {
switchToInMode: function switchToInMode() { switchToInMode: function switchToInMode() {
var self = this; var self = this;
if (this.currentHandler) if (this.currentHandler)
iQ(document).unbind("keydown", this.currentHandler); iQ(window).unbind("keypress", this.currentHandler);
this.currentHandler = function(event) self.inSearchKeyHandler(event); this.currentHandler = function(event) self.inSearchKeyHandler(event);
iQ(document).keydown(self.currentHandler); iQ(window).keypress(this.currentHandler);
} }
}; };
@ -488,13 +489,13 @@ function hideSearch(event){
event.stopPropagation(); event.stopPropagation();
} }
let newEvent = document.createEvent("Events");
newEvent.initEvent("tabviewsearchdisabled", false, false);
dispatchEvent(newEvent);
// Return focus to the tab window // Return focus to the tab window
UI.blurAll(); UI.blurAll();
gTabViewFrame.contentWindow.focus(); gTabViewFrame.contentWindow.focus();
let newEvent = document.createEvent("Events");
newEvent.initEvent("tabviewsearchdisabled", false, false);
dispatchEvent(newEvent);
} }
function performSearch() { function performSearch() {
@ -515,7 +516,7 @@ function ensureSearchShown(event){
iQ("#searchbutton").css({ opacity: 1 }); iQ("#searchbutton").css({ opacity: 1 });
if ($search.css("display") == "none") { if (!isSearchEnabled()) {
$search.show(); $search.show();
var mainWindow = gWindow.document.getElementById("main-window"); var mainWindow = gWindow.document.getElementById("main-window");
mainWindow.setAttribute("activetitlebarcolor", "#717171"); mainWindow.setAttribute("activetitlebarcolor", "#717171");
@ -529,18 +530,20 @@ function ensureSearchShown(event){
$searchbox[0].focus(); $searchbox[0].focus();
$searchbox[0].val = '0'; $searchbox[0].val = '0';
$searchbox.css({"z-index":"1015"}); $searchbox.css({"z-index":"1015"});
if (event != null){ if (event != null)
var keyCode = event.which + (event.shiftKey ? 0 : 32); $searchbox.val(String.fromCharCode(event.charCode));
$searchbox.val(String.fromCharCode(keyCode));
}
}, 0);
let newEvent = document.createEvent("Events"); let newEvent = document.createEvent("Events");
newEvent.initEvent("tabviewsearchenabled", false, false); newEvent.initEvent("tabviewsearchenabled", false, false);
dispatchEvent(newEvent); dispatchEvent(newEvent);
}, 0);
} }
} }
function isSearchEnabled() {
return iQ("#search").css("display") != "none";
}
var SearchEventHandler = new SearchEventHandlerClass(); var SearchEventHandler = new SearchEventHandlerClass();
// Features to add: // Features to add:

Просмотреть файл

@ -70,8 +70,10 @@ function TabItem(tab, options) {
this.canvasSizeForced = false; this.canvasSizeForced = false;
this.isShowingCachedData = false; this.isShowingCachedData = false;
this.favEl = (iQ('.favicon>img', $div))[0]; this.favEl = (iQ('.favicon', $div))[0];
this.favImgEl = (iQ('.favicon>img', $div))[0];
this.nameEl = (iQ('.tab-title', $div))[0]; this.nameEl = (iQ('.tab-title', $div))[0];
this.thumbEl = (iQ('.thumb', $div))[0];
this.canvasEl = (iQ('.thumb canvas', $div))[0]; this.canvasEl = (iQ('.thumb canvas', $div))[0];
this.cachedThumbEl = (iQ('img.cached-thumb', $div))[0]; this.cachedThumbEl = (iQ('img.cached-thumb', $div))[0];
@ -96,6 +98,8 @@ function TabItem(tab, options) {
this.bounds = $div.bounds(); this.bounds = $div.bounds();
this._lastTabUpdateTime = Date.now();
// ___ superclass setup // ___ superclass setup
this._init($div[0]); this._init($div[0]);
@ -194,6 +198,7 @@ function TabItem(tab, options) {
iQ("<div>") iQ("<div>")
.addClass('close') .addClass('close')
.appendTo($div); .appendTo($div);
this.closeEl = (iQ(".close", $div))[0];
iQ("<div>") iQ("<div>")
.addClass('expander') .addClass('expander')
@ -322,10 +327,10 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
this.bounds.copy(rect); this.bounds.copy(rect);
else { else {
var $container = iQ(this.container); var $container = iQ(this.container);
var $title = iQ('.tab-title', $container); var $title = iQ(this.nameEl);
var $thumb = iQ('.thumb', $container); var $thumb = iQ(this.thumbEl);
var $close = iQ('.close', $container); var $close = iQ(this.closeEl);
var $fav = iQ('.favicon', $container); var $fav = iQ(this.favEl);
var css = {}; var css = {};
const fontSizeRange = new Range(8,15); const fontSizeRange = new Range(8,15);
@ -461,12 +466,20 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// Function: close // Function: close
// Closes this item (actually closes the tab associated with it, which automatically // Closes this item (actually closes the tab associated with it, which automatically
// closes the item. // closes the item.
// Returns true if this tab is removed.
close: function TabItem_close() { close: function TabItem_close() {
// when "TabClose" event is fired, the browser tab is about to close and our
// item "close" is fired before the browser tab actually get closed.
// Therefore, we need "tabRemoved" event below.
gBrowser.removeTab(this.tab); gBrowser.removeTab(this.tab);
let tabNotClosed =
Array.some(gBrowser.tabs, function(tab) { return tab == this.tab; }, this);
if (!tabNotClosed)
this._sendToSubscribers("tabRemoved"); this._sendToSubscribers("tabRemoved");
// No need to explicitly delete the tab data, becasue sessionstore data // No need to explicitly delete the tab data, becasue sessionstore data
// associated with the tab will automatically go away // associated with the tab will automatically go away
return !tabNotClosed;
}, },
// ---------- // ----------
@ -544,9 +557,14 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
function onZoomDone() { function onZoomDone() {
UI.goToTab(tab); UI.goToTab(tab);
// tab might not be selected because hideTabView() is invoked after
// UI.goToTab() so we need to setup everything for the gBrowser.selectedTab
if (tab != gBrowser.selectedTab) {
UI.onTabSelect(gBrowser.selectedTab);
} else {
if (isNewBlankTab) if (isNewBlankTab)
gWindow.gURLBar.focus(); gWindow.gURLBar.focus();
}
if (childHitResult.callback) if (childHitResult.callback)
childHitResult.callback(); childHitResult.callback();
} }
@ -581,9 +599,10 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
onZoomDone(); onZoomDone();
} }
}); });
} else } else {
setTimeout(onZoomDone, 0); setTimeout(onZoomDone, 0);
} }
}
}, },
// ---------- // ----------
@ -684,10 +703,11 @@ let TabItems = {
items: [], items: [],
paintingPaused: 0, paintingPaused: 0,
_tabsWaitingForUpdate: [], _tabsWaitingForUpdate: [],
_heartbeatOn: false, _heartbeatOn: false, // see explanation at startHeartbeat() below
_heartbeatTiming: 100, // milliseconds between beats _heartbeatTiming: 100, // milliseconds between _checkHeartbeat() calls
_lastUpdateTime: Date.now(), _lastUpdateTime: Date.now(),
_eventListeners: [], _eventListeners: [],
tempCanvas: null,
// ---------- // ----------
// Function: init // Function: init
@ -696,6 +716,15 @@ let TabItems = {
Utils.assert(window.AllTabs, "AllTabs must be initialized first"); Utils.assert(window.AllTabs, "AllTabs must be initialized first");
var self = this; var self = this;
let $canvas = iQ("<canvas>");
$canvas.appendTo(iQ("body"));
$canvas.hide();
this.tempCanvas = $canvas[0];
// 150 pixels is an empirical size, below which FF's drawWindow()
// algorithm breaks down
this.tempCanvas.width = 150;
this.tempCanvas.height = 150;
// When a tab is opened, create the TabItem // When a tab is opened, create the TabItem
this._eventListeners["open"] = function(tab) { this._eventListeners["open"] = function(tab) {
if (tab.ownerDocument.defaultView != gWindow || tab.pinned) if (tab.ownerDocument.defaultView != gWindow || tab.pinned)
@ -774,6 +803,7 @@ let TabItems = {
if (shouldDefer && !isCurrentTab) { if (shouldDefer && !isCurrentTab) {
if (this._tabsWaitingForUpdate.indexOf(tab) == -1) if (this._tabsWaitingForUpdate.indexOf(tab) == -1)
this._tabsWaitingForUpdate.push(tab); this._tabsWaitingForUpdate.push(tab);
this.startHeartbeat();
} else } else
this._update(tab); this._update(tab);
} catch(e) { } catch(e) {
@ -802,8 +832,8 @@ let TabItems = {
if (iconUrl == null) if (iconUrl == null)
iconUrl = Utils.defaultFaviconURL; iconUrl = Utils.defaultFaviconURL;
if (iconUrl != tabItem.favEl.src) if (iconUrl != tabItem.favImgEl.src)
tabItem.favEl.src = iconUrl; tabItem.favImgEl.src = iconUrl;
// ___ URL // ___ URL
let tabUrl = tab.linkedBrowser.currentURI.spec; let tabUrl = tab.linkedBrowser.currentURI.spec;
@ -834,6 +864,9 @@ let TabItems = {
} }
} }
this._lastUpdateTime = Date.now();
tabItem._lastTabUpdateTime = this._lastUpdateTime;
tabItem.tabCanvas.paint(); tabItem.tabCanvas.paint();
// ___ cache // ___ cache
@ -843,8 +876,6 @@ let TabItems = {
} catch(e) { } catch(e) {
Utils.log(e); Utils.log(e);
} }
this._lastUpdateTime = Date.now();
}, },
// ---------- // ----------
@ -901,24 +932,41 @@ let TabItems = {
}, },
// ---------- // ----------
// Function: heartbeat // Function: startHeartbeat
// Allows us to spreadout update calls over a period of time. // Start a new heartbeat if there isn't one already started.
heartbeat: function TabItems_heartbeat() { // The heartbeat is a chain of setTimeout calls that allows us to spread
if (!this._heartbeatOn) // out update calls over a period of time.
// _heartbeatOn is used to make sure that we don't add multiple
// setTimeout chains.
startHeartbeat: function TabItems_startHeartbeat() {
if (!this._heartbeatOn) {
this._heartbeatOn = true;
let self = this;
setTimeout(function() {
self._checkHeartbeat();
}, this._heartbeatTiming);
}
},
// ----------
// Function: _checkHeartbeat
// This periodically checks for tabs waiting to be updated, and calls
// _update on them.
// Should only be called by startHeartbeat and resumePainting.
_checkHeartbeat: function TabItems__checkHeartbeat() {
this._heartbeatOn = false;
if (this.isPaintingPaused())
return; return;
if (this._tabsWaitingForUpdate.length) { if (this._tabsWaitingForUpdate.length && UI.isIdle()) {
this._update(this._tabsWaitingForUpdate[0]); this._update(this._tabsWaitingForUpdate[0]);
// _update will remove the tab from the waiting list //_update will remove the tab from the waiting list
} }
let self = this;
if (this._tabsWaitingForUpdate.length) { if (this._tabsWaitingForUpdate.length) {
setTimeout(function() { this.startHeartbeat();
self.heartbeat(); }
}, this._heartbeatTiming);
} else
this._hearbeatOn = false;
}, },
// ---------- // ----------
@ -929,9 +977,6 @@ let TabItems = {
// pausePainting needs to be mirrored with a call to <resumePainting>. // pausePainting needs to be mirrored with a call to <resumePainting>.
pausePainting: function TabItems_pausePainting() { pausePainting: function TabItems_pausePainting() {
this.paintingPaused++; this.paintingPaused++;
if (this.isPaintingPaused() && this._heartbeatOn)
this._heartbeatOn = false;
}, },
// ---------- // ----------
@ -941,13 +986,8 @@ let TabItems = {
// three times before TabItems will start updating thumbnails again. // three times before TabItems will start updating thumbnails again.
resumePainting: function TabItems_resumePainting() { resumePainting: function TabItems_resumePainting() {
this.paintingPaused--; this.paintingPaused--;
if (!this.isPaintingPaused())
if (!this.isPaintingPaused() && this.startHeartbeat();
this._tabsWaitingForUpdate.length &&
!this._heartbeatOn) {
this._heartbeatOn = true;
this.heartbeat();
}
}, },
// ---------- // ----------
@ -1106,8 +1146,6 @@ TabCanvas.prototype = {
// ---------- // ----------
// Function: paint // Function: paint
paint: function TabCanvas_paint(evt) { paint: function TabCanvas_paint(evt) {
var ctx = this.canvas.getContext("2d");
var w = this.canvas.width; var w = this.canvas.width;
var h = this.canvas.height; var h = this.canvas.height;
if (!w || !h) if (!w || !h)
@ -1119,6 +1157,45 @@ TabCanvas.prototype = {
return; return;
} }
let tempCanvas = TabItems.tempCanvas;
if (w < tempCanvas.width) {
// Small draw case where nearest-neighbor algorithm breaks down in Windows
// First draw to a larger canvas (150px wide), and then draw that image
// to the destination canvas.
var tempCtx = tempCanvas.getContext("2d");
let canvW = tempCanvas.width;
let canvH = (h/w) * canvW;
var scaler = canvW/fromWin.innerWidth;
tempCtx.save();
tempCtx.clearRect(0,0,tempCanvas.width,tempCanvas.height);
tempCtx.scale(scaler, scaler);
try{
tempCtx.drawWindow(fromWin, fromWin.scrollX, fromWin.scrollY,
canvW/scaler, canvH/scaler, "#fff");
} catch(e) {
Utils.error('paint', e);
}
tempCtx.restore();
// Now copy to tabitem canvas. No save/restore necessary.
var destCtx = this.canvas.getContext("2d");
try{
// the tempcanvas is square, so draw it as a square.
destCtx.drawImage(tempCanvas, 0, 0, w, w);
} catch(e) {
Utils.error('paint', e);
}
} else {
// General case where nearest neighbor algorithm looks good
// Draw directly to the destination canvas
var ctx = this.canvas.getContext("2d");
var scaler = w/fromWin.innerWidth; var scaler = w/fromWin.innerWidth;
// TODO: Potentially only redraw the dirty rect? (Is it worth it?) // TODO: Potentially only redraw the dirty rect? (Is it worth it?)
@ -1132,6 +1209,7 @@ TabCanvas.prototype = {
} }
ctx.restore(); ctx.restore();
}
}, },
// ---------- // ----------

Просмотреть файл

@ -88,6 +88,12 @@ let UI = {
// An array of functions to be called at uninit time // An array of functions to be called at uninit time
_cleanupFunctions: [], _cleanupFunctions: [],
// Constant: _maxInteractiveWait
// If the UI is in the middle of an operation, this is the max amount of
// milliseconds to wait between input events before we no longer consider
// the operation interactive.
_maxInteractiveWait: 250,
// Variable: _privateBrowsing // Variable: _privateBrowsing
// Keeps track of info related to private browsing, including: // Keeps track of info related to private browsing, including:
// transitionStage - what step we're on in entering/exiting PB // transitionStage - what step we're on in entering/exiting PB
@ -171,6 +177,7 @@ let UI = {
// ___ Storage // ___ Storage
GroupItems.pauseArrange();
GroupItems.init(); GroupItems.init();
let firstTime = true; let firstTime = true;
@ -224,6 +231,8 @@ let UI = {
dispatchEvent(event); dispatchEvent(event);
} catch(e) { } catch(e) {
Utils.log(e); Utils.log(e);
} finally {
GroupItems.resumeArrange();
} }
}, },
@ -320,6 +329,18 @@ let UI = {
}); });
}, },
// ----------
// Function: isIdle
// Returns true if the last interaction was long enough ago to consider the
// UI idle. Used to determine whether interactivity would be sacrificed if
// the CPU was to become busy.
//
isIdle: function UI_isIdle() {
let time = Date.now();
let maxEvent = Math.max(drag.lastMoveTime, resize.lastMoveTime);
return (time - maxEvent) > this._maxInteractiveWait;
},
// ---------- // ----------
// Function: getActiveTab // Function: getActiveTab
// Returns the currently active tab as a <TabItem> // Returns the currently active tab as a <TabItem>
@ -450,6 +471,8 @@ let UI = {
if (!this._isTabViewVisible()) if (!this._isTabViewVisible())
return; return;
// another tab might be select if user decides to stay on a page when
// a onclose confirmation prompts.
GroupItems.removeHiddenGroups(); GroupItems.removeHiddenGroups();
TabItems.pausePainting(); TabItems.pausePainting();
@ -678,6 +701,7 @@ let UI = {
}, },
// ---------- // ----------
// Function: goToTab
// Selects the given xul:tab in the browser. // Selects the given xul:tab in the browser.
goToTab: function UI_goToTab(xulTab) { goToTab: function UI_goToTab(xulTab) {
// If it's not focused, the onFocus listener would handle it. // If it's not focused, the onFocus listener would handle it.
@ -710,6 +734,11 @@ let UI = {
if (this._isTabViewVisible()) if (this._isTabViewVisible())
this.hideTabView(); this.hideTabView();
// another tab might be selected when hideTabView() is invoked so a
// validation is needed.
if (this._currentTab != tab)
return;
let oldItem = null; let oldItem = null;
let newItem = null; let newItem = null;
@ -814,11 +843,16 @@ let UI = {
var self = this; var self = this;
iQ(window).keyup(function(event) { iQ(window).keyup(function(event) {
if (!event.metaKey) Keys.meta = false; if (!event.metaKey)
Keys.meta = false;
}); });
iQ(window).keydown(function(event) { iQ(window).keydown(function(event) {
if (event.metaKey) Keys.meta = true; if (event.metaKey)
Keys.meta = true;
if (isSearchEnabled())
return;
function getClosestTabBy(norm) { function getClosestTabBy(norm) {
if (!self.getActiveTab()) if (!self.getActiveTab())
@ -989,11 +1023,12 @@ let UI = {
} }
function collapse() { function collapse() {
let center = phantom.bounds().center();
phantom.animate({ phantom.animate({
width: 0, width: 0,
height: 0, height: 0,
top: phantom.position().x + phantom.height()/2, top: center.y,
left: phantom.position().y + phantom.width()/2 left: center.x
}, { }, {
duration: 300, duration: 300,
complete: function() { complete: function() {

Просмотреть файл

@ -3,37 +3,41 @@
* http://creativecommons.org/publicdomain/zero/1.0/ * http://creativecommons.org/publicdomain/zero/1.0/
**/ **/
var gTests = [
{
name: "normal search (search service)",
testText: "test search",
searchURL: Services.search.originalDefaultEngine.getSubmission("test search").uri.spec
},
{
name: "?-prefixed search (search service)",
testText: "? foo ",
searchURL: Services.search.originalDefaultEngine.getSubmission("foo").uri.spec
},
{
name: "normal search (keyword.url)",
testText: "test search",
keywordURLPref: "http://example.com/?q=",
searchURL: "http://example.com/?q=test+search"
},
{
name: "?-prefixed search (keyword.url)",
testText: "? foo ",
keywordURLPref: "http://example.com/?q=",
searchURL: "http://example.com/?q=foo"
},
{
name: "encoding test (keyword.url)",
testText: "test encoded+%/",
keywordURLPref: "http://example.com/?q=",
searchURL: "http://example.com/?q=test+encoded%2B%25%2F"
}
];
function test() { function test() {
waitForExplicitFinish(); waitForExplicitFinish();
let tab = gBrowser.selectedTab = gBrowser.addTab(); let windowObserver = {
let searchText = "test search";
let listener = {
onStateChange: function onLocationChange(webProgress, req, flags, status) {
ok(flags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT, "only notified for document");
// Only care about starts
if (!(flags & Ci.nsIWebProgressListener.STATE_START))
return;
ok(req instanceof Ci.nsIChannel, "req is a channel");
let searchURL = Services.search.originalDefaultEngine.getSubmission(searchText).uri.spec;
is(req.originalURI.spec, searchURL, "search URL was loaded");
info("Actual URI: " + req.URI.spec);
Services.ww.unregisterNotification(observer);
gBrowser.removeProgressListener(this);
executeSoon(function () {
gBrowser.removeTab(tab);
finish();
});
}
}
gBrowser.addProgressListener(listener, Ci.nsIWebProgressListener.NOTIFY_STATE_DOCUMENT);
let observer = {
observe: function(aSubject, aTopic, aData) { observe: function(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") { if (aTopic == "domwindowopened") {
ok(false, "Alert window opened"); ok(false, "Alert window opened");
@ -42,19 +46,67 @@ function test() {
win.removeEventListener("load", arguments.callee, false); win.removeEventListener("load", arguments.callee, false);
win.close(); win.close();
}, false); }, false);
gBrowser.removeProgressListener(listener); executeSoon(finish);
executeSoon(function () {
gBrowser.removeTab(tab);
finish();
});
} }
Services.ww.unregisterNotification(this);
} }
}; };
Services.ww.registerNotification(observer);
Services.ww.registerNotification(windowObserver);
let tab = gBrowser.selectedTab = gBrowser.addTab();
let listener = {
onStateChange: function onLocationChange(webProgress, req, flags, status) {
// Only care about document starts
let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
Ci.nsIWebProgressListener.STATE_START;
if (!(flags & docStart))
return;
info("received document start");
ok(req instanceof Ci.nsIChannel, "req is a channel");
is(req.originalURI.spec, gCurrTest.searchURL, "search URL was loaded");
info("Actual URI: " + req.URI.spec);
executeSoon(nextTest);
}
}
gBrowser.addProgressListener(listener);
registerCleanupFunction(function () {
Services.ww.unregisterNotification(windowObserver);
gBrowser.removeProgressListener(listener);
gBrowser.removeTab(tab);
});
nextTest();
}
var gCurrTest;
function nextTest() {
// Clear the pref before every test (and after the last)
try {
Services.prefs.clearUserPref("keyword.URL");
} catch(ex) {}
if (gTests.length) {
gCurrTest = gTests.shift();
doTest();
} else {
finish();
}
}
function doTest() {
info("Running test: " + gCurrTest.name);
if (gCurrTest.keywordURLPref)
Services.prefs.setCharPref("keyword.URL", gCurrTest.keywordURLPref);
// Simulate a user entering search terms // Simulate a user entering search terms
gURLBar.value = searchText; gURLBar.value = gCurrTest.testText;
gURLBar.focus(); gURLBar.focus();
EventUtils.synthesizeKey("VK_RETURN", {}); EventUtils.synthesizeKey("VK_RETURN", {});
} }

Просмотреть файл

@ -48,6 +48,7 @@ _BROWSER_FILES = \
browser_tabview_apptabs.js \ browser_tabview_apptabs.js \
browser_tabview_bug580412.js \ browser_tabview_bug580412.js \
browser_tabview_bug587043.js \ browser_tabview_bug587043.js \
browser_tabview_bug587231.js \
browser_tabview_bug587990.js \ browser_tabview_bug587990.js \
browser_tabview_bug589324.js \ browser_tabview_bug589324.js \
browser_tabview_bug590606.js \ browser_tabview_bug590606.js \
@ -59,7 +60,9 @@ _BROWSER_FILES = \
browser_tabview_bug595804.js \ browser_tabview_bug595804.js \
browser_tabview_bug595930.js \ browser_tabview_bug595930.js \
browser_tabview_bug595943.js \ browser_tabview_bug595943.js \
browser_tabview_bug597399.js \
browser_tabview_bug598600.js \ browser_tabview_bug598600.js \
browser_tabview_bug599626.js \
browser_tabview_dragdrop.js \ browser_tabview_dragdrop.js \
browser_tabview_exit_button.js \ browser_tabview_exit_button.js \
browser_tabview_group.js \ browser_tabview_group.js \
@ -76,6 +79,7 @@ _BROWSER_FILES = \
head.js \ head.js \
search1.html \ search1.html \
search2.html \ search2.html \
test_bug599626.html \
$(NULL) $(NULL)
# compartments: test disabled # compartments: test disabled

Просмотреть файл

@ -0,0 +1,125 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tabview drag and drop test.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Sean Dunn <seanedunn@yahoo.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
let activeTab;
let testTab;
let testGroup;
let contentWindow;
function test() {
waitForExplicitFinish();
contentWindow = document.getElementById("tab-view").contentWindow;
// create new tab
testTab = gBrowser.addTab("http://mochi.test:8888/");
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
TabView.toggle();
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
ok(TabView.isVisible(), "Tab View is visible");
// create group
let testGroupRect = new contentWindow.Rect(20, 20, 300, 300);
testGroup = new contentWindow.GroupItem([], { bounds: testGroupRect });
ok(testGroup.isEmpty(), "This group is empty");
// place tab in group
let testTabItem = testTab.tabItem;
if (testTabItem.parent)
testTabItem.parent.remove(testTabItem);
testGroup.add(testTabItem);
// record last update time of tab canvas
let initialUpdateTime = testTabItem._lastTabUpdateTime;
// simulate resize
let resizer = contentWindow.iQ('.iq-resizable-handle', testGroup.container)[0];
let offsetX = 100;
let offsetY = 100;
let delay = 500;
let funcChain = new Array();
funcChain.push(function() {
EventUtils.synthesizeMouse(
resizer, 1, 1, { type: "mousedown" }, contentWindow);
setTimeout(funcChain.shift(), delay);
});
// drag
for (let i = 4; i >= 0; i--) {
funcChain.push(function() {
EventUtils.synthesizeMouse(
resizer, Math.round(offsetX/4), Math.round(offsetY/4),
{ type: "mousemove" }, contentWindow);
setTimeout(funcChain.shift(), delay);
});
}
funcChain.push(function() {
EventUtils.synthesizeMouse(resizer, 0, 0, { type: "mouseup" },
contentWindow);
setTimeout(funcChain.shift(), delay);
});
funcChain.push(function() {
// verify that update time has changed after last update
let lastTime = testTabItem._lastTabUpdateTime;
let hbTiming = contentWindow.TabItems._heartbeatTiming;
ok((lastTime - initialUpdateTime) > hbTiming, "Tab has been updated:"+lastTime+"-"+initialUpdateTime+">"+hbTiming);
// clean up
testGroup.remove(testTab.tabItem);
testTab.tabItem.close();
testGroup.close();
let currentTabs = contentWindow.TabItems.getItems();
ok(currentTabs[0], "A tab item exists to make active");
contentWindow.UI.setActiveTab(currentTabs[0]);
window.addEventListener("tabviewhidden", finishTest, false);
TabView.toggle();
});
setTimeout(funcChain.shift(), delay);
}
function finishTest() {
window.removeEventListener("tabviewhidden", finishTest, false);
ok(!TabView.isVisible(), "Tab View is not visible");
finish();
}

Просмотреть файл

@ -55,10 +55,10 @@ function onTabViewWindowLoaded() {
ok(searchButton, "Search button exists"); ok(searchButton, "Search button exists");
let onSearchEnabled = function() { let onSearchEnabled = function() {
let search = contentWindow.document.getElementById("search");
ok(search.style.display != "none", "Search is enabled");
contentWindow.removeEventListener( contentWindow.removeEventListener(
"tabviewsearchenabled", onSearchEnabled, false); "tabviewsearchenabled", onSearchEnabled, false);
let search = contentWindow.document.getElementById("search");
ok(search.style.display != "none", "Search is enabled");
escapeTest(contentWindow); escapeTest(contentWindow);
} }
contentWindow.addEventListener("tabviewsearchenabled", onSearchEnabled, contentWindow.addEventListener("tabviewsearchenabled", onSearchEnabled,
@ -70,21 +70,16 @@ function onTabViewWindowLoaded() {
function escapeTest(contentWindow) { function escapeTest(contentWindow) {
let onSearchDisabled = function() { let onSearchDisabled = function() {
let search = contentWindow.document.getElementById("search");
ok(search.style.display == "none", "Search is disabled");
contentWindow.removeEventListener( contentWindow.removeEventListener(
"tabviewsearchdisabled", onSearchDisabled, false); "tabviewsearchdisabled", onSearchDisabled, false);
let search = contentWindow.document.getElementById("search");
ok(search.style.display == "none", "Search is disabled");
toggleTabViewTest(contentWindow); toggleTabViewTest(contentWindow);
} }
contentWindow.addEventListener("tabviewsearchdisabled", onSearchDisabled, contentWindow.addEventListener("tabviewsearchdisabled", onSearchDisabled,
false); false);
// the search box focus()es in a function on the timeout queue, so we just EventUtils.synthesizeKey("VK_ESCAPE", { type: "keypress" }, contentWindow);
// want to queue behind it.
setTimeout( function() {
EventUtils.synthesizeKey("VK_ESCAPE", {});
}, 0);
} }
function toggleTabViewTest(contentWindow) { function toggleTabViewTest(contentWindow) {
@ -92,14 +87,9 @@ function toggleTabViewTest(contentWindow) {
contentWindow.removeEventListener("tabviewhidden", onTabViewHidden, false); contentWindow.removeEventListener("tabviewhidden", onTabViewHidden, false);
ok(!TabView.isVisible(), "Tab View is hidden"); ok(!TabView.isVisible(), "Tab View is hidden");
finish(); finish();
} }
contentWindow.addEventListener("tabviewhidden", onTabViewHidden, false); contentWindow.addEventListener("tabviewhidden", onTabViewHidden, false);
// When search is hidden, it focus()es on the background, so avert the
// race condition by delaying ourselves on the timeout queue
setTimeout( function() {
// Use keyboard shortcut to toggle back to browser view // Use keyboard shortcut to toggle back to browser view
EventUtils.synthesizeKey("e", { accelKey: true }); EventUtils.synthesizeKey("e", { accelKey: true });
}, 0);
} }

Просмотреть файл

@ -0,0 +1,82 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is a test for bug 597399.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
waitForExplicitFinish();
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
TabView.toggle();
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
let contentWindow = document.getElementById("tab-view").contentWindow;
let number = -1;
let onSearchEnabled = function() {
let searchBox = contentWindow.document.getElementById("searchbox");
is(searchBox.value, number, "The seach box matches the number: " + number);
contentWindow.hideSearch(null);
}
let onSearchDisabled = function() {
if (++number <= 9) {
EventUtils.synthesizeKey(String(number), { }, contentWindow);
} else {
contentWindow.removeEventListener(
"tabviewsearchenabled", onSearchEnabled, false);
contentWindow.removeEventListener(
"tabviewsearchdisabled", onSearchDisabled, false);
let endGame = function() {
window.removeEventListener("tabviewhidden", endGame, false);
ok(!TabView.isVisible(), "Tab View is hidden");
finish();
}
window.addEventListener("tabviewhidden", endGame, false);
TabView.toggle();
}
}
contentWindow.addEventListener(
"tabviewsearchenabled", onSearchEnabled, false);
contentWindow.addEventListener(
"tabviewsearchdisabled", onSearchDisabled, false);
onSearchDisabled();
}

Просмотреть файл

@ -0,0 +1,194 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tabview bug 599626 test.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
let handleDialog;
function test() {
waitForExplicitFinish();
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
TabView.toggle();
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
let contentWindow = document.getElementById("tab-view").contentWindow;
let groupItemOne = contentWindow.GroupItems.getActiveGroupItem();
// Create a group and make it active
let box = new contentWindow.Rect(10, 10, 300, 300);
let groupItemTwo = new contentWindow.GroupItem([], { bounds: box });
contentWindow.GroupItems.setActiveGroupItem(groupItemTwo);
let testTab =
gBrowser.addTab(
"http://mochi.test:8888/browser/browser/base/content/test/tabview/test_bug599626.html");
let browser = gBrowser.getBrowserForTab(testTab);
let onLoad = function() {
browser.removeEventListener("load", onLoad, true);
testStayOnPage(contentWindow, groupItemOne, groupItemTwo);
}
browser.addEventListener("load", onLoad, true);
}
function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) {
groupItemTwo.addSubscriber(groupItemTwo, "groupShown", function() {
groupItemTwo.removeSubscriber(groupItemTwo, "groupShown");
is(gBrowser.tabs.length, 2,
"The total number of tab is 2 when staying on the page");
is(contentWindow.TabItems.getItems().length, 2,
"The total number of tab items is 2 when staying on the page");
let onTabViewShown = function() {
window.removeEventListener("tabviewshown", onTabViewShown, false);
// start the next test
testLeavePage(contentWindow, groupItemOne, groupItemTwo);
};
window.addEventListener("tabviewshown", onTabViewShown, false);
TabView.toggle();
});
// stay on page
doc.documentElement.getButton("cancel").click();
});
}
function testLeavePage(contentWindow, groupItemOne, groupItemTwo) {
setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) {
// clean up and finish the test
groupItemTwo.addSubscriber(groupItemTwo, "close", function() {
groupItemTwo.removeSubscriber(groupItemTwo, "close");
is(gBrowser.tabs.length, 1,
"The total number of tab is 1 after leaving the page");
is(contentWindow.TabItems.getItems().length, 1,
"The total number of tab items is 1 after leaving the page");
let endGame = function() {
window.removeEventListener("tabviewhidden", endGame, false);
finish();
};
window.addEventListener("tabviewhidden", endGame, false);
});
// Leave page
doc.documentElement.getButton("accept").click();
});
}
function setupAndRun(contentWindow, groupItemOne, groupItemTwo, callback) {
let closeButton = groupItemTwo.container.getElementsByClassName("close");
ok(closeButton[0], "Group close button exists");
// click the close button
EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
handleDialog = function(doc) {
callback(doc);
};
startCallbackTimer();
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
let tabItem = groupItemOne.getChild(0);
tabItem.zoomIn();
}
// Copied from http://mxr.mozilla.org/mozilla-central/source/toolkit/components/places/tests/mochitest/prompt_common.js
let observer = {
QueryInterface : function (iid) {
const interfaces = [Ci.nsIObserver, Ci.nsISupports, Ci.nsISupportsWeakReference];
if (!interfaces.some( function(v) { return iid.equals(v) } ))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
observe : function (subject, topic, data) {
let doc = getDialogDoc();
if (doc)
handleDialog(doc);
else
startCallbackTimer(); // try again in a bit
}
};
function startCallbackTimer() {
// Delay before the callback twiddles the prompt.
const dialogDelay = 10;
// Use a timer to invoke a callback to twiddle the authentication dialog
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.init(observer, dialogDelay, Ci.nsITimer.TYPE_ONE_SHOT);
}
function getDialogDoc() {
// Find the <browser> which contains notifyWindow, by looking
// through all the open windows and all the <browsers> in each.
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
let enumerator = wm.getXULWindowEnumerator(null);
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
let windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
let containedDocShells = windowDocShell.getDocShellEnumerator(
Ci.nsIDocShellTreeItem.typeChrome,
Ci.nsIDocShell.ENUMERATE_FORWARDS);
while (containedDocShells.hasMoreElements()) {
// Get the corresponding document for this docshell
let childDocShell = containedDocShells.getNext();
// We don't want it if it's not done loading.
if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
continue;
let childDoc = childDocShell.QueryInterface(Ci.nsIDocShell).
contentViewer.DOMDocument;
if (childDoc.location.href == "chrome://global/content/commonDialog.xul")
return childDoc;
}
}
return null;
}

Просмотреть файл

@ -0,0 +1,10 @@
<html>
<script>
window.onbeforeunload = function(event){
event.returnValue = 'Confirmation? ';
}
</script>
<body>
Test page
</body>
</html>

Просмотреть файл

@ -200,6 +200,7 @@
<method name="onBeforeValueSet"> <method name="onBeforeValueSet">
<parameter name="aValue"/> <parameter name="aValue"/>
<body><![CDATA[ <body><![CDATA[
this._hideOverLink();
this._value = aValue; this._value = aValue;
var returnValue = aValue; var returnValue = aValue;
var action = this._parseActionUrl(aValue); var action = this._parseActionUrl(aValue);
@ -642,19 +643,21 @@
<method name="setOverLink"> <method name="setOverLink">
<parameter name="aURL"/> <parameter name="aURL"/>
<body><![CDATA[ <body><![CDATA[
// If the over-link is already scheduled to appear or hide, cancel it. this._cancelOverLinkDelayTimer();
if (this._overLinkDelayTimer) {
clearTimeout(this._overLinkDelayTimer); // Hide the over-link immediately if necessary.
this._overLinkDelayTimer = null; if (!aURL && (XULBrowserWindow.hideOverLinkImmediately ||
this._hideOverLinkImmediately)) {
this._setOverLinkState(null);
return;
} }
// Hide the over-link if aURL is falsey or if the URL bar is focused. // If aURL is falsey, fade it out after a delay. This happens on
if (!aURL || this.focused) { // mouseout for example.
if (!aURL) {
this._overLinkDelayTimer = setTimeout(function overLinkOut(self) { this._overLinkDelayTimer = setTimeout(function overLinkOut(self) {
self._overLinkDelayTimer = null; self._overLinkDelayTimer = null;
let style = window.getComputedStyle(self._overLinkBox, null); self._setOverLinkState("fade-out");
self._overLinkTransitioning = style.opacity != 0;
self.removeAttribute("overlinkstate");
}, this._overLinkOutDelay, this); }, this._overLinkOutDelay, this);
return; return;
} }
@ -662,8 +665,7 @@
// If it's in transition, update and show it immediately. // If it's in transition, update and show it immediately.
if (this._overLinkTransitioning) { if (this._overLinkTransitioning) {
this._updateOverLink(aURL); this._updateOverLink(aURL);
this._overLinkTransitioning = false; this._setOverLinkState("showing");
this.setAttribute("overlinkstate", "showing");
return; return;
} }
@ -673,13 +675,54 @@
this._overLinkDelayTimer = setTimeout(function overLinkIn(self) { this._overLinkDelayTimer = setTimeout(function overLinkIn(self) {
self._overLinkDelayTimer = null; self._overLinkDelayTimer = null;
self._updateOverLink(aURL); self._updateOverLink(aURL);
let style = window.getComputedStyle(self._overLinkBox, null); self._setOverLinkState("fade-in");
self._overLinkTransitioning = style.opacity != 1;
self.setAttribute("overlinkstate", "fade-in");
}, this._overLinkInDelay, this); }, this._overLinkInDelay, this);
]]></body> ]]></body>
</method> </method>
<method name="_hideOverLink">
<body><![CDATA[
this._hideOverLinkImmediately = true;
this.setOverLink("");
this._hideOverLinkImmediately = false;
]]></body>
</method>
<method name="_cancelOverLinkDelayTimer">
<body><![CDATA[
if (this._overLinkDelayTimer) {
clearTimeout(this._overLinkDelayTimer);
this._overLinkDelayTimer = null;
}
]]></body>
</method>
<method name="_setOverLinkState">
<parameter name="aVal"/>
<body><![CDATA[
switch (aVal) {
case "fade-in":
var style = window.getComputedStyle(this._overLinkBox);
this._overLinkTransitioning = style.opacity != 1;
this.setAttribute("overlinkstate", aVal);
break;
case "fade-out":
style = window.getComputedStyle(this._overLinkBox);
this._overLinkTransitioning = style.opacity != 0;
this.setAttribute("overlinkstate", aVal);
break;
case "showing":
this._overLinkTransitioning = false;
this.setAttribute("overlinkstate", aVal);
break;
default:
this._overLinkTransitioning = false;
this.removeAttribute("overlinkstate");
break;
}
]]></body>
</method>
<method name="_updateOverLink"> <method name="_updateOverLink">
<parameter name="aURL"/> <parameter name="aURL"/>
<body><![CDATA[ <body><![CDATA[
@ -761,8 +804,8 @@
]]></handler> ]]></handler>
<handler event="focus" phase="capturing"><![CDATA[ <handler event="focus" phase="capturing"><![CDATA[
this._hideOverLink();
this._hideURLTooltip(); this._hideURLTooltip();
this.setOverLink(null);
]]></handler> ]]></handler>
<handler event="dragover" phase="capturing" action="this.onDragOver(event, this);"/> <handler event="dragover" phase="capturing" action="this.onDragOver(event, this);"/>

Просмотреть файл

@ -45,8 +45,8 @@ function test() {
const HISTORY_SIDEBAR_TREE_ID = "historyTree"; const HISTORY_SIDEBAR_TREE_ID = "historyTree";
// Initialization. // Initialization.
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIWindowWatcher); getService(Ci.nsIObserverService);
let bs = PlacesUtils.bookmarks; let bs = PlacesUtils.bookmarks;
let hs = PlacesUtils.history; let hs = PlacesUtils.history;
let sidebarBox = document.getElementById("sidebar-box"); let sidebarBox = document.getElementById("sidebar-box");
@ -125,22 +125,20 @@ function test() {
preFunc(); preFunc();
function observer(aSubject, aTopic, aData) { function observer(aSubject, aTopic, aData) {
if (aTopic != "domwindowopened")
return;
ww.unregisterNotification(observer);
let alertDialog = aSubject.QueryInterface(Ci.nsIDOMWindow);
alertDialog.addEventListener("load", function () {
alertDialog.removeEventListener("load", arguments.callee, false);
info("alert dialog observed as expected"); info("alert dialog observed as expected");
os.removeObserver(observer, "common-dialog-loaded");
os.removeObserver(observer, "tabmodal-dialog-loaded");
aSubject.Dialog.ui.button0.click();
executeSoon(function () { executeSoon(function () {
alertDialog.close();
toggleSidebar(currentTest.sidebarName); toggleSidebar(currentTest.sidebarName);
currentTest.cleanup(); currentTest.cleanup();
postFunc(); postFunc();
}); });
}, false);
} }
ww.registerNotification(observer); os.addObserver(observer, "common-dialog-loaded", false);
os.addObserver(observer, "tabmodal-dialog-loaded", false);
// Select the inserted places item. // Select the inserted places item.
currentTest.selectNode(tree); currentTest.selectNode(tree);
@ -160,7 +158,7 @@ function test() {
y = y.value + height.value / 2; y = y.value + height.value / 2;
// Simulate the click. // Simulate the click.
EventUtils.synthesizeMouse(tree.body, x, y, {}, doc.defaultView); EventUtils.synthesizeMouse(tree.body, x, y, {}, doc.defaultView);
// Now, wait for the domwindowopened observer to catch the alert dialog. // Now, wait for the observer to catch the alert dialog.
// If something goes wrong, the test will time out at this stage. // If something goes wrong, the test will time out at this stage.
// Note that for the history sidebar, the URL itself is not opened, // Note that for the history sidebar, the URL itself is not opened,
// and Places will show the load-js-data-url-error prompt as an alert // and Places will show the load-js-data-url-error prompt as an alert

Просмотреть файл

@ -69,10 +69,20 @@ function runNextTest() {
// set an empty state & run the next test, or finish // set an empty state & run the next test, or finish
if (tests.length) { if (tests.length) {
// Enumerate windows and close everything but our primary window. We can't
// use waitForFocus() because apparently it's buggy. See bug 599253.
var windowsEnum = Services.wm.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
var currentWindow = windowsEnum.getNext();
if (currentWindow != window) {
currentWindow.close();
}
}
ss.setBrowserState(JSON.stringify({ windows: [{ tabs: [{ url: 'about:blank' }] }] })); ss.setBrowserState(JSON.stringify({ windows: [{ tabs: [{ url: 'about:blank' }] }] }));
let test = tests.shift(); let currentTest = tests.shift();
info("running " + test.name); info("running " + currentTest.name);
executeSoon(test); executeSoon(currentTest);
} }
else { else {
ss.setBrowserState(stateBackup); ss.setBrowserState(stateBackup);

Просмотреть файл

@ -105,7 +105,7 @@
margin-top: -1px; margin-top: -1px;
} }
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox:-moz-lwtheme { #main-window[sizemode="normal"] #titlebar-buttonbox:-moz-lwtheme {
margin-top: -2px; margin-top: -2px;
} }

Просмотреть файл

@ -325,7 +325,7 @@
-moz-appearance: -moz-window-button-box; -moz-appearance: -moz-window-button-box;
} }
#main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox { #main-window[sizemode="maximized"] #titlebar-buttonbox {
-moz-appearance: -moz-window-button-box-maximized; -moz-appearance: -moz-window-button-box-maximized;
} }
@ -339,7 +339,7 @@
-moz-appearance: -moz-window-button-maximize; -moz-appearance: -moz-window-button-maximize;
} }
#main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox > #titlebar-max { #main-window[sizemode="maximized"] #titlebar-max {
-moz-appearance: -moz-window-button-restore; -moz-appearance: -moz-window-button-restore;
} }
@ -1412,10 +1412,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
padding-bottom: 1px; padding-bottom: 1px;
} }
.tabbrowser-tabs:-moz-system-metric(touch-enabled) {
min-height: 7.3mozmm;
}
/* Tabs */ /* Tabs */
.tabbrowser-tab, .tabbrowser-tab,
.tabs-newtab-button { .tabs-newtab-button {
@ -1558,6 +1554,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
.tabs-newtab-button { .tabs-newtab-button {
min-width: 10mozmm; min-width: 10mozmm;
} }
.tab-content {
min-height: -moz-calc(6.8mozmm - 7px); /* subtract borders from the desired height */
}
} }
.tabbrowser-arrowscrollbox > .scrollbutton-up, .tabbrowser-arrowscrollbox > .scrollbutton-up,

Просмотреть файл

@ -37,6 +37,7 @@
# ***** END LICENSE BLOCK ***** # ***** END LICENSE BLOCK *****
import socket import socket
import SocketServer
import time, datetime import time, datetime
import os import os
import re import re
@ -65,7 +66,7 @@ class DeviceManager:
base_prompt = '\$\>' base_prompt = '\$\>'
prompt_sep = '\x00' prompt_sep = '\x00'
prompt_regex = '.*' + base_prompt + prompt_sep prompt_regex = '.*' + base_prompt + prompt_sep
agentErrorRE = re.compile('^##AGENT-ERROR##.*') agentErrorRE = re.compile('^##AGENT-WARNING##.*')
def __init__(self, host, port = 20701): def __init__(self, host, port = 20701):
self.host = host self.host = host
@ -272,6 +273,9 @@ class DeviceManager:
return None return None
def mkDir(self, name): def mkDir(self, name):
if (self.dirExists(name)):
return name
else:
return self.sendCMD(['mkdr ' + name]) return self.sendCMD(['mkdr ' + name])
# make directory structure on the device # make directory structure on the device
@ -306,7 +310,9 @@ class DeviceManager:
match = ".*" + dirname + "$" match = ".*" + dirname + "$"
dirre = re.compile(match) dirre = re.compile(match)
data = self.sendCMD(['cd ' + dirname, 'cwd']) data = self.sendCMD(['cd ' + dirname, 'cwd'])
if (data == None): # Because this is a compound command, cd can fail while cwd can succeed,
# we should check for agent error directly
if (data == None or self.agentErrorRE.match(data) ):
return None return None
retVal = self.stripPrompt(data) retVal = self.stripPrompt(data)
data = retVal.split('\n') data = retVal.split('\n')
@ -549,7 +555,8 @@ class DeviceManager:
# /reftest # /reftest
# /mochitest # /mochitest
def getDeviceRoot(self): def getDeviceRoot(self):
if (not self.deviceRoot): # This caching of deviceRoot is causing issues if things fail
# if (not self.deviceRoot):
data = self.sendCMD(['testroot']) data = self.sendCMD(['testroot'])
if (data == None): if (data == None):
return '/tests' return '/tests'
@ -690,8 +697,8 @@ class DeviceManager:
Application bundle - path to the application bundle on the device Application bundle - path to the application bundle on the device
Destination - destination directory of where application should be Destination - destination directory of where application should be
installed to (optional) installed to (optional)
Returns True or False depending on what we get back Returns None for success, or output if known failure
TODO: we need a real way to know if this works or not TODO: we need a better way to know if this works or not
""" """
def installApp(self, appBundlePath, destPath=None): def installApp(self, appBundlePath, destPath=None):
cmd = 'inst ' + appBundlePath cmd = 'inst ' + appBundlePath
@ -699,9 +706,13 @@ class DeviceManager:
cmd += ' ' + destPath cmd += ' ' + destPath
data = self.sendCMD([cmd]) data = self.sendCMD([cmd])
if (data is None): if (data is None):
return False return None
else:
return True f = re.compile('Failure')
for line in data.split():
if (f.match(line)):
return data
return None
""" """
Uninstalls the named application from device and causes a reboot. Uninstalls the named application from device and causes a reboot.
@ -714,9 +725,53 @@ class DeviceManager:
cmd = 'uninst ' + appName cmd = 'uninst ' + appName
if installPath: if installPath:
cmd += ' ' + installPath cmd += ' ' + installPath
self.sendCMD([cmd]) data = self.sendCMD([cmd])
if (self.debug > 3): print "uninstallAppAndReboot: " + str(data)
return True return True
"""
Updates the application on the device.
Application bundle - path to the application bundle on the device
Process name of application - used to end the process if the applicaiton is
currently running
Destination - Destination directory to where the application should be
installed (optional)
ipAddr - IP address to await a callback ping to let us know that the device has updated
properly - defaults to current IP.
port - port to await a callback ping to let us know that the device has updated properly
defaults to 30000, and counts up from there if it finds a conflict
Returns True if succeeds, False if not
NOTE: We have no real way to know if the device gets updated or not due to the
reboot that the udpate call forces on us. We can't install our own heartbeat
listener here because we run the risk of racing with other heartbeat listeners.
"""
def updateApp(self, appBundlePath, processName=None, destPath=None, ipAddr=None, port=None):
status = None
cmd = 'updt '
if (processName == None):
# Then we pass '' for processName
cmd += "'' " + appBundlePath
else:
cmd += processName + ' ' + appBundlePath
if (destPath):
cmd += " " + destPath
ip, port = self.getCallbackIpAndPort(ipAddr, 30000)
cmd += " %s %s" % (ip, port)
if (self.debug > 3): print "updateApp using command: " + str(cmd)
# Set up our callback server
callbacksvr = callbackServer(ip, port, self.debug)
data = self.sendCMD([cmd])
status = callbacksvr.disconnect()
if (self.debug > 3): print "got status back: " + str(status)
return status
""" """
return the current time on the device return the current time on the device
""" """
@ -726,3 +781,112 @@ class DeviceManager:
return None return None
return self.stripPrompt(data).strip('\n') return self.stripPrompt(data).strip('\n')
"""
Connect the ipaddress and port for a callback ping. Defaults to current IP address
And ports starting at 30000.
NOTE: the detection for current IP address only works on Linux!
"""
def getCallbackIpAndPort(self, aIp, aPort):
ip = aIp
nettools = NetworkTools()
if (ip == None):
ip = nettools.getLanIp()
if (aPort != None):
port = nettools.findOpenPort(ip, aPort)
else:
port = nettools.findOpenPort(ip, 30000)
return ip, port
gCallbackData = ''
class callbackServer():
def __init__(self, ip, port, debuglevel):
self.ip = ip
self.port = port
self.connected = False
self.debug = debuglevel
if (self.debug > 3) : print "Creating server with " + str(ip) + ":" + str(port)
self.server = SocketServer.TCPServer((ip, port), self.myhandler)
self.server_thread = Thread(target=self.server.serve_forever)
self.server_thread.setDaemon(True)
self.server_thread.start()
def disconnect(self, step = 60, timeout = 600):
t = 0
if (self.debug > 3): print "Calling disconnect on callback server"
while t < timeout:
if (gCallbackData):
# Got the data back
if (self.debug > 3): print "Got data back from agent: " + str(gCallbackData)
break
time.sleep(step)
t += step
try:
if (self.debug > 3): print "Shutting down server now"
self.server.shutdown()
except:
print "Unable to shutdown callback server - check for a connection on port: " + str(self.port)
return gCallbackData
class myhandler(SocketServer.BaseRequestHandler):
def handle(self):
global gCallbackData
gCallbackData = self.request.recv(1024)
#print "Callback Handler got data: " + str(gCallbackData)
self.request.send("OK")
class NetworkTools:
def __init__(self):
pass
# Utilities to get the local ip address
def getInterfaceIp(self, ifname):
if os.name != "nt":
import fcntl
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
else:
return None
def getLanIp(self):
ip = socket.gethostbyname(socket.gethostname())
if ip.startswith("127.") and os.name != "nt":
interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
for ifname in interfaces:
try:
ip = self.getInterfaceIp(ifname)
break;
except IOError:
pass
return ip
# Gets an open port starting with the seed by incrementing by 1 each time
def findOpenPort(self, ip, seed):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
connected = False
if isinstance(seed, basestring):
seed = int(seed)
maxportnum = seed + 5000 # We will try at most 5000 ports to find an open one
while not connected:
try:
s.bind((ip, seed))
connected = True
s.close()
except:
if seed > maxportnum:
print "Could not find open port after checking 5000 ports"
raise
seed += 1
except:
print "Socket error trying to find open port"
return seed

Просмотреть файл

@ -42,7 +42,7 @@ import os
import socket import socket
from automation import Automation from automation import Automation
from devicemanager import DeviceManager from devicemanager import DeviceManager, NetworkTools
class RemoteAutomation(Automation): class RemoteAutomation(Automation):
_devicemanager = None _devicemanager = None
@ -99,31 +99,9 @@ class RemoteAutomation(Automation):
# return app, ['--environ:NO_EM_RESTART=1'] + args # return app, ['--environ:NO_EM_RESTART=1'] + args
return app, args return app, args
# Utilities to get the local ip address
def getInterfaceIp(self, ifname):
if os.name != "nt":
import fcntl
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
else:
return None
def getLanIp(self): def getLanIp(self):
ip = socket.gethostbyname(socket.gethostname()) nettools = NetworkTools()
if ip.startswith("127.") and os.name != "nt": return nettools.getLanIp()
interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
for ifname in interfaces:
try:
ip = self.getInterfaceIp(ifname)
break;
except IOError:
pass
return ip
def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = '.'): def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
if stdout == None or stdout == -1: if stdout == None or stdout == -1:
@ -176,4 +154,3 @@ class RemoteAutomation(Automation):
def kill(self): def kill(self):
self.dm.killProcess(self.procName) self.dm.killProcess(self.procName)

Просмотреть файл

@ -1,5 +1,6 @@
{ {
global: global:
NSModule; NSModule;
NSGetModule;
local: *; local: *;
}; };

Просмотреть файл

@ -1,5 +1,6 @@
EXPORTED { EXPORTED {
global: global:
NSModule; NSModule;
NSGetModule;
local: *; local: *;
}; };

Просмотреть файл

@ -0,0 +1,19 @@
{
global:
_malloc_postfork;
_malloc_prefork;
jemalloc_stats;
malloc_usable_size;
posix_memalign;
free;
realloc;
calloc;
malloc;
memalign;
valloc;
__free_hook;
__malloc_hook;
__realloc_hook;
__memalign_hook;
local: *;
};

Просмотреть файл

@ -106,12 +106,6 @@ nsIStringBundle *nsScriptSecurityManager::sStrBundle = nsnull;
JSRuntime *nsScriptSecurityManager::sRuntime = 0; JSRuntime *nsScriptSecurityManager::sRuntime = 0;
PRBool nsScriptSecurityManager::sStrictFileOriginPolicy = PR_TRUE; PRBool nsScriptSecurityManager::sStrictFileOriginPolicy = PR_TRUE;
// Info we need about the JSClasses used by XPConnects wrapped
// natives, to avoid having to QI to nsIXPConnectWrappedNative all the
// time when doing security checks.
static JSEqualityOp sXPCWrappedNativeEqualityOps;
/////////////////////////// ///////////////////////////
// Convenience Functions // // Convenience Functions //
/////////////////////////// ///////////////////////////
@ -2415,10 +2409,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
// Note: jsClass is set before this loop, and also at the // Note: jsClass is set before this loop, and also at the
// *end* of this loop. // *end* of this loop.
// NOTE: These class and equality hook checks better match if (IS_WRAPPER_CLASS(jsClass)) {
// what IS_WRAPPER_CLASS() does in xpconnect!
if (jsClass->ext.equality == js::Valueify(sXPCWrappedNativeEqualityOps)) {
result = sXPConnect->GetPrincipal(aObj, result = sXPConnect->GetPrincipal(aObj,
#ifdef DEBUG #ifdef DEBUG
aAllowShortCircuit aAllowShortCircuit
@ -3423,7 +3414,6 @@ nsresult nsScriptSecurityManager::Init()
JS_SetRuntimeSecurityCallbacks(sRuntime, &securityCallbacks); JS_SetRuntimeSecurityCallbacks(sRuntime, &securityCallbacks);
NS_ASSERTION(!oldcallbacks, "Someone else set security callbacks!"); NS_ASSERTION(!oldcallbacks, "Someone else set security callbacks!");
sXPConnect->GetXPCWrappedNativeJSClassInfo(&sXPCWrappedNativeEqualityOps);
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -43,6 +43,6 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk include $(DEPTH)/config/autoconf.mk
DIRS = mochitest browser DIRS = mochitest
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,54 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# the Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2010
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Justin Lebar <justin.lebar@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = caps/tests/browser
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
browser_bug571289.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

Просмотреть файл

@ -1,24 +0,0 @@
function test() {
// Access an xpcom component from off the main thread.
let threadman = Components.classes["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager);
let thread = threadman.newThread(0);
thread.dispatch(
function() {
// Get another handle on the thread manager, this time from within the
// thread we created.
let threadman2 = Components.classes["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager);
// Now do something with the thread manager. It doesn't really matter
// what we do.
if (threadman2.mainThread == threadman2.currentThread)
ok(false, "Shouldn't be on the main thread.");
}, 1); // dispatch sync
thread.shutdown();
ok(true, "Done!");
}

Просмотреть файл

@ -171,6 +171,7 @@ VPX_ASM_SUFFIX = @VPX_ASM_SUFFIX@
VPX_X86_ASM = @VPX_X86_ASM@ VPX_X86_ASM = @VPX_X86_ASM@
VPX_ARM_ASM = @VPX_ARM_ASM@ VPX_ARM_ASM = @VPX_ARM_ASM@
NS_PRINTING = @NS_PRINTING@ NS_PRINTING = @NS_PRINTING@
MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@
MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@ MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@ MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
MOC= @MOC@ MOC= @MOC@
@ -195,6 +196,7 @@ RM = rm -f
MOZ_UI_LOCALE = @MOZ_UI_LOCALE@ MOZ_UI_LOCALE = @MOZ_UI_LOCALE@
MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS = @MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS@ MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS = @MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS@
MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS = @MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS@
MOZ_COMPONENT_NSPR_LIBS=@MOZ_COMPONENT_NSPR_LIBS@ MOZ_COMPONENT_NSPR_LIBS=@MOZ_COMPONENT_NSPR_LIBS@
MOZ_FIX_LINK_PATHS=@MOZ_FIX_LINK_PATHS@ MOZ_FIX_LINK_PATHS=@MOZ_FIX_LINK_PATHS@

Просмотреть файл

@ -162,6 +162,11 @@ MOZ_WIDGET_SUPPORT_LIBS = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFF
ifdef MOZ_MEMORY ifdef MOZ_MEMORY
ifneq (,$(filter-out WINNT WINCE,$(OS_ARCH))) ifneq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
JEMALLOC_LIBS = $(MKSHLIB_FORCE_ALL) $(call EXPAND_MOZLIBNAME,jemalloc) $(MKSHLIB_UNFORCE_ALL) JEMALLOC_LIBS = $(MKSHLIB_FORCE_ALL) $(call EXPAND_MOZLIBNAME,jemalloc) $(MKSHLIB_UNFORCE_ALL)
# If we are linking jemalloc into a program, we want the jemalloc symbols
# to be exported
ifneq (,$(SIMPLE_PROGRAMS)$(PROGRAM))
JEMALLOC_LIBS += $(MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS)
endif
endif endif
endif endif

Просмотреть файл

@ -301,8 +301,8 @@ if test "$target" = "arm-android-eabi" ; then
STRIP="$android_toolchain"/bin/arm-eabi-strip STRIP="$android_toolchain"/bin/arm-eabi-strip
CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS" CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS"
CFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions -march=armv5te -mthumb-interwork $CFLAGS" CFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions $CFLAGS"
CXXFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions -march=armv5te -mthumb-interwork $CXXFLAGS" CXXFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions $CXXFLAGS"
dnl Add -llog by default, since we use it all over the place. dnl Add -llog by default, since we use it all over the place.
dnl Add --allow-shlib-undefined, because libGLESv2 links to an dnl Add --allow-shlib-undefined, because libGLESv2 links to an
@ -2415,7 +2415,7 @@ ia64*-hpux*)
LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
MOZ_COMPONENT_NSPR_LIBS='$(NSPR_LIBS)' MOZ_COMPONENT_NSPR_LIBS='$(NSPR_LIBS)'
if test $_MSC_VER -ge 1400; then if test $_MSC_VER -ge 1400; then
LDFLAGS="$LDFLAGS -NXCOMPAT" LDFLAGS="$LDFLAGS -LARGEADDRESSAWARE -NXCOMPAT"
dnl For profile-guided optimization dnl For profile-guided optimization
PROFILE_GEN_CFLAGS="-GL" PROFILE_GEN_CFLAGS="-GL"
PROFILE_GEN_LDFLAGS="-LTCG:PGINSTRUMENT" PROFILE_GEN_LDFLAGS="-LTCG:PGINSTRUMENT"
@ -2893,11 +2893,13 @@ esac
AC_SUBST(NO_LD_ARCHIVE_FLAGS) AC_SUBST(NO_LD_ARCHIVE_FLAGS)
dnl ======================================================== dnl ========================================================
dnl = Flags to strip unused symbols from .so components dnl = Flags to strip unused symbols from .so components and
dnl = to export jemalloc symbols when linking a program
dnl ======================================================== dnl ========================================================
case "$target" in case "$target" in
*-linux*|*-kfreebsd*-gnu|*-gnu*) *-linux*|*-kfreebsd*-gnu|*-gnu*)
MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script' MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script'
MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS='-rdynamic -Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/jemalloc-standalone-linkage-version-script'
;; ;;
*-solaris*) *-solaris*)
if test -z "$GNU_CC"; then if test -z "$GNU_CC"; then
@ -4992,6 +4994,7 @@ MOZ_XTF=1
MOZ_XUL=1 MOZ_XUL=1
MOZ_ZIPWRITER=1 MOZ_ZIPWRITER=1
NS_PRINTING=1 NS_PRINTING=1
MOZ_PDF_PRINTING=
MOZ_DISABLE_DOMCRYPTO= MOZ_DISABLE_DOMCRYPTO=
NSS_DISABLE_DBM= NSS_DISABLE_DBM=
NECKO_WIFI=1 NECKO_WIFI=1
@ -5031,7 +5034,6 @@ case "${target}" in
NSS_DISABLE_DBM=1 NSS_DISABLE_DBM=1
USE_ARM_KUSER=1 USE_ARM_KUSER=1
MOZ_INSTALLER= MOZ_INSTALLER=
NS_PRINTING=
NECKO_WIFI= NECKO_WIFI=
MOZ_THUMB2=1 MOZ_THUMB2=1
MOZ_THEME_FASTSTRIPE=1 MOZ_THEME_FASTSTRIPE=1
@ -5187,6 +5189,7 @@ cairo-windows)
NS_PRINTING= NS_PRINTING=
;; ;;
esac esac
MOZ_PDF_PRINTING=1
;; ;;
cairo-gtk2|cairo-gtk2-x11) cairo-gtk2|cairo-gtk2-x11)
@ -5203,6 +5206,7 @@ cairo-gtk2|cairo-gtk2-x11)
TK_CFLAGS='$(MOZ_GTK2_CFLAGS)' TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
TK_LIBS='$(MOZ_GTK2_LIBS)' TK_LIBS='$(MOZ_GTK2_LIBS)'
AC_DEFINE(MOZ_WIDGET_GTK2) AC_DEFINE(MOZ_WIDGET_GTK2)
MOZ_PDF_PRINTING=1
;; ;;
cairo-gtk2-dfb) cairo-gtk2-dfb)
@ -5220,6 +5224,7 @@ cairo-gtk2-dfb)
AC_MSG_WARN([Disabling X when DirectFB is specified.]) AC_MSG_WARN([Disabling X when DirectFB is specified.])
no_x=yes no_x=yes
fi fi
MOZ_PDF_PRINTING=1
;; ;;
cairo-qt) cairo-qt)
@ -5237,6 +5242,7 @@ cairo-qt)
TK_CFLAGS='$(MOZ_QT_CFLAGS)' TK_CFLAGS='$(MOZ_QT_CFLAGS)'
TK_LIBS='$(MOZ_QT_LIBS)' TK_LIBS='$(MOZ_QT_LIBS)'
AC_DEFINE(MOZ_WIDGET_QT) AC_DEFINE(MOZ_WIDGET_QT)
MOZ_PDF_PRINTING=1
;; ;;
cairo-beos) cairo-beos)
@ -5251,6 +5257,7 @@ cairo-os2)
USE_FC_FREETYPE=1 USE_FC_FREETYPE=1
TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)' TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
TK_LIBS='$(MOZ_CAIRO_LIBS)' TK_LIBS='$(MOZ_CAIRO_LIBS)'
MOZ_PDF_PRINTING=1
;; ;;
cairo-cocoa) cairo-cocoa)
@ -5271,11 +5278,20 @@ cairo-cocoa)
cairo-android) cairo-android)
AC_DEFINE(MOZ_WIDGET_ANDROID) AC_DEFINE(MOZ_WIDGET_ANDROID)
MOZ_WIDGET_TOOLKIT=android MOZ_WIDGET_TOOLKIT=android
TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
TK_LIBS='$(MOZ_CAIRO_LIBS)'
MOZ_WEBGL=1 MOZ_WEBGL=1
MOZ_PDF_PRINTING=1
;; ;;
esac esac
AC_SUBST(MOZ_PDF_PRINTING)
if test "$MOZ_PDF_PRINTING"; then
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
AC_DEFINE(MOZ_PDF_PRINTING)
fi
if test "$MOZ_ENABLE_XREMOTE"; then if test "$MOZ_ENABLE_XREMOTE"; then
AC_DEFINE(MOZ_ENABLE_XREMOTE) AC_DEFINE(MOZ_ENABLE_XREMOTE)
fi fi
@ -7098,6 +7114,16 @@ if test -n "$MOZ_THUMB2"; then
AC_MSG_ERROR([--enable-thumb2 is not supported for non-ARM CPU architectures]) AC_MSG_ERROR([--enable-thumb2 is not supported for non-ARM CPU architectures])
;; ;;
esac esac
else
case "$target_cpu" in
arm*)
if test "$GNU_CC"; then
CFLAGS="$CFLAGS -march=armv5te -mthumb-interwork -Wa, -march=armv5te -Wa, -mthumb-interwork"
CXXFLAGS="$CXXFLAGS -march=armv5te -mthumb-interwork -Wa, -march=armv5te -Wa, -mthumb-interwork"
ASFLAGS="$ASFLAGS -march=armv5te -mthumb-interwork"
fi
;;
esac
fi fi
AC_SUBST(MOZ_THUMB2) AC_SUBST(MOZ_THUMB2)
@ -8499,7 +8525,6 @@ if test "$MOZ_TREE_CAIRO"; then
XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1" XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1" XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1" PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1" FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
MOZ_ENABLE_CAIRO_FT=1 MOZ_ENABLE_CAIRO_FT=1
CAIRO_FT_CFLAGS="$FT2_CFLAGS" CAIRO_FT_CFLAGS="$FT2_CFLAGS"
@ -8538,12 +8563,10 @@ if test "$MOZ_TREE_CAIRO"; then
AC_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1) AC_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1)
fi fi
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
fi fi
if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
OS2_SURFACE_FEATURE="#define CAIRO_HAS_OS2_SURFACE 1" OS2_SURFACE_FEATURE="#define CAIRO_HAS_OS2_SURFACE 1"
FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1" FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
MOZ_ENABLE_CAIRO_FT=1 MOZ_ENABLE_CAIRO_FT=1
CAIRO_FT_CFLAGS="-I${MZFTCFGFT2}/include" CAIRO_FT_CFLAGS="-I${MZFTCFGFT2}/include"
CAIRO_FT_LIBS="-L${MZFTCFGFT2}/lib -lmozft -lmzfntcfg" CAIRO_FT_LIBS="-L${MZFTCFGFT2}/lib -lmozft -lmzfntcfg"
@ -8924,6 +8947,7 @@ AC_SUBST(PKG_SKIP_STRIP)
AC_SUBST(USE_ELF_DYNSTR_GC) AC_SUBST(USE_ELF_DYNSTR_GC)
AC_SUBST(INCREMENTAL_LINKER) AC_SUBST(INCREMENTAL_LINKER)
AC_SUBST(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS) AC_SUBST(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
AC_SUBST(MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS)
AC_SUBST(MOZ_COMPONENT_NSPR_LIBS) AC_SUBST(MOZ_COMPONENT_NSPR_LIBS)
AC_SUBST(MOZ_FIX_LINK_PATHS) AC_SUBST(MOZ_FIX_LINK_PATHS)

Просмотреть файл

@ -0,0 +1 @@
<script async src="data:">0</script>

Просмотреть файл

@ -74,3 +74,4 @@ load 582601.html
load 575462.svg load 575462.svg
load 595606-1.html load 595606-1.html
load 595606-2.html load 595606-2.html
load 606729-1.html

Просмотреть файл

@ -42,6 +42,8 @@
#include "nsAString.h" #include "nsAString.h"
#include "nsMargin.h" #include "nsMargin.h"
class nsIInterfaceRequestor;
// {3682DD99-8560-44f4-9B8F-CCCE9D7B96FB} // {3682DD99-8560-44f4-9B8F-CCCE9D7B96FB}
#define NS_ICONTENTUTILS_IID \ #define NS_ICONTENTUTILS_IID \
{ 0x3682dd99, 0x8560, 0x44f4, \ { 0x3682dd99, 0x8560, 0x44f4, \
@ -71,4 +73,20 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentUtils, NS_ICONTENTUTILS_IID) NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentUtils, NS_ICONTENTUTILS_IID)
// {60083ad4-f7ed-488b-a706-bacb378fe1a5}
#define NS_ICONTENTUTILS2_IID \
{ 0x60083ad4, 0xf7ed, 0x488b, \
{ 0xa7, 0x06, 0xba, 0xcb, 0x37, 0x8f, 0xe1, 0xa5 } }
class nsIContentUtils2 : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTUTILS2_IID)
NS_DECL_ISUPPORTS
virtual nsIInterfaceRequestor* GetSameOriginChecker();
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentUtils2, NS_ICONTENTUTILS2_IID)
#endif /* nsIContentUtils_h__ */ #endif /* nsIContentUtils_h__ */

Просмотреть файл

@ -70,6 +70,7 @@ public:
mFrozen(PR_FALSE), mFrozen(PR_FALSE),
mDefer(PR_FALSE), mDefer(PR_FALSE),
mAsync(PR_FALSE), mAsync(PR_FALSE),
mExternal(PR_FALSE),
mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT ? mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT ?
mozilla::dom::NOT_FROM_PARSER : aFromParser), mozilla::dom::NOT_FROM_PARSER : aFromParser),
// Fragment parser-created scripts (if executable) // Fragment parser-created scripts (if executable)
@ -126,6 +127,15 @@ public:
return mAsync; return mAsync;
} }
/**
* Is the script an external script?
*/
PRBool GetScriptExternal()
{
NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
return mExternal;
}
/** /**
* Returns how the element was created. * Returns how the element was created.
*/ */
@ -249,6 +259,12 @@ protected:
*/ */
PRPackedBool mAsync; PRPackedBool mAsync;
/**
* The effective externalness. A script can be external with mUri being null
* if the src attribute contained an invalid URL string.
*/
PRPackedBool mExternal;
/** /**
* Whether this element was parser-created. * Whether this element was parser-created.
*/ */

Просмотреть файл

@ -1,106 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Netscape Communications.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vidur Apparao <vidur@netscape.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDocument;
interface nsIScriptElement;
interface nsIScriptLoaderObserver;
[scriptable, uuid(339a4eb5-dac6-4034-8c43-f4f8c645ce57)]
interface nsIScriptLoader : nsISupports {
/**
* Initialize loader with a document. The container of this document
* will be used for getting script evaluation information, including
* the context in which to do the evaluation. The loader maintains a
* strong reference to the document.
*
* @param aDocument The document to use as the basis for script
* processing.
*/
void init(in nsIDocument aDocument);
/**
* The loader maintains a strong reference to the document with
* which it is initialized. This call forces the reference to
* be dropped.
*/
void dropDocumentReference();
/**
* Add an observer for all scripts loaded through this loader.
*
* @param aObserver observer for all script processing.
*/
void addObserver(in nsIScriptLoaderObserver aObserver);
/**
* Remove an observer.
*
* @param aObserver observer to be removed
*/
void removeObserver(in nsIScriptLoaderObserver aObserver);
/**
* Process a script element. This will include both loading the
* source of the element if it is not inline and evaluating
* the script itself.
*
* @param aElement The element representing the script to be loaded and
* evaluated.
* @param aObserver An observer for this script load only
*
*/
void processScriptElement(in nsIScriptElement aElement,
in nsIScriptLoaderObserver aObserver);
/**
* Gets the currently executing script. This is useful if you want to
* generate a unique key based on the currently executing script.
*/
nsIScriptElement getCurrentScript();
/**
* Whether the loader is enabled or not.
* When disabled, processing of new script elements is disabled.
* Any call to processScriptElement() will fail with a return code of
* NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable
* currently loading or executing scripts.
*/
attribute boolean enabled;
};

Просмотреть файл

@ -592,6 +592,7 @@ nsContentUtils::InitializeEventTable() {
{ nsGkAtoms::onpageshow, NS_PAGE_SHOW, EventNameType_HTML, NS_EVENT }, { nsGkAtoms::onpageshow, NS_PAGE_SHOW, EventNameType_HTML, NS_EVENT },
{ nsGkAtoms::onpagehide, NS_PAGE_HIDE, EventNameType_HTML, NS_EVENT }, { nsGkAtoms::onpagehide, NS_PAGE_HIDE, EventNameType_HTML, NS_EVENT },
{ nsGkAtoms::onMozBeforeResize, NS_BEFORERESIZE_EVENT, EventNameType_None, NS_EVENT },
{ nsGkAtoms::onresize, NS_RESIZE_EVENT, { nsGkAtoms::onresize, NS_RESIZE_EVENT,
(EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT }, (EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
{ nsGkAtoms::onscroll, NS_SCROLL_EVENT, { nsGkAtoms::onscroll, NS_SCROLL_EVENT,
@ -5536,6 +5537,11 @@ nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
return NS_OK; return NS_OK;
} }
JSObject *wrapper = xpc_GetCachedSlimWrapper(cache, scope, vp);
if (wrapper) {
return NS_OK;
}
NS_ENSURE_TRUE(sXPConnect && sThreadJSContextStack, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(sXPConnect && sThreadJSContextStack, NS_ERROR_UNEXPECTED);
// Keep sXPConnect and sThreadJSContextStack alive. If we're on the main // Keep sXPConnect and sThreadJSContextStack alive. If we're on the main
@ -6489,3 +6495,11 @@ nsIContentUtils::FindInternalContentViewer(const char* aType,
return NULL; return NULL;
} }
NS_IMPL_ISUPPORTS1(nsIContentUtils2, nsIContentUtils2)
nsIInterfaceRequestor*
nsIContentUtils2::GetSameOriginChecker()
{
return nsContentUtils::GetSameOriginChecker();
}

Просмотреть файл

@ -709,6 +709,7 @@ GK_ATOM(onpopupshown, "onpopupshown")
GK_ATOM(onreadystatechange, "onreadystatechange") GK_ATOM(onreadystatechange, "onreadystatechange")
GK_ATOM(onRequest, "onRequest") GK_ATOM(onRequest, "onRequest")
GK_ATOM(onreset, "onreset") GK_ATOM(onreset, "onreset")
GK_ATOM(onMozBeforeResize, "onMozBeforeResize")
GK_ATOM(onresize, "onresize") GK_ATOM(onresize, "onresize")
GK_ATOM(onscroll, "onscroll") GK_ATOM(onscroll, "onscroll")
GK_ATOM(onselect, "onselect") GK_ATOM(onselect, "onselect")

Просмотреть файл

@ -546,10 +546,13 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Step 9. in the HTML5 spec // Step 9. in the HTML5 spec
nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
nsRefPtr<nsScriptLoadRequest> request; nsRefPtr<nsScriptLoadRequest> request;
if (scriptURI) { if (aElement->GetScriptExternal()) {
// external script // external script
nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
if (!scriptURI) {
return NS_ERROR_NOT_AVAILABLE;
}
nsTArray<PreloadInfo>::index_type i = nsTArray<PreloadInfo>::index_type i =
mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator()); mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator());
if (i != nsTArray<PreloadInfo>::NoIndex) { if (i != nsTArray<PreloadInfo>::NoIndex) {

Просмотреть файл

@ -442,6 +442,7 @@ _TEST_FILES2 = \
file_bug604660-5.xml \ file_bug604660-5.xml \
file_bug604660-6.xsl \ file_bug604660-6.xsl \
test_bug605982.html \ test_bug605982.html \
test_bug606729.html \
test_treewalker_nextsibling.xml \ test_treewalker_nextsibling.xml \
$(NULL) $(NULL)

Просмотреть файл

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=606729
-->
<head>
<title>Test for Bug 606729</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=606729">Mozilla Bug 606729</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script
src="data:"
onerror="ok(false, 'Script with src=data: should not fire onerror.');"
onload="ok(false, 'Script with src=data: should not fire onload.');"
>
ok(false, "Script with src=data: should not run textContent.");
</script>
<script
src="bogus:"
onerror="ok(false, 'Script with src=bogus: should not fire onerror.');"
onload="ok(false, 'Script with src=bogus: should not fire onload.');"
>
ok(false, "Script with src=bogus: should not run textContent.");
</script>
<script class="testbody" type="text/javascript">
ok(true, "Obligatory succeeding test assertion.");
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -50,6 +50,7 @@
class nsHTMLCanvasElement; class nsHTMLCanvasElement;
class gfxContext; class gfxContext;
class gfxASurface; class gfxASurface;
class nsIPropertyBag;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@ -115,6 +116,14 @@ public:
// Redraw the dirty rectangle of this canvas. // Redraw the dirty rectangle of this canvas.
NS_IMETHOD Redraw(const gfxRect &dirty) = 0; NS_IMETHOD Redraw(const gfxRect &dirty) = 0;
// Passes a generic nsIPropertyBag options argument, along with the
// previous one, if any. Optional.
NS_IMETHOD SetContextOptions(nsIPropertyBag *aNewOptions) { return NS_OK; }
//
// shmem support
//
// If this context can be set to use Mozilla's Shmem segments as its backing // If this context can be set to use Mozilla's Shmem segments as its backing
// store, this will set it to that state. Note that if you have drawn // store, this will set it to that state. Note that if you have drawn
// anything into this canvas before changing the shmem state, it will be // anything into this canvas before changing the shmem state, it will be

Просмотреть файл

@ -82,14 +82,14 @@ helper_isFloat32Array(JSObject *obj) {
* BufferData_array (int, js::TypedArray *, int) * BufferData_array (int, js::TypedArray *, int)
*/ */
static JSBool static JSBool
nsICanvasRenderingContextWebGL_BufferData(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_BufferData(JSContext *cx, uintN argc, jsval *vp)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -149,14 +149,14 @@ nsICanvasRenderingContextWebGL_BufferData(JSContext *cx, uintN argc, jsval *vp)
* BufferSubData_array (int, int, js::TypedArray *) * BufferSubData_array (int, int, js::TypedArray *)
*/ */
static JSBool static JSBool
nsICanvasRenderingContextWebGL_BufferSubData(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_BufferSubData(JSContext *cx, uintN argc, jsval *vp)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -215,7 +215,7 @@ nsICanvasRenderingContextWebGL_BufferSubData(JSContext *cx, uintN argc, jsval *v
* ReadPixels(int, int, int, int, uint, uint, ArrayBufferView) * ReadPixels(int, int, int, int, uint, uint, ArrayBufferView)
*/ */
static JSBool static JSBool
nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
@ -224,7 +224,7 @@ nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
nsresult rv; nsresult rv;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -278,7 +278,7 @@ nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
* TexImage2D(uint, int, uint, uint, uint, ImageData) * TexImage2D(uint, int, uint, uint, uint, ImageData)
*/ */
static JSBool static JSBool
nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
@ -287,7 +287,7 @@ nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
nsresult rv; nsresult rv;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -396,7 +396,7 @@ nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
* TexSubImage2D(uint, int, int, int, uint, uint, ImageData) * TexSubImage2D(uint, int, int, int, uint, uint, ImageData)
*/ */
static JSBool static JSBool
nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
@ -405,7 +405,7 @@ nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *v
nsresult rv; nsresult rv;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -504,7 +504,7 @@ nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *v
/* NOTE: There is a TN version of this below, update it as well */ /* NOTE: There is a TN version of this below, update it as well */
static inline JSBool static inline JSBool
helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(JSContext *cx, uintN argc, jsval *vp, int nElements) helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(JSContext *cx, uintN argc, jsval *vp, int nElements)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
@ -513,7 +513,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(JSContext *cx, uintN argc, js
nsresult rv; nsresult rv;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -578,7 +578,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(JSContext *cx, uintN argc, js
/* NOTE: There is a TN version of this below, update it as well */ /* NOTE: There is a TN version of this below, update it as well */
static inline JSBool static inline JSBool
helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements) helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
@ -587,7 +587,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(JSContext *cx, uintN argc, js
nsresult rv; nsresult rv;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -652,7 +652,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(JSContext *cx, uintN argc, js
/* NOTE: There is a TN version of this below, update it as well */ /* NOTE: There is a TN version of this below, update it as well */
static inline JSBool static inline JSBool
helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements) helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
@ -661,7 +661,7 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(JSContext *cx, uintN ar
nsresult rv; nsresult rv;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -727,7 +727,7 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(JSContext *cx, uintN ar
} }
static inline JSBool static inline JSBool
helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements) helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp);
@ -736,7 +736,7 @@ helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(JSContext *cx, uintN arg
nsresult rv; nsresult rv;
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
js::AutoValueRooter tvr(cx); js::AutoValueRooter tvr(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
@ -796,104 +796,104 @@ helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(JSContext *cx, uintN arg
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_Uniform1iv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_Uniform1iv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 1); return helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(cx, argc, vp, 1);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_Uniform2iv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_Uniform2iv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 2); return helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(cx, argc, vp, 2);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_Uniform3iv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_Uniform3iv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 3); return helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(cx, argc, vp, 3);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_Uniform4iv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_Uniform4iv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 4); return helper_nsIDOMWebGLRenderingContext_Uniform_x_iv(cx, argc, vp, 4);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_Uniform1fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_Uniform1fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 1); return helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(cx, argc, vp, 1);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_Uniform2fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_Uniform2fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 2); return helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(cx, argc, vp, 2);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_Uniform3fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_Uniform3fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 3); return helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(cx, argc, vp, 3);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_Uniform4fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_Uniform4fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 4); return helper_nsIDOMWebGLRenderingContext_Uniform_x_fv(cx, argc, vp, 4);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_UniformMatrix2fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_UniformMatrix2fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 2); return helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(cx, argc, vp, 2);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_UniformMatrix3fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_UniformMatrix3fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 3); return helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(cx, argc, vp, 3);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_UniformMatrix4fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_UniformMatrix4fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 4); return helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(cx, argc, vp, 4);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_VertexAttrib1fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_VertexAttrib1fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 1); return helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(cx, argc, vp, 1);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_VertexAttrib2fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_VertexAttrib2fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 2); return helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(cx, argc, vp, 2);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_VertexAttrib3fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_VertexAttrib3fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 3); return helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(cx, argc, vp, 3);
} }
static JSBool static JSBool
nsICanvasRenderingContextWebGL_VertexAttrib4fv(JSContext *cx, uintN argc, jsval *vp) nsIDOMWebGLRenderingContext_VertexAttrib4fv(JSContext *cx, uintN argc, jsval *vp)
{ {
return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 4); return helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(cx, argc, vp, 4);
} }
#ifdef JS_TRACER #ifdef JS_TRACER
static inline void FASTCALL static inline void FASTCALL
helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj, helper_nsIDOMWebGLRenderingContext_Uniform_x_iv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj,
JSObject *arg, int nElements) JSObject *arg, int nElements)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
xpc_qsArgValArray<3> vp(cx); xpc_qsArgValArray<3> vp(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
@ -902,7 +902,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *o
} }
if (!arg) { if (!arg) {
xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNiv"); xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsIDOMWebGLRenderingContext", "uniformNiv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
} }
@ -932,7 +932,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *o
*obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj); *obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj);
wa = js::TypedArray::fromJSObject(nobj); wa = js::TypedArray::fromJSObject(nobj);
} else { } else {
xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNiv"); xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsIDOMWebGLRenderingContext", "uniformNiv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
return; return;
} }
@ -950,18 +950,18 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *o
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNiv"); xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsIDOMWebGLRenderingContext", "uniformNiv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
} }
} }
static inline void FASTCALL static inline void FASTCALL
helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj, helper_nsIDOMWebGLRenderingContext_Uniform_x_fv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj,
JSObject *arg, int nElements) JSObject *arg, int nElements)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
xpc_qsArgValArray<3> vp(cx); xpc_qsArgValArray<3> vp(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
@ -970,7 +970,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *o
} }
if (!arg) { if (!arg) {
xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNfv"); xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsIDOMWebGLRenderingContext", "uniformNfv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
} }
@ -1000,7 +1000,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *o
*obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj); *obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj);
wa = js::TypedArray::fromJSObject(nobj); wa = js::TypedArray::fromJSObject(nobj);
} else { } else {
xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNfv"); xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsIDOMWebGLRenderingContext", "uniformNfv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
return; return;
} }
@ -1018,7 +1018,7 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *o
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNfv"); xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsIDOMWebGLRenderingContext", "uniformNfv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
} }
@ -1026,12 +1026,12 @@ helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *o
} }
static inline void FASTCALL static inline void FASTCALL
helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj, helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj,
JSBool transpose, JSObject *arg, int nElements) JSBool transpose, JSObject *arg, int nElements)
{ {
XPC_QS_ASSERT_CONTEXT_OK(cx); XPC_QS_ASSERT_CONTEXT_OK(cx);
nsICanvasRenderingContextWebGL *self; nsIDOMWebGLRenderingContext *self;
xpc_qsSelfRef selfref; xpc_qsSelfRef selfref;
xpc_qsArgValArray<4> vp(cx); xpc_qsArgValArray<4> vp(cx);
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
@ -1040,7 +1040,7 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObj
} }
if (!arg) { if (!arg) {
xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv"); xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsIDOMWebGLRenderingContext", "uniformMatrixNfv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
} }
@ -1070,7 +1070,7 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObj
*obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj); *obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj);
wa = js::TypedArray::fromJSObject(nobj); wa = js::TypedArray::fromJSObject(nobj);
} else { } else {
xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv"); xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsIDOMWebGLRenderingContext", "uniformMatrixNfv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
return; return;
} }
@ -1085,7 +1085,7 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObj
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv"); xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsIDOMWebGLRenderingContext", "uniformMatrixNfv");
js_SetTraceableNativeFailed(cx); js_SetTraceableNativeFailed(cx);
} }
} }
@ -1093,133 +1093,133 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObj
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_Uniform1iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) nsIDOMWebGLRenderingContext_Uniform1iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 1); helper_nsIDOMWebGLRenderingContext_Uniform_x_iv_tn(cx, obj, location, arg, 1);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1iv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_Uniform1iv,
(4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (4, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_Uniform1iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) nsIDOMWebGLRenderingContext_Uniform2iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 2); helper_nsIDOMWebGLRenderingContext_Uniform_x_iv_tn(cx, obj, location, arg, 2);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2iv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_Uniform2iv,
(4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (4, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_Uniform2iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) nsIDOMWebGLRenderingContext_Uniform3iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 3); helper_nsIDOMWebGLRenderingContext_Uniform_x_iv_tn(cx, obj, location, arg, 3);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3iv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_Uniform3iv,
(4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (4, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_Uniform3iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) nsIDOMWebGLRenderingContext_Uniform4iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 4); helper_nsIDOMWebGLRenderingContext_Uniform_x_iv_tn(cx, obj, location, arg, 4);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4iv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_Uniform4iv,
(4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (4, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_Uniform4iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) nsIDOMWebGLRenderingContext_Uniform1fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 1); helper_nsIDOMWebGLRenderingContext_Uniform_x_fv_tn(cx, obj, location, arg, 1);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1fv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_Uniform1fv,
(4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (4, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_Uniform1fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) nsIDOMWebGLRenderingContext_Uniform2fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 2); helper_nsIDOMWebGLRenderingContext_Uniform_x_fv_tn(cx, obj, location, arg, 2);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2fv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_Uniform2fv,
(4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (4, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_Uniform2fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) nsIDOMWebGLRenderingContext_Uniform3fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 3); helper_nsIDOMWebGLRenderingContext_Uniform_x_fv_tn(cx, obj, location, arg, 3);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3fv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_Uniform3fv,
(4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (4, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_Uniform3fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) nsIDOMWebGLRenderingContext_Uniform4fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 4); helper_nsIDOMWebGLRenderingContext_Uniform_x_fv_tn(cx, obj, location, arg, 4);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4fv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_Uniform4fv,
(4, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (4, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_Uniform4fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg) nsIDOMWebGLRenderingContext_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 2); helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 2);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix2fv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_UniformMatrix2fv,
(5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (5, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_UniformMatrix2fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg) nsIDOMWebGLRenderingContext_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 3); helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 3);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix3fv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_UniformMatrix3fv,
(5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (5, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_UniformMatrix3fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
// FIXME This should return void, not uint32 // FIXME This should return void, not uint32
// (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798) // (waiting for https://bugzilla.mozilla.org/show_bug.cgi?id=572798)
static uint32 FASTCALL static uint32 FASTCALL
nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg) nsIDOMWebGLRenderingContext_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
{ {
helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 4); helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 4);
return 0; return 0;
} }
JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix4fv, JS_DEFINE_TRCINFO_1(nsIDOMWebGLRenderingContext_UniformMatrix4fv,
(5, (static, UINT32_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY))) (5, (static, UINT32_FAIL, nsIDOMWebGLRenderingContext_UniformMatrix4fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACCSET_STORE_ANY)))
#endif /* JS_TRACER */ #endif /* JS_TRACER */

Просмотреть файл

@ -48,6 +48,11 @@
#include "nsDOMError.h" #include "nsDOMError.h"
#include "nsIGfxInfo.h" #include "nsIGfxInfo.h"
#include "nsIPropertyBag.h"
#include "nsIVariant.h"
#include "imgIEncoder.h"
#include "gfxContext.h" #include "gfxContext.h"
#include "gfxPattern.h" #include "gfxPattern.h"
#include "gfxUtils.h" #include "gfxUtils.h"
@ -66,12 +71,12 @@ using namespace mozilla;
using namespace mozilla::gl; using namespace mozilla::gl;
using namespace mozilla::layers; using namespace mozilla::layers;
nsresult NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult); nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
nsresult nsresult
NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult) NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
{ {
nsICanvasRenderingContextWebGL* ctx = new WebGLContext(); nsIDOMWebGLRenderingContext* ctx = new WebGLContext();
if (!ctx) if (!ctx)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -88,6 +93,7 @@ WebGLContext::WebGLContext()
mInvalidated = PR_FALSE; mInvalidated = PR_FALSE;
mResetLayer = PR_TRUE; mResetLayer = PR_TRUE;
mVerbose = PR_FALSE; mVerbose = PR_FALSE;
mOptionsFrozen = PR_FALSE;
mActiveTexture = 0; mActiveTexture = 0;
mSynthesizedGLError = LOCAL_GL_NO_ERROR; mSynthesizedGLError = LOCAL_GL_NO_ERROR;
@ -266,6 +272,67 @@ WebGLContext::SetCanvasElement(nsHTMLCanvasElement* aParentCanvas)
return NS_OK; return NS_OK;
} }
static bool
GetBoolFromPropertyBag(nsIPropertyBag *bag, const char *propName, bool *boolResult)
{
nsCOMPtr<nsIVariant> vv;
PRBool bv;
nsresult rv = bag->GetProperty(NS_ConvertASCIItoUTF16(propName), getter_AddRefs(vv));
if (NS_FAILED(rv) || !vv)
return false;
rv = vv->GetAsBool(&bv);
if (NS_FAILED(rv))
return false;
*boolResult = bv ? true : false;
return true;
}
NS_IMETHODIMP
WebGLContext::SetContextOptions(nsIPropertyBag *aOptions)
{
if (!aOptions)
return NS_OK;
WebGLContextOptions newOpts;
// defaults are: yes: depth, alpha, premultipliedAlpha; no: stencil
if (!GetBoolFromPropertyBag(aOptions, "stencil", &newOpts.stencil))
newOpts.stencil = false;
if (!GetBoolFromPropertyBag(aOptions, "depth", &newOpts.depth))
newOpts.depth = true;
if (!GetBoolFromPropertyBag(aOptions, "alpha", &newOpts.alpha))
newOpts.alpha = true;
if (!GetBoolFromPropertyBag(aOptions, "premultipliedAlpha", &newOpts.premultipliedAlpha))
newOpts.premultipliedAlpha = true;
GetBoolFromPropertyBag(aOptions, "antialiasHint", &newOpts.antialiasHint);
// enforce that if stencil is specified, we also give back depth
newOpts.depth |= newOpts.stencil;
LogMessage("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d\n",
newOpts.antialiasHint ? 1 : 0,
newOpts.stencil ? 1 : 0,
newOpts.depth ? 1 : 0,
newOpts.alpha ? 1 : 0,
newOpts.premultipliedAlpha ? 1 : 0);
if (mOptionsFrozen && newOpts != mOptions) {
// Error if the options are already frozen, and the ones that were asked for
// aren't the same as what they were originally.
return NS_ERROR_FAILURE;
}
mOptions = newOpts;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
WebGLContext::SetDimensions(PRInt32 width, PRInt32 height) WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
{ {
@ -300,8 +367,26 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
DestroyResourcesAndContext(); DestroyResourcesAndContext();
gl::ContextFormat format(gl::ContextFormat::BasicRGBA32); gl::ContextFormat format(gl::ContextFormat::BasicRGBA32);
format.depth = 16; if (mOptions.depth) {
format.minDepth = 1; format.depth = 24;
format.minDepth = 16;
}
if (mOptions.stencil) {
format.stencil = 8;
format.minStencil = 8;
}
if (!mOptions.alpha) {
// Select 565; we won't/shouldn't hit this on the desktop,
// but let mobile know we're ok with it.
format.red = 5;
format.green = 6;
format.blue = 5;
format.alpha = 0;
format.minAlpha = 0;
}
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID); nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE); NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
@ -421,6 +506,7 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
mResetLayer = PR_TRUE; mResetLayer = PR_TRUE;
mOptionsFrozen = PR_TRUE;
// increment the generation number // increment the generation number
++mGeneration; ++mGeneration;
@ -482,17 +568,20 @@ WebGLContext::GetInputStream(const char* aMimeType,
const PRUnichar* aEncoderOptions, const PRUnichar* aEncoderOptions,
nsIInputStream **aStream) nsIInputStream **aStream)
{ {
NS_ASSERTION(gl, "GetInputStream on invalid context?");
if (!gl)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
// XXX fix this nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(gfxIntSize(mWidth, mHeight),
#if 0 gfxASurface::ImageFormatARGB32);
if (!mGLPbuffer || if (surf->CairoStatus() != 0)
!mGLPbuffer->ThebesSurface())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
gl->ReadPixelsIntoImageSurface(0, 0, mWidth, mHeight, surf);
nsresult rv; nsresult rv;
const char encoderPrefix[] = "@mozilla.org/image/encoder;2?type="; const char encoderPrefix[] = "@mozilla.org/image/encoder;2?type=";
nsAutoArrayPtr<char> conid(new (std::nothrow) char[strlen(encoderPrefix) + strlen(aMimeType) + 1]); nsAutoArrayPtr<char> conid(new char[strlen(encoderPrefix) + strlen(aMimeType) + 1]);
if (!conid) if (!conid)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -504,45 +593,15 @@ WebGLContext::GetInputStream(const char* aMimeType,
if (!encoder) if (!encoder)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
nsAutoArrayPtr<PRUint8> imageBuffer(new (std::nothrow) PRUint8[mWidth * mHeight * 4]); rv = encoder->InitFromData(surf->Data(),
if (!imageBuffer) mWidth * mHeight * 4,
return NS_ERROR_OUT_OF_MEMORY; mWidth, mHeight,
surf->Stride(),
nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(imageBuffer.get(),
gfxIntSize(mWidth, mHeight),
mWidth * 4,
gfxASurface::ImageFormatARGB32);
if (!imgsurf || imgsurf->CairoStatus())
return NS_ERROR_FAILURE;
nsRefPtr<gfxContext> ctx = new gfxContext(imgsurf);
if (!ctx || ctx->HasError())
return NS_ERROR_FAILURE;
nsRefPtr<gfxASurface> surf = mGLPbuffer->ThebesSurface();
nsRefPtr<gfxPattern> pat = CanvasGLThebes::CreatePattern(surf);
gfxMatrix m;
m.Translate(gfxPoint(0.0, mGLPbuffer->Height()));
m.Scale(1.0, -1.0);
pat->SetMatrix(m);
// XXX I don't want to use PixelSnapped here, but layout doesn't guarantee
// pixel alignment for this stuff!
ctx->NewPath();
ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->Fill();
rv = encoder->InitFromData(imageBuffer.get(),
mWidth * mHeight * 4, mWidth, mHeight, mWidth * 4,
imgIEncoder::INPUT_FORMAT_HOSTARGB, imgIEncoder::INPUT_FORMAT_HOSTARGB,
nsDependentString(aEncoderOptions)); nsDependentString(aEncoderOptions));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(encoder, aStream); return CallQueryInterface(encoder, aStream);
#endif
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -589,7 +648,7 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
} }
data.mSize = nsIntSize(mWidth, mHeight); data.mSize = nsIntSize(mWidth, mHeight);
data.mGLBufferIsPremultiplied = PR_FALSE; data.mGLBufferIsPremultiplied = mOptions.premultipliedAlpha ? PR_TRUE : PR_FALSE;
canvasLayer->Initialize(data); canvasLayer->Initialize(data);
PRUint32 flags = gl->CreationFormat().alpha == 0 ? Layer::CONTENT_OPAQUE : 0; PRUint32 flags = gl->CreationFormat().alpha == 0 ? Layer::CONTENT_OPAQUE : 0;
@ -602,12 +661,46 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
return canvasLayer.forget().get(); return canvasLayer.forget().get();
} }
NS_IMETHODIMP
WebGLContext::GetContextAttributes(jsval *aResult)
{
JSContext *cx = nsContentUtils::GetCurrentJSContext();
if (!cx)
return NS_ERROR_FAILURE;
JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
if (!obj)
return NS_ERROR_FAILURE;
*aResult = OBJECT_TO_JSVAL(obj);
gl::ContextFormat cf = gl->ActualFormat();
if (!JS_DefineProperty(cx, obj, "alpha", cf.alpha > 0 ? JSVAL_TRUE : JSVAL_FALSE,
NULL, NULL, JSPROP_ENUMERATE) ||
!JS_DefineProperty(cx, obj, "depth", cf.depth > 0 ? JSVAL_TRUE : JSVAL_FALSE,
NULL, NULL, JSPROP_ENUMERATE) ||
!JS_DefineProperty(cx, obj, "stencil", cf.stencil > 0 ? JSVAL_TRUE : JSVAL_FALSE,
NULL, NULL, JSPROP_ENUMERATE) ||
!JS_DefineProperty(cx, obj, "antialias", JSVAL_FALSE,
NULL, NULL, JSPROP_ENUMERATE) ||
!JS_DefineProperty(cx, obj, "premultipliedAlpha",
mOptions.premultipliedAlpha ? JSVAL_TRUE : JSVAL_FALSE,
NULL, NULL, JSPROP_ENUMERATE))
{
*aResult = JSVAL_VOID;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
// //
// XPCOM goop // XPCOM goop
// //
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(WebGLContext, nsICanvasRenderingContextWebGL) NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(WebGLContext, nsIDOMWebGLRenderingContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(WebGLContext, nsICanvasRenderingContextWebGL) NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(WebGLContext, nsIDOMWebGLRenderingContext)
NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLContext) NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLContext) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLContext)
@ -620,10 +713,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
DOMCI_DATA(CanvasRenderingContextWebGL, WebGLContext) DOMCI_DATA(CanvasRenderingContextWebGL, WebGLContext)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextWebGL) NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal) NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasRenderingContextWebGL) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWebGLRenderingContext)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CanvasRenderingContextWebGL) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CanvasRenderingContextWebGL)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END

Просмотреть файл

@ -50,7 +50,7 @@
#include "nsIDocShell.h" #include "nsIDocShell.h"
#include "nsICanvasRenderingContextWebGL.h" #include "nsIDOMWebGLRenderingContext.h"
#include "nsICanvasRenderingContextInternal.h" #include "nsICanvasRenderingContextInternal.h"
#include "nsHTMLCanvasElement.h" #include "nsHTMLCanvasElement.h"
#include "nsWeakReference.h" #include "nsWeakReference.h"
@ -67,6 +67,7 @@
#define CONTEXT_LOST_WEBGL 0x9242 #define CONTEXT_LOST_WEBGL 0x9242
class nsIDocShell; class nsIDocShell;
class nsIPropertyBag;
namespace mozilla { namespace mozilla {
@ -235,8 +236,10 @@ private:
class WebGLBuffer; class WebGLBuffer;
struct WebGLVertexAttribData { struct WebGLVertexAttribData {
// note that these initial values are what GL initializes vertex attribs to
WebGLVertexAttribData() WebGLVertexAttribData()
: buf(0), stride(0), size(0), byteOffset(0), type(0), enabled(PR_FALSE), normalized(PR_FALSE) : buf(0), stride(0), size(4), byteOffset(0),
type(LOCAL_GL_FLOAT), enabled(PR_FALSE), normalized(PR_FALSE)
{ } { }
WebGLObjectRefPtr<WebGLBuffer> buf; WebGLObjectRefPtr<WebGLBuffer> buf;
@ -277,8 +280,41 @@ struct WebGLVertexAttribData {
} }
}; };
struct WebGLContextOptions {
// these are defaults
WebGLContextOptions()
: alpha(true), depth(true), stencil(false),
premultipliedAlpha(true), antialiasHint(false)
{ }
bool operator==(const WebGLContextOptions& other) const {
return
alpha == other.alpha &&
depth == other.depth &&
stencil == other.stencil &&
premultipliedAlpha == other.premultipliedAlpha &&
antialiasHint == other.antialiasHint;
}
bool operator!=(const WebGLContextOptions& other) const {
return
alpha != other.alpha ||
depth != other.depth ||
stencil != other.stencil ||
premultipliedAlpha != other.premultipliedAlpha ||
antialiasHint != other.antialiasHint;
}
bool alpha;
bool depth;
bool stencil;
bool premultipliedAlpha;
bool antialiasHint;
};
class WebGLContext : class WebGLContext :
public nsICanvasRenderingContextWebGL, public nsIDOMWebGLRenderingContext,
public nsICanvasRenderingContextInternal, public nsICanvasRenderingContextInternal,
public nsSupportsWeakReference public nsSupportsWeakReference
{ {
@ -288,9 +324,9 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebGLContext, nsICanvasRenderingContextWebGL) NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebGLContext, nsIDOMWebGLRenderingContext)
NS_DECL_NSICANVASRENDERINGCONTEXTWEBGL NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
// nsICanvasRenderingContextInternal // nsICanvasRenderingContextInternal
NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas); NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
@ -305,6 +341,8 @@ public:
nsIInputStream **aStream); nsIInputStream **aStream);
NS_IMETHOD GetThebesSurface(gfxASurface **surface); NS_IMETHOD GetThebesSurface(gfxASurface **surface);
NS_IMETHOD SetIsOpaque(PRBool b) { return NS_OK; }; NS_IMETHOD SetIsOpaque(PRBool b) { return NS_OK; };
NS_IMETHOD SetContextOptions(nsIPropertyBag *aOptions);
NS_IMETHOD SetIsIPC(PRBool b) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHOD SetIsIPC(PRBool b) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD Redraw(const gfxRect&) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHOD Redraw(const gfxRect&) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD Swap(mozilla::ipc::Shmem& aBack, NS_IMETHOD Swap(mozilla::ipc::Shmem& aBack,
@ -360,9 +398,12 @@ protected:
PRInt32 mWidth, mHeight; PRInt32 mWidth, mHeight;
CheckedUint32 mGeneration; CheckedUint32 mGeneration;
WebGLContextOptions mOptions;
PRPackedBool mInvalidated; PRPackedBool mInvalidated;
PRPackedBool mResetLayer; PRPackedBool mResetLayer;
PRPackedBool mVerbose; PRPackedBool mVerbose;
PRPackedBool mOptionsFrozen;
WebGLuint mActiveTexture; WebGLuint mActiveTexture;
WebGLenum mSynthesizedGLError; WebGLenum mSynthesizedGLError;
@ -729,13 +770,14 @@ public:
NS_DECL_NSIWEBGLTEXTURE NS_DECL_NSIWEBGLTEXTURE
protected: protected:
friend class WebGLContext;
friend class WebGLFramebuffer;
PRBool mDeleted; PRBool mDeleted;
WebGLuint mName; WebGLuint mName;
//////////////////////////////////////////////////////////////////////////////////////////////////// // we store information about the various images that are part of
/////// everything below that point is only used for the texture completeness/npot business // this texture (cubemap faces, mipmap levels)
/////// (sections 3.7.10 and 3.8.2 in GL ES 2.0.24 spec)
////////////////////////////////////////////////////////////////////////////////////////////////////
struct ImageInfo { struct ImageInfo {
ImageInfo() : mWidth(0), mHeight(0), mFormat(0), mType(0), mIsDefined(PR_FALSE) {} ImageInfo() : mWidth(0), mHeight(0), mFormat(0), mType(0), mIsDefined(PR_FALSE) {}
@ -1211,21 +1253,21 @@ public:
return mAttachedShaders.RemoveElement(shader); return mAttachedShaders.RemoveElement(shader);
} }
PRBool HasBothShaderTypesAttached() { PRBool HasAttachedShaderOfType(GLenum shaderType) {
PRBool haveVertex = PR_FALSE;
PRBool haveFrag = PR_FALSE;
for (PRUint32 i = 0; i < mAttachedShaders.Length(); ++i) { for (PRUint32 i = 0; i < mAttachedShaders.Length(); ++i) {
if (mAttachedShaders[i]->ShaderType() == LOCAL_GL_FRAGMENT_SHADER) if (mAttachedShaders[i]->ShaderType() == shaderType) {
haveFrag = PR_TRUE;
else if (mAttachedShaders[i]->ShaderType() == LOCAL_GL_VERTEX_SHADER)
haveVertex = PR_TRUE;
if (haveFrag && haveVertex)
return PR_TRUE; return PR_TRUE;
} }
}
return PR_FALSE; return PR_FALSE;
} }
PRBool HasBothShaderTypesAttached() {
return
HasAttachedShaderOfType(LOCAL_GL_VERTEX_SHADER) &&
HasAttachedShaderOfType(LOCAL_GL_FRAGMENT_SHADER);
}
PRBool NextGeneration() PRBool NextGeneration()
{ {
if (!(mGeneration+1).valid()) if (!(mGeneration+1).valid())
@ -1328,6 +1370,7 @@ public:
WebGLFramebuffer(WebGLContext *context, WebGLuint name) : WebGLFramebuffer(WebGLContext *context, WebGLuint name) :
WebGLContextBoundObject(context), WebGLContextBoundObject(context),
mName(name), mDeleted(PR_FALSE), mName(name), mDeleted(PR_FALSE),
mColorAttachment0HasAlpha(PR_FALSE),
mHasDepthAttachment(PR_FALSE), mHasDepthAttachment(PR_FALSE),
mHasStencilAttachment(PR_FALSE), mHasStencilAttachment(PR_FALSE),
mHasDepthStencilAttachment(PR_FALSE) mHasDepthStencilAttachment(PR_FALSE)
@ -1342,6 +1385,8 @@ public:
PRBool Deleted() { return mDeleted; } PRBool Deleted() { return mDeleted; }
WebGLuint GLName() { return mName; } WebGLuint GLName() { return mName; }
PRBool ColorAttachment0HasAlpha() { return mColorAttachment0HasAlpha; }
nsresult FramebufferRenderbuffer(WebGLenum target, nsresult FramebufferRenderbuffer(WebGLenum target,
WebGLenum attachment, WebGLenum attachment,
WebGLenum rbtarget, WebGLenum rbtarget,
@ -1405,15 +1450,20 @@ public:
{ {
return mContext->ErrorInvalidOperation(badAttachmentFormatMsg); return mContext->ErrorInvalidOperation(badAttachmentFormatMsg);
} }
// ReadPixels needs alpha and size information, but only
// for COLOR_ATTACHMENT0
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0) {
setDimensions(wrb);
mColorAttachment0HasAlpha = InternalFormatHasAlpha(wrb->mInternalFormat);
} else {
mColorAttachment0HasAlpha = PR_FALSE;
}
} }
mColorRenderbufferAttachment = wrb; mColorRenderbufferAttachment = wrb;
break; break;
} }
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0)
setDimensions(wrb);
mContext->MakeContextCurrent(); mContext->MakeContextCurrent();
mContext->gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername); mContext->gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername);
@ -1460,13 +1510,25 @@ public:
{ {
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment); return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment);
} }
// nothing to do for color buffers. all textures have a color-renderable format.
break; // keep data for readPixels, function only uses COLOR_ATTACHMENT0
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0) {
setDimensions(wtex);
if (wtex) {
const WebGLTexture::ImageInfo& ia = wtex->ImageInfoAt
(level, textarget == LOCAL_GL_TEXTURE_2D
? 0
: textarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X);
mColorAttachment0HasAlpha = InternalFormatHasAlpha(ia.mFormat);
} else {
mColorAttachment0HasAlpha = PR_FALSE;
}
} }
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0 // nothing else to do for color buffers. all textures have a color-renderable format.
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0) break;
setDimensions(wtex); }
mContext->MakeContextCurrent(); mContext->MakeContextCurrent();
mContext->gl->fFramebufferTexture2D(target, attachment, textarget, texturename, level); mContext->gl->fFramebufferTexture2D(target, attachment, textarget, texturename, level);
@ -1501,6 +1563,14 @@ public:
int(mHasDepthStencilAttachment) > 1; int(mHasDepthStencilAttachment) > 1;
} }
static PRBool InternalFormatHasAlpha(WebGLenum aInternalFormat) {
return
aInternalFormat == LOCAL_GL_RGBA ||
aInternalFormat == LOCAL_GL_ALPHA ||
aInternalFormat == LOCAL_GL_RGBA4 ||
aInternalFormat == LOCAL_GL_RGB5_A1;
}
protected: protected:
// protected because WebGLContext should only call InitializeRenderbuffers // protected because WebGLContext should only call InitializeRenderbuffers
@ -1605,7 +1675,8 @@ protected:
} }
WebGLuint mName; WebGLuint mName;
PRBool mDeleted; PRPackedBool mDeleted;
PRPackedBool mColorAttachment0HasAlpha;
// we only store pointers to attached renderbuffers, not to attached textures, because // we only store pointers to attached renderbuffers, not to attached textures, because
// we will only need to initialize renderbuffers. Textures are already initialized. // we will only need to initialize renderbuffers. Textures are already initialized.

Просмотреть файл

@ -123,18 +123,17 @@ WebGLProgram::GetUniformLocationObject(GLint glLocation)
return loc.forget(); return loc.forget();
} }
static PRBool
InternalFormatHasAlpha(WebGLenum aInternalFormat) {
return aInternalFormat == LOCAL_GL_RGBA4 ||
aInternalFormat == LOCAL_GL_RGB5_A1;
}
// //
// WebGL API // WebGL API
// //
/* void present (); */
NS_IMETHODIMP
WebGLContext::Present()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void GlActiveTexture (in GLenum texture); */ /* void GlActiveTexture (in GLenum texture); */
NS_IMETHODIMP NS_IMETHODIMP
WebGLContext::ActiveTexture(WebGLenum texture) WebGLContext::ActiveTexture(WebGLenum texture)
@ -163,6 +162,12 @@ WebGLContext::AttachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj)
!GetConcreteObjectAndGLName("attachShader: shader", shobj, &shader, &shadername)) !GetConcreteObjectAndGLName("attachShader: shader", shobj, &shader, &shadername))
return NS_OK; return NS_OK;
// Per GLSL ES 2.0, we can only have one of each type of shader
// attached. This renders the next test somewhat moot, but we'll
// leave it for when we support more than one shader of each type.
if (program->HasAttachedShaderOfType(shader->ShaderType()))
return ErrorInvalidOperation("AttachShader: only one of each type of shader may be attached to a program");
if (!program->AttachShader(shader)) if (!program->AttachShader(shader))
return ErrorInvalidOperation("AttachShader: shader is already attached"); return ErrorInvalidOperation("AttachShader: shader is already attached");
@ -540,6 +545,11 @@ WebGLContext::Clear(PRUint32 mask)
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers()) if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return NS_OK; return NS_OK;
PRUint32 m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
if (mask != m) {
return ErrorInvalidValue("clear: invalid mask bits");
}
gl->fClear(mask); gl->fClear(mask);
Invalidate(); Invalidate();
@ -1433,7 +1443,6 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
case LOCAL_GL_CULL_FACE_MODE: case LOCAL_GL_CULL_FACE_MODE:
case LOCAL_GL_FRONT_FACE: case LOCAL_GL_FRONT_FACE:
case LOCAL_GL_ACTIVE_TEXTURE: case LOCAL_GL_ACTIVE_TEXTURE:
case LOCAL_GL_DEPTH_CLEAR_VALUE:
case LOCAL_GL_STENCIL_CLEAR_VALUE: case LOCAL_GL_STENCIL_CLEAR_VALUE:
case LOCAL_GL_STENCIL_FUNC: case LOCAL_GL_STENCIL_FUNC:
case LOCAL_GL_STENCIL_REF: case LOCAL_GL_STENCIL_REF:
@ -1521,6 +1530,7 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
break; break;
// float // float
case LOCAL_GL_DEPTH_CLEAR_VALUE:
case LOCAL_GL_LINE_WIDTH: case LOCAL_GL_LINE_WIDTH:
case LOCAL_GL_POLYGON_OFFSET_FACTOR: case LOCAL_GL_POLYGON_OFFSET_FACTOR:
case LOCAL_GL_POLYGON_OFFSET_UNITS: case LOCAL_GL_POLYGON_OFFSET_UNITS:
@ -2470,30 +2480,31 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
WebGLsizei boundHeight = mBoundFramebuffer ? mBoundFramebuffer->height() : mHeight; WebGLsizei boundHeight = mBoundFramebuffer ? mBoundFramebuffer->height() : mHeight;
PRUint32 size = 0; PRUint32 size = 0;
bool badFormat = false, badType = false;
switch (format) { switch (format) {
case LOCAL_GL_ALPHA:
size = 1;
break;
case LOCAL_GL_RGB:
size = 3;
break;
case LOCAL_GL_RGBA: case LOCAL_GL_RGBA:
size = 4; size = 4;
break; break;
default: default:
return ErrorInvalidEnumInfo("readPixels: format", format); badFormat = true;
break;
} }
switch (type) { switch (type) {
// case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
// case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
// case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
case LOCAL_GL_UNSIGNED_BYTE: case LOCAL_GL_UNSIGNED_BYTE:
break; break;
default: default:
return ErrorInvalidEnumInfo("ReadPixels: type", type); badType = true;
break;
} }
if (badFormat && badType)
return ErrorInvalidOperation("readPixels: bad format and type");
if (badFormat)
return ErrorInvalidEnumInfo("readPixels: format", format);
if (badType)
return ErrorInvalidEnumInfo("ReadPixels: type", type);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * size; CheckedUint32 checked_plainRowSize = CheckedUint32(width) * size;
PRUint32 packAlignment = mPixelStorePackAlignment; PRUint32 packAlignment = mPixelStorePackAlignment;
@ -2579,6 +2590,51 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
} }
delete [] subrect_data; delete [] subrect_data;
} }
// if we're reading alpha, we may need to do fixup
if (format == LOCAL_GL_ALPHA ||
format == LOCAL_GL_RGBA)
{
PRBool needAlphaFixup;
if (mBoundFramebuffer) {
needAlphaFixup = !mBoundFramebuffer->ColorAttachment0HasAlpha();
} else {
needAlphaFixup = gl->ActualFormat().alpha == 0;
}
if (needAlphaFixup) {
if (format == LOCAL_GL_ALPHA && type == LOCAL_GL_UNSIGNED_BYTE) {
// this is easy; it's an 0xff memset per row
PRUint8 *row = (PRUint8*)data;
for (GLint j = 0; j < height; ++j) {
memset(row, 0xff, checked_plainRowSize.value());
row += checked_alignedRowSize.value();
}
} else if (format == LOCAL_GL_RGBA && type == LOCAL_GL_UNSIGNED_BYTE) {
// this is harder, we need to just set the alpha byte here
PRUint8 *row = (PRUint8*)data;
for (GLint j = 0; j < height; ++j) {
PRUint8 *rowp = row;
#ifdef IS_LITTLE_ENDIAN
// offset to get the alpha byte; we're always going to
// move by 4 bytes
rowp += 3;
#endif
PRUint8 *endrowp = rowp + 4 * width;
while (rowp != endrowp) {
*rowp = 0xff;
rowp += 4;
}
row += checked_alignedRowSize.value();
}
} else {
NS_WARNING("Unhandled case, how'd we get here?");
return NS_ERROR_FAILURE;
}
}
}
return NS_OK; return NS_OK;
} }
@ -3767,7 +3823,7 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
PRUint32 bytesNeeded = checked_neededByteLength.value(); PRUint32 bytesNeeded = checked_neededByteLength.value();
if (byteLength < bytesNeeded) if (byteLength < bytesNeeded)
return ErrorInvalidValue("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength); return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
WebGLTexture *tex = activeBoundTextureForTarget(target); WebGLTexture *tex = activeBoundTextureForTarget(target);
@ -3880,129 +3936,6 @@ WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level,
srcFormat, PR_TRUE); srcFormat, PR_TRUE);
} }
#if 0
// ImageData getImageData (in float x, in float y, in float width, in float height);
NS_IMETHODIMP
WebGLContext::GetImageData(PRUint32 x, PRUint32 y, PRUint32 w, PRUint32 h)
{
// disabled due to win32 linkage issues with thebes symbols and NS_RELEASE
return NS_ERROR_FAILURE;
#if 0
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
if (js.argc != 4) return NS_ERROR_INVALID_ARG;
if (!mGLPbuffer ||
!mGLPbuffer->ThebesSurface())
return NS_ERROR_FAILURE;
if (!mCanvasElement)
return NS_ERROR_FAILURE;
if (HTMLCanvasElement()->IsWriteOnly() && !IsCallerTrustedForRead()) {
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_DOM_SECURITY_ERR;
}
JSContext *ctx = js.ctx;
if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
return NS_ERROR_DOM_SYNTAX_ERR;
nsAutoArrayPtr<PRUint8> surfaceData (new (std::nothrow) PRUint8[w * h * 4]);
int surfaceDataStride = w*4;
int surfaceDataOffset = 0;
if (!surfaceData)
return NS_ERROR_OUT_OF_MEMORY;
nsRefPtr<gfxImageSurface> tmpsurf = new gfxImageSurface(surfaceData,
gfxIntSize(w, h),
w * 4,
gfxASurface::ImageFormatARGB32);
if (!tmpsurf || tmpsurf->CairoStatus())
return NS_ERROR_FAILURE;
nsRefPtr<gfxContext> tmpctx = new gfxContext(tmpsurf);
if (!tmpctx || tmpctx->HasError())
return NS_ERROR_FAILURE;
nsRefPtr<gfxASurface> surf = mGLPbuffer->ThebesSurface();
nsRefPtr<gfxPattern> pat = CanvasGLThebes::CreatePattern(surf);
gfxMatrix m;
m.Translate(gfxPoint(x, mGLPbuffer->Height()-y));
m.Scale(1.0, -1.0);
pat->SetMatrix(m);
// XXX I don't want to use PixelSnapped here, but layout doesn't guarantee
// pixel alignment for this stuff!
tmpctx->NewPath();
tmpctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, w, h), pat);
tmpctx->SetOperator(gfxContext::OPERATOR_SOURCE);
tmpctx->Fill();
tmpctx = nsnull;
tmpsurf = nsnull;
PRUint32 len = w * h * 4;
if (len > (((PRUint32)0xfff00000)/sizeof(jsval)))
return NS_ERROR_INVALID_ARG;
nsAutoArrayPtr<jsval> jsvector(new (std::nothrow) jsval[w * h * 4]);
if (!jsvector)
return NS_ERROR_OUT_OF_MEMORY;
jsval *dest = jsvector.get();
PRUint8 *row;
for (PRUint32 j = 0; j < h; j++) {
row = surfaceData + surfaceDataOffset + (surfaceDataStride * j);
for (PRUint32 i = 0; i < w; i++) {
// XXX Is there some useful swizzle MMX we can use here?
// I guess we have to INT_TO_JSVAL still
#ifdef IS_LITTLE_ENDIAN
PRUint8 b = *row++;
PRUint8 g = *row++;
PRUint8 r = *row++;
PRUint8 a = *row++;
#else
PRUint8 a = *row++;
PRUint8 r = *row++;
PRUint8 g = *row++;
PRUint8 b = *row++;
#endif
// Convert to non-premultiplied color
if (a != 0) {
r = (r * 255) / a;
g = (g * 255) / a;
b = (b * 255) / a;
}
*dest++ = INT_TO_JSVAL(r);
*dest++ = INT_TO_JSVAL(g);
*dest++ = INT_TO_JSVAL(b);
*dest++ = INT_TO_JSVAL(a);
}
}
JSObject *dataArray = JS_NewArrayObject(ctx, w*h*4, jsvector);
if (!dataArray)
return NS_ERROR_OUT_OF_MEMORY;
JSObjectHelper retobj(&js);
retobj.DefineProperty("width", w);
retobj.DefineProperty("height", h);
retobj.DefineProperty("data", dataArray);
js.SetRetVal(retobj);
return NS_OK;
#endif
}
#endif
PRBool PRBool
BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize) BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize)
{ {

Просмотреть файл

@ -36,12 +36,12 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "nsICanvasRenderingContextWebGL.h" #include "nsIDOMWebGLRenderingContext.h"
#include "nsDOMClassInfoID.h" #include "nsDOMClassInfoID.h"
#define DUMMY(func,rtype) nsresult func (rtype ** aResult) { return NS_ERROR_FAILURE; } #define DUMMY(func,rtype) nsresult func (rtype ** aResult) { return NS_ERROR_FAILURE; }
DUMMY(NS_NewCanvasRenderingContextWebGL, nsICanvasRenderingContextWebGL) DUMMY(NS_NewCanvasRenderingContextWebGL, nsIDOMWebGLRenderingContext)
DOMCI_DATA(CanvasRenderingContextWebGL, void) DOMCI_DATA(CanvasRenderingContextWebGL, void)
DOMCI_DATA(WebGLBuffer, void) DOMCI_DATA(WebGLBuffer, void)

Просмотреть файл

@ -1,6 +1,6 @@
This is a local copy of the WebGL conformance suite. This is a local copy of the WebGL conformance suite.
SVN revision: 11955 SVN revision: 12905
The canonical location for this testsuite is: The canonical location for this testsuite is:

Просмотреть файл

@ -7,7 +7,6 @@ buffer-data-array-buffer.html
canvas-test.html canvas-test.html
constants.html constants.html
context-attributes-alpha-depth-stencil-antialias.html context-attributes-alpha-depth-stencil-antialias.html
context-attributes.html
context-type-test.html context-type-test.html
copy-tex-image-and-sub-image-2d.html copy-tex-image-and-sub-image-2d.html
draw-arrays-out-of-bounds.html draw-arrays-out-of-bounds.html
@ -17,11 +16,13 @@ framebuffer-object-attachment.html
framebuffer-test.html framebuffer-test.html
get-active-test.html get-active-test.html
gl-bind-attrib-location-test.html gl-bind-attrib-location-test.html
gl-clear.html
gl-drawelements.html gl-drawelements.html
gl-enable-enum-test.html gl-enable-enum-test.html
gl-enable-vertex-attrib.html gl-enable-vertex-attrib.html
gl-enum-tests.html gl-enum-tests.html
gl-get-active-attribute.html gl-get-active-attribute.html
gl-get-active-uniform.html
gl-get-calls.html gl-get-calls.html
gl-getstring.html gl-getstring.html
gl-object-get-calls.html gl-object-get-calls.html
@ -45,10 +46,13 @@ index-validation-with-resized-buffer.html
index-validation.html index-validation.html
invalid-UTF-16.html invalid-UTF-16.html
invalid-passed-params.html invalid-passed-params.html
is-object.html
methods.html methods.html
more-than-65536-points.html more-than-65536-points.html
null-object-behaviour.html null-object-behaviour.html
null-uniform-location.html null-uniform-location.html
object-deletion-behaviour.html
origin-clean-conformance.html
point-size.html point-size.html
program-test.html program-test.html
read-pixels-pack-alignment.html read-pixels-pack-alignment.html
@ -72,7 +76,9 @@ texture-formats-test.html
texture-npot.html texture-npot.html
texture-transparent-pixels-initialized.html texture-transparent-pixels-initialized.html
triangle.html triangle.html
#uniform-location.html type-conversion-test.html
uniform-location.html
uniform-samplers-test.html uniform-samplers-test.html
uninitialized-test.html uninitialized-test.html
viewport-unchanged-upon-resize.html viewport-unchanged-upon-resize.html
webgl-specific.html

Просмотреть файл

@ -1,82 +0,0 @@
array-buffer-crash.html
array-buffer-view-crash.html
array-unit-tests.html
bad-arguments-test.html
buffer-bind-test.html
buffer-data-array-buffer.html
canvas-test.html
constants.html
context-attributes-alpha-depth-stencil-antialias.html
context-attributes.html
context-type-test.html
copy-tex-image-and-sub-image-2d.html
draw-arrays-out-of-bounds.html
draw-elements-out-of-bounds.html
error-reporting.html
framebuffer-object-attachment.html
framebuffer-test.html
get-active-test.html
gl-bind-attrib-location-test.html
gl-clear.html
gl-drawelements.html
gl-enable-enum-test.html
gl-enable-vertex-attrib.html
gl-enum-tests.html
gl-get-active-attribute.html
gl-get-active-uniform.html
gl-get-calls.html
gl-getstring.html
gl-object-get-calls.html
gl-pixelstorei.html
gl-scissor-test.html
gl-shader-test.html
gl-teximage.html
gl-uniform-arrays.html
gl-uniform-bool.html
gl-uniformmatrix4fv.html
gl-unknown-uniform.html
gl-vertex-attrib.html
gl-vertexattribpointer.html
glsl-2types-of-textures-on-same-unit.html
glsl-conformance.html
incorrect-context-object-behaviour.html
index-validation-copies-indices.html
index-validation-crash-with-buffer-sub-data.html
index-validation-verifies-too-many-indices.html
index-validation-with-resized-buffer.html
index-validation.html
invalid-UTF-16.html
invalid-passed-params.html
methods.html
more-than-65536-points.html
null-object-behaviour.html
null-uniform-location.html
object-deletion-behaviour.html
origin-clean-conformance.html
point-size.html
program-test.html
read-pixels-pack-alignment.html
read-pixels-test.html
renderbuffer-initialization.html
resource-sharing-test.html
tex-image-and-sub-image-2d-with-array-buffer-view.html
tex-image-and-sub-image-2d-with-image-data.html
tex-image-and-sub-image-2d-with-image.html
tex-image-and-sub-image-2d-with-video.html
tex-image-and-uniform-binding-bugs.html
tex-image-with-format-and-type.html
tex-image-with-invalid-data.html
tex-input-validation.html
tex-sub-image-2d.html
texparameter-test.html
texture-active-bind-2.html
texture-active-bind.html
texture-complete.html
texture-formats-test.html
texture-npot.html
texture-transparent-pixels-initialized.html
triangle.html
uniform-location.html
uniform-samplers-test.html
uninitialized-test.html
viewport-unchanged-upon-resize.html

Просмотреть файл

@ -438,6 +438,15 @@ function testConstructionWithUnalignedOffset(type, name, elementSizeInBytes) {
} }
} }
function testConstructionWithUnalignedLength(type, name, elementSizeInBytes) {
if (elementSizeInBytes > 1) {
shouldThrowIndexSizeErr(function() {
var buffer = new ArrayBuffer(elementSizeInBytes + 1);
var array = new type(buffer, 0);
}, "Construction of " + name + " with unaligned length");
}
}
function testConstructionOfHugeArray(type, name, sz) { function testConstructionOfHugeArray(type, name, sz) {
if (sz == 1) if (sz == 1)
return; return;
@ -671,6 +680,7 @@ function runTests() {
testConstructionWithOutOfRangeValues(type, name); testConstructionWithOutOfRangeValues(type, name);
testConstructionWithNegativeOutOfRangeValues(type, name); testConstructionWithNegativeOutOfRangeValues(type, name);
testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes); testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes);
testConstructionWithUnalignedLength(type, name, testCase.elementSizeInBytes);
testConstructionOfHugeArray(type, name, testCase.elementSizeInBytes); testConstructionOfHugeArray(type, name, testCase.elementSizeInBytes);
testConstructionWithBothArrayBufferAndLength(type, name, testCase.elementSizeInBytes); testConstructionWithBothArrayBufferAndLength(type, name, testCase.elementSizeInBytes);
testSlicingWithOutOfRangeValues(type, name, testCase.elementSizeInBytes); testSlicingWithOutOfRangeValues(type, name, testCase.elementSizeInBytes);

Просмотреть файл

@ -79,7 +79,6 @@ for (var i = 0; i < arguments.length; ++i) {
argument = arguments[i].value; argument = arguments[i].value;
func("context.compileShader(argument)"); func("context.compileShader(argument)");
func("context.linkProgram(argument)"); func("context.linkProgram(argument)");
func("context.attachShader(argument)");
func("context.attachShader(program, argument)"); func("context.attachShader(program, argument)");
func("context.attachShader(argument, shader)"); func("context.attachShader(argument, shader)");
func("context.detachShader(program, argument)"); func("context.detachShader(program, argument)");

Просмотреть файл

@ -33,6 +33,10 @@ glErrorShouldBe(gl, gl.INVALID_OPERATION);
gl.bindBuffer(gl.ARRAY_BUFFER, buf); gl.bindBuffer(gl.ARRAY_BUFFER, buf);
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
// This should not crash, but the selection of the overload is ambiguous per Web IDL.
gl.bufferData(gl.ARRAY_BUFFER, null, gl.STATIC_DRAW);
gl.getError();
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW); gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
@ -41,6 +45,9 @@ array = new ArrayBuffer(64);
gl.bufferSubData(gl.ARRAY_BUFFER, 10, array); gl.bufferSubData(gl.ARRAY_BUFFER, 10, array);
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
gl.bufferSubData(gl.ARRAY_BUFFER, 10, null);
glErrorShouldBe(gl, gl.NO_ERROR);
successfullyParsed = true; successfullyParsed = true;
</script> </script>

Просмотреть файл

@ -375,10 +375,6 @@ VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A,
VERTEX_ATTRIB_ARRAY_POINTER : 0x8645, VERTEX_ATTRIB_ARRAY_POINTER : 0x8645,
VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F, VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F,
/* Read Format */
IMPLEMENTATION_COLOR_READ_TYPE : 0x8B9A,
IMPLEMENTATION_COLOR_READ_FORMAT : 0x8B9B,
/* Shader Source */ /* Shader Source */
COMPILE_STATUS : 0x8B81, COMPILE_STATUS : 0x8B81,
INFO_LOG_LENGTH : 0x8B84, INFO_LOG_LENGTH : 0x8B84,
@ -403,6 +399,7 @@ RGB565 : 0x8D62,
DEPTH_COMPONENT16 : 0x81A5, DEPTH_COMPONENT16 : 0x81A5,
STENCIL_INDEX : 0x1901, STENCIL_INDEX : 0x1901,
STENCIL_INDEX8 : 0x8D48, STENCIL_INDEX8 : 0x8D48,
DEPTH_STENCIL : 0x84F9,
RENDERBUFFER_WIDTH : 0x8D42, RENDERBUFFER_WIDTH : 0x8D42,
RENDERBUFFER_HEIGHT : 0x8D43, RENDERBUFFER_HEIGHT : 0x8D43,
@ -422,6 +419,7 @@ FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3,
COLOR_ATTACHMENT0 : 0x8CE0, COLOR_ATTACHMENT0 : 0x8CE0,
DEPTH_ATTACHMENT : 0x8D00, DEPTH_ATTACHMENT : 0x8D00,
STENCIL_ATTACHMENT : 0x8D20, STENCIL_ATTACHMENT : 0x8D20,
DEPTH_STENCIL_ATTACHMENT : 0x821A,
NONE : 0, NONE : 0,
@ -435,7 +433,14 @@ FRAMEBUFFER_BINDING : 0x8CA6,
RENDERBUFFER_BINDING : 0x8CA7, RENDERBUFFER_BINDING : 0x8CA7,
MAX_RENDERBUFFER_SIZE : 0x84E8, MAX_RENDERBUFFER_SIZE : 0x84E8,
INVALID_FRAMEBUFFER_OPERATION : 0x0506 INVALID_FRAMEBUFFER_OPERATION : 0x0506,
/* WebGL-specific enums */
UNPACK_FLIP_Y_WEBGL : 0x9240,
UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241,
CONTEXT_LOST_WEBGL : 0x9242,
UNPACK_COLORSPACE_CONVERSION_WEBGL : 0x9243,
BROWSER_DEFAULT_WEBGL : 0x9244
}; };
function assertProperty(v, p) { function assertProperty(v, p) {

Просмотреть файл

@ -54,66 +54,14 @@ function init()
function getWebGL(canvasName, contextAttribs, clearColor, clearDepth, clearStencil) function getWebGL(canvasName, contextAttribs, clearColor, clearDepth, clearStencil)
{ {
var canvas = document.getElementById(canvasName); var context = initWebGL(canvasName, "vshader", "fshader", ["pos", "colorIn"], clearColor, clearDepth, contextAttribs);
var gl = canvas.getContext("experimental-webgl", contextAttribs); if (context) {
if (!gl) { context.clearStencil(clearStencil);
alert("No WebGL context found"); context.enable(context.STENCIL_TEST);
return null; context.disable(context.BLEND);
context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT | context.STENCIL_BUFFER_BIT);
} }
var actualContextAttribs = gl.getContextAttributes(); return context;
// Add a console
gl.console = ("console" in window) ? window.console : { log: function() { } };
// create our shaders
var vertexShader = loadShader(gl, "vshader");
var fragmentShader = loadShader(gl, "fshader");
if (!vertexShader || !fragmentShader)
return null;
// Create the program object
gl.program = gl.createProgram();
if (!gl.program)
return null;
// Attach our two shaders to the program
gl.attachShader(gl.program, vertexShader);
gl.attachShader(gl.program, fragmentShader);
// Bind attributes
var attribs = [ "pos", "colorIn" ];
for (var i in attribs)
gl.bindAttribLocation(gl.program, i, attribs[i]);
// Link the program
gl.linkProgram(gl.program);
// Check the link status
var linked = gl.getProgramParameter(gl.program, gl.LINK_STATUS);
if (!linked) {
// something went wrong with the link
var error = gl.getProgramInfoLog (gl.program);
gl.console.log("Error in program linking:"+error);
gl.deleteProgram(gl.program);
gl.deleteProgram(fragmentShader);
gl.deleteProgram(vertexShader);
return null;
}
gl.useProgram(gl.program);
gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
gl.clearDepth(clearDepth);
gl.clearStencil(clearStencil);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.STENCIL_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
return gl;
} }
function drawAndReadPixel(gl, vertices, colors, x, y) function drawAndReadPixel(gl, vertices, colors, x, y)
@ -146,11 +94,6 @@ function testAlpha(alpha)
else else
shouldBeNonNull("webGL = getWebGL('alphaOff', { alpha: false, depth: false, stencil: false, antialias: false }, [ 0, 0, 0, 0 ], 1, 0)"); shouldBeNonNull("webGL = getWebGL('alphaOff', { alpha: false, depth: false, stencil: false, antialias: false }, [ 0, 0, 0, 0 ], 1, 0)");
shouldBeNonNull("contextAttribs = webGL.getContextAttributes()"); shouldBeNonNull("contextAttribs = webGL.getContextAttributes()");
shouldBe("contextAttribs.alpha", (alpha ? "true" : "false"));
shouldBe("contextAttribs.depth", "false");
shouldBe("contextAttribs.stencil", "false");
shouldBe("contextAttribs.antialias", "false");
shouldBe("contextAttribs.premultipliedAlpha", "true");
var buf = new Uint8Array(1 * 1 * 4); var buf = new Uint8Array(1 * 1 * 4);
webGL.readPixels(0, 0, 1, 1, webGL.RGBA, webGL.UNSIGNED_BYTE, buf); webGL.readPixels(0, 0, 1, 1, webGL.RGBA, webGL.UNSIGNED_BYTE, buf);
@ -158,7 +101,7 @@ function testAlpha(alpha)
pixel[1] = buf[1]; pixel[1] = buf[1];
pixel[2] = buf[2]; pixel[2] = buf[2];
pixel[3] = buf[3]; pixel[3] = buf[3];
correctColor = (alpha ? [0, 0, 0, 0] : [0, 0, 0, 255]); correctColor = (contextAttribs.alpha ? [0, 0, 0, 0] : [0, 0, 0, 255]);
shouldBe("pixel", "correctColor"); shouldBe("pixel", "correctColor");
} }
@ -170,11 +113,6 @@ function testDepth(depth)
else else
shouldBeNonNull("webGL = getWebGL('depthOff', { depth: false, stencil: false, antialias: false }, [ 0, 0, 0, 1 ], 1, 0)"); shouldBeNonNull("webGL = getWebGL('depthOff', { depth: false, stencil: false, antialias: false }, [ 0, 0, 0, 1 ], 1, 0)");
shouldBeNonNull("contextAttribs = webGL.getContextAttributes()"); shouldBeNonNull("contextAttribs = webGL.getContextAttributes()");
shouldBe("contextAttribs.depth", (depth ? "true" : "false"));
shouldBe("contextAttribs.alpha", "true");
shouldBe("contextAttribs.stencil", "false");
shouldBe("contextAttribs.antialias", "false");
shouldBe("contextAttribs.premultipliedAlpha", "true");
webGL.depthFunc(webGL.NEVER); webGL.depthFunc(webGL.NEVER);
@ -198,7 +136,7 @@ function testDepth(depth)
pixel[1] = buf[1]; pixel[1] = buf[1];
pixel[2] = buf[2]; pixel[2] = buf[2];
pixel[3] = buf[3]; pixel[3] = buf[3];
correctColor = (depth ? [0, 0, 0, 255] : [255, 0, 0, 255]); correctColor = (contextAttribs.depth ? [0, 0, 0, 255] : [255, 0, 0, 255]);
shouldBe("pixel", "correctColor"); shouldBe("pixel", "correctColor");
} }
@ -210,11 +148,6 @@ function testStencil(stencil)
else else
shouldBeNonNull("webGL = getWebGL('stencilOff', { depth: false, stencil: false, antialias: false }, [ 0, 0, 0, 1 ], 1, 0)"); shouldBeNonNull("webGL = getWebGL('stencilOff', { depth: false, stencil: false, antialias: false }, [ 0, 0, 0, 1 ], 1, 0)");
shouldBeNonNull("contextAttribs = webGL.getContextAttributes()"); shouldBeNonNull("contextAttribs = webGL.getContextAttributes()");
// If EXT_packed_depth_stencil is supported, both depth & stencil will be true; otherwise, both will be false.
shouldBe("contextAttribs.depth == contextAttribs.stencil", "true");
shouldBe("contextAttribs.alpha", "true");
shouldBe("contextAttribs.antialias", "false");
shouldBe("contextAttribs.premultipliedAlpha", "true");
webGL.depthFunc(webGL.ALWAYS); webGL.depthFunc(webGL.ALWAYS);
@ -241,10 +174,7 @@ function testStencil(stencil)
pixel[1] = buf[1]; pixel[1] = buf[1];
pixel[2] = buf[2]; pixel[2] = buf[2];
pixel[3] = buf[3]; pixel[3] = buf[3];
correctColor = (stencil ? [0, 0, 0, 255] : [255, 0, 0, 255]); correctColor = (contextAttribs.stencil ? [0, 0, 0, 255] : [255, 0, 0, 255]);
// If stencil is requested but not supported, we fake the effect.
if (stencil && !contextAttribs.stencil)
pixel[0] = 0;
shouldBe("pixel", "correctColor"); shouldBe("pixel", "correctColor");
} }
@ -256,11 +186,6 @@ function testAntialias(antialias)
else else
shouldBeNonNull("webGL = getWebGL('antialiasOff', { depth: false, stencil: false, alpha: false, antialias: false }, [ 0, 0, 0, 1 ], 1, 0)"); shouldBeNonNull("webGL = getWebGL('antialiasOff', { depth: false, stencil: false, alpha: false, antialias: false }, [ 0, 0, 0, 1 ], 1, 0)");
shouldBeNonNull("contextAttribs = webGL.getContextAttributes()"); shouldBeNonNull("contextAttribs = webGL.getContextAttributes()");
shouldBe("contextAttribs.depth", "false");
shouldBe("contextAttribs.stencil", "false");
shouldBe("contextAttribs.alpha", "false");
shouldBe("contextAttribs.antialias == true || contextAttribs.antialias == false", "true");
shouldBe("contextAttribs.premultipliedAlpha", "true");
var vertices = new Float32Array([ var vertices = new Float32Array([
1.0, 1.0, 0.0, 1.0, 1.0, 0.0,
@ -272,10 +197,7 @@ function testAntialias(antialias)
255, 0, 0, 255]); 255, 0, 0, 255]);
var buf = drawAndReadPixel(webGL, vertices, colors, 0, 0); var buf = drawAndReadPixel(webGL, vertices, colors, 0, 0);
pixel[0] = buf[0]; pixel[0] = buf[0];
// If antialias is requested but not supported, we fake the effect. shouldBe("pixel[0] != 255 && pixel[0] != 0", "contextAttribs.antialias");
if (antialias && !contextAttribs.antialias)
pixel[0] = 127;
shouldBe("pixel[0] == 255 || pixel[0] == 0", (antialias ? "false" : "true"));
} }
function runTest() function runTest()

Просмотреть файл

@ -1,66 +0,0 @@
<!--
Copyright (c) 2010 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<html>
<head>
<link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script>
<script src="resources/webgl-test.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
description("Test passing down and fetching of WebGLContextAttributes");
debug("Test default values");
var context;
var attribs;
shouldBeNonNull("context = create3DContext(null)");
shouldBeNonNull("attribs = context.getContextAttributes()");
shouldBe("attribs.depth", "true");
shouldBe("attribs.alpha", "true");
shouldBe("attribs.stencil", "false");
// Antialias is requested by default, but might or might not be supported.
shouldBe("attribs.antialias == true || attribs.antialias == false", "true");
shouldBe("attribs.premultipliedAlpha", "true");
debug ("Test customized values");
shouldBeNonNull("context = create3DContext(null, { stencil: false, antialias: false })");
shouldBeNonNull("attribs = context.getContextAttributes()");
shouldBe("attribs.depth", "true");
shouldBe("attribs.alpha", "true");
shouldBe("attribs.stencil", "false");
shouldBe("attribs.antialias", "false");
shouldBe("attribs.premultipliedAlpha", "true");
debug("Test customized values");
// (stencil == true && depth == false) is not supported.
// Default depth to true if EXT_packed_depth_stencil is supported.
// Otherwise, both depth and stencil should be false.
shouldBeNonNull("context = create3DContext(null, { depth: false, stencil: true, antialias: false })");
shouldBeNonNull("attribs = context.getContextAttributes()");
shouldBe("attribs.depth == attribs.stencil", "true");
shouldBe("attribs.alpha", "true");
shouldBe("attribs.antialias", "false");
shouldBe("attribs.premultipliedAlpha", "true");
debug("Test customized values");
// (premultipliedAlpha == false) is not supported by most implementations yet
shouldBeNonNull("context = create3DContext(null, { premultipliedAlpha: false, antialias: false })");
shouldBeNonNull("attribs = context.getContextAttributes()");
shouldBe("attribs.depth", "true");
shouldBe("attribs.alpha", "true");
shouldBe("attribs.stencil == true || attribs.stencil == false", "true");
shouldBe("attribs.antialias", "false");
shouldBe("attribs.premultipliedAlpha == true || attribs.premultipliedAlpha == false", "true");
successfullyParsed = true;
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>

Просмотреть файл

@ -88,7 +88,7 @@ function runTestIteration(antialias)
gl.enableVertexAttribArray(0); gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(1); gl.enableVertexAttribArray(1);
gl.vertexAttribPointer(1, 2, gl.FLOAT, gl.FALSE, 0, texCoordOffset); gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, texCoordOffset);
gl.colorMask(1, 1, 1, 0); gl.colorMask(1, 1, 1, 0);
gl.disable(gl.BLEND); gl.disable(gl.BLEND);

Просмотреть файл

@ -50,10 +50,10 @@ shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(co
shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0, 10000)"); shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0, 10000)");
shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0, 10000000000000)"); shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0, 10000000000000)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, 0, -1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, 0, -1)");
shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 1, 0)"); shouldGenerateGLError(context, context.NO_ERROR, "context.drawArrays(context.TRIANGLES, 1, 0)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, -1, 0)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, -1, 0)");
shouldGenerateGLError(context, context.NO_ERROR, "context.drawArrays(context.TRIANGLES, 0, 0)"); shouldGenerateGLError(context, context.NO_ERROR, "context.drawArrays(context.TRIANGLES, 0, 0)");
shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 100, 0)"); shouldGenerateGLError(context, context.NO_ERROR, "context.drawArrays(context.TRIANGLES, 100, 0)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, 1, -1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, 1, -1)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, -1, 1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, -1, 1)");
@ -69,7 +69,7 @@ shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(co
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, 0, -1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, 0, -1)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, -1, 0)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, -1, 0)");
shouldGenerateGLError(context, context.NO_ERROR, "context.drawArrays(context.TRIANGLES, 0, 0)"); shouldGenerateGLError(context, context.NO_ERROR, "context.drawArrays(context.TRIANGLES, 0, 0)");
shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 100, 0)"); shouldGenerateGLError(context, context.NO_ERROR, "context.drawArrays(context.TRIANGLES, 100, 0)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, 1, -1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, 1, -1)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, -1, 1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawArrays(context.TRIANGLES, -1, 1)");

Просмотреть файл

@ -74,7 +74,7 @@ shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(cont
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, 0, context.UNSIGNED_BYTE, -1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, 0, context.UNSIGNED_BYTE, -1)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, -1, context.UNSIGNED_BYTE, 1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, -1, context.UNSIGNED_BYTE, 1)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, 1, context.UNSIGNED_BYTE, -1)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, 1, context.UNSIGNED_BYTE, -1)");
shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 0, context.UNSIGNED_BYTE, 4)"); shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 0, context.UNSIGNED_BYTE, 4)");
shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, 0xffffffff, context.UNSIGNED_BYTE, 0)"); shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, 0xffffffff, context.UNSIGNED_BYTE, 0)");
shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 0x7fffffff, context.UNSIGNED_BYTE, 0)"); shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 0x7fffffff, context.UNSIGNED_BYTE, 0)");
shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 0x7fffffff, context.UNSIGNED_BYTE, 0x7fffffff)"); shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 0x7fffffff, context.UNSIGNED_BYTE, 0x7fffffff)");

Просмотреть файл

@ -28,25 +28,29 @@ function testAttachment(attachment, buffer, isConflicted)
{ {
shouldBeNonNull("fbo = gl.createFramebuffer()"); shouldBeNonNull("fbo = gl.createFramebuffer()");
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, buffer); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, buffer);
glErrorShouldBe(gl, isConflicted ? gl.INVALID_OPERATION : gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
if (isConflicted) {
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
gl.clear(gl.COLOR_BUFFER_BIT);
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(width * height * 4));
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
}
} }
function testAttachments(attachment0, buffer0, attachment1, buffer1, isConflicted) function testAttachments(attachment0, buffer0, attachment1, buffer1, isConflicted)
{ {
shouldBeNonNull("fbo = gl.createFramebuffer()"); shouldBeNonNull("fbo = gl.createFramebuffer()");
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment0, gl.RENDERBUFFER, buffer0); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment0, gl.RENDERBUFFER, buffer0);
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment1, gl.RENDERBUFFER, buffer1); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment1, gl.RENDERBUFFER, buffer1);
glErrorShouldBe(gl, isConflicted ? gl.INVALID_OPERATION : gl.NO_ERROR);
if (isConflicted) {
// Detach buffer0 first using a null object, then attaching buffer1 should succeed.
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment0, gl.RENDERBUFFER, null);
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment1, gl.RENDERBUFFER, buffer1); if (isConflicted)
glErrorShouldBe(gl, gl.NO_ERROR); shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
}
} }
function testColorRenderbuffer(internalformat) function testColorRenderbuffer(internalformat)
@ -58,10 +62,33 @@ function testColorRenderbuffer(internalformat)
testAttachment(gl.COLOR_ATTACHMENT0, colorBuffer, false); testAttachment(gl.COLOR_ATTACHMENT0, colorBuffer, false);
} }
function testDepthStencilRenderbuffer()
{
shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()");
gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
glErrorShouldBe(gl, gl.NO_ERROR);
shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)", "width");
shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)", "height");
shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTERNAL_FORMAT)", "gl.DEPTH_STENCIL");
shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_RED_SIZE)", "0");
shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_GREEN_SIZE)", "0");
shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_BLUE_SIZE)", "0");
shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA_SIZE)", "0");
shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE) > 0");
shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_STENCIL_SIZE) > 0");
glErrorShouldBe(gl, gl.NO_ERROR);
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, false);
}
description("Test framebuffer object attachment behaviors"); description("Test framebuffer object attachment behaviors");
debug("Create renderbuffers"); debug("Create renderbuffers");
shouldBeNonNull("gl = create3DContext()"); shouldBeNonNull("gl = create3DContext()");
shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, width, height);
glErrorShouldBe(gl, gl.NO_ERROR);
shouldBeNonNull("depthBuffer = gl.createRenderbuffer()"); shouldBeNonNull("depthBuffer = gl.createRenderbuffer()");
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height); gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
@ -116,6 +143,9 @@ testColorRenderbuffer(gl.RGB5_A1);
debug("Attach color renderbuffer with internalformat == RGB565"); debug("Attach color renderbuffer with internalformat == RGB565");
testColorRenderbuffer(gl.RGB565); testColorRenderbuffer(gl.RGB565);
debug("Create and attach depthStencil renderbuffer");
testDepthStencilRenderbuffer();
successfullyParsed = true; successfullyParsed = true;
</script> </script>

Просмотреть файл

@ -64,7 +64,7 @@ var shaders = gl.getAttachedShaders(standardProgram);
shouldBe('shaders.length', '2'); shouldBe('shaders.length', '2');
shouldBeTrue('shaders[0] == standardVert && shaders[1] == standardFrag || shaders[1] == standardVert && shaders[0] == standardFrag'); shouldBeTrue('shaders[0] == standardVert && shaders[1] == standardFrag || shaders[1] == standardVert && shaders[0] == standardFrag');
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
shouldBeUndefined('gl.getAttachedShaders(null)'); shouldBeNull('gl.getAttachedShaders(null)');
glErrorShouldBe(gl, gl.INVALID_VALUE); glErrorShouldBe(gl, gl.INVALID_VALUE);
shouldThrow('gl.getAttachedShaders(standardVert)'); shouldThrow('gl.getAttachedShaders(standardVert)');
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
@ -174,9 +174,9 @@ gl.uniform3i(bval3Loc, 1, 0, 1);
gl.uniform4i(bval4Loc, 1, 0, 1, 0); gl.uniform4i(bval4Loc, 1, 0, 1, 0);
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
shouldBe('gl.getUniform(boolProgram, bvalLoc)', 'true'); shouldBe('gl.getUniform(boolProgram, bvalLoc)', 'true');
shouldBe('gl.getUniform(boolProgram, bval2Loc)', '[1, 0]'); shouldBe('gl.getUniform(boolProgram, bval2Loc)', '[true, false]');
shouldBe('gl.getUniform(boolProgram, bval3Loc)', '[1, 0, 1]'); shouldBe('gl.getUniform(boolProgram, bval3Loc)', '[true, false, true]');
shouldBe('gl.getUniform(boolProgram, bval4Loc)', '[1, 0, 1, 0]'); shouldBe('gl.getUniform(boolProgram, bval4Loc)', '[true, false, true, false]');
// Integer uniform variables // Integer uniform variables
var intProgram = loadProgram(gl, "resources/intUniformShader.vert", "resources/noopUniformShader.frag"); var intProgram = loadProgram(gl, "resources/intUniformShader.vert", "resources/noopUniformShader.frag");
shouldBe('gl.getProgramParameter(intProgram, gl.LINK_STATUS)', 'true'); shouldBe('gl.getProgramParameter(intProgram, gl.LINK_STATUS)', 'true');

Просмотреть файл

@ -38,7 +38,8 @@ var imgURLs = [
'resources/gray-ramp.png', 'resources/gray-ramp.png',
'resources/zero-alpha.png', 'resources/zero-alpha.png',
'resources/3x3.png', 'resources/3x3.png',
'resources/blue-1x1.jpg']; 'resources/blue-1x1.jpg',
'resources/green-2x2-16bit.png'];
wtu.loadImagesAsync(imgURLs, runTests); wtu.loadImagesAsync(imgURLs, runTests);
@ -167,6 +168,7 @@ function runTests(imgs) {
debug(""); debug("");
debug("Check that gamma settings don't effect 8bit pngs"); debug("Check that gamma settings don't effect 8bit pngs");
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
imgs['resources/gray-ramp-default-gamma.png']); imgs['resources/gray-ramp-default-gamma.png']);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
@ -289,6 +291,19 @@ function runTests(imgs) {
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors"); glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
debug("");
debug("check uploading of 16-bit images");
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
imgs['resources/green-2x2-16bit.png']);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
wtu.drawQuad(gl);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
checkPixelRange(buf, middle, center, [ 15, 121, 0, 255], 10);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
debug(""); debug("");
successfullyParsed = true; successfullyParsed = true;
shouldBeTrue("successfullyParsed"); shouldBeTrue("successfullyParsed");

Просмотреть файл

@ -19,7 +19,7 @@ found in the LICENSE file.
<div id="console"></div> <div id="console"></div>
<canvas id="canvas" width="2" height="2"> </canvas> <canvas id="canvas" width="2" height="2"> </canvas>
<script> <script>
description("This test ensures WebGL implementations vertexAttribPointer can not be set if no buffer is bound."); description("This test checks vertexAttribPointer behaviors in WebGL.");
debug(""); debug("");
debug("Canvas.getContext"); debug("Canvas.getContext");
@ -36,6 +36,16 @@ if (!gl) {
gl.vertexAttribPointer(0, 3, gl.FLOAT, 0, 0, 12); gl.vertexAttribPointer(0, 3, gl.FLOAT, 0, 0, 12);
glErrorShouldBe(gl, gl.INVALID_OPERATION, glErrorShouldBe(gl, gl.INVALID_OPERATION,
"vertexAttribPointer should fail if no buffer is bound"); "vertexAttribPointer should fail if no buffer is bound");
var vertexObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(512), gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 1, gl.FLOAT, 0, 256, 0);
glErrorShouldBe(gl, gl.INVALID_VALUE,
"WebGL API supports vertex attribute data strides up to 255 bytes");
gl.vertexAttribPointer(0, 1, gl.FLOAT, 0, 255, 0);
glErrorShouldBe(gl, gl.NO_ERROR,
"vertexAttribPointer with stride <= 255 should succeed");
} }
debug(""); debug("");

Просмотреть файл

@ -60,6 +60,7 @@ function init()
gl = initWebGL("example", "vshader", "fshader", [ "vPosition", "texCoord0"], gl = initWebGL("example", "vshader", "fshader", [ "vPosition", "texCoord0"],
[ 0, 0, 0, 1 ], 1); [ 0, 0, 0, 1 ], 1);
gl = WebGLDebugUtils.makeDebugContext(gl);
gl.disable(gl.DEPTH_TEST); gl.disable(gl.DEPTH_TEST);
gl.disable(gl.BLEND); gl.disable(gl.BLEND);
@ -124,7 +125,7 @@ function init()
var y = Math.floor(ii / 2); var y = Math.floor(ii / 2);
gl.drawArrays(gl.TRIANGLES, 0, 6); gl.drawArrays(gl.TRIANGLES, 0, 6);
glErrorShouldBe(gl, gl.INVALID_OPERATION, glErrorShouldBe(gl, gl.INVALID_OPERATION,
"drawing with 2 different targets on the same texture unit should generate error"); "drawing with 2 different targets on the same texture unit should generate INVALID_VALUE");
} }
} }

Просмотреть файл

@ -223,6 +223,37 @@ foo
<script id="vshaderWith__FILE__" type="text/something-not-javascript"> <script id="vshaderWith__FILE__" type="text/something-not-javascript">
__FILE__ __FILE__
</script> </script>
<script id="fshaderWithdFdx" type="text/something-not-javascript">
#extension GL_OES_standard_derivatives:enable
precision mediump float;
void main()
{
gl_FragColor = vec4(dFdx(0.5),0.0,0.0,1.0);
}
</script>
<script id="fshaderWithdFdxNoExt" type="text/something-not-javascript">
precision mediump float;
void main()
{
gl_FragColor = vec4(dFdx(0.5),0.0,0.0,1.0);
}
</script>
<script id="fshaderWith256CharacterIdentifier" type="text/something-not-javascript">
precision mediump float;
uniform float a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 = 2.0;
void main()
{
gl_FragColor = vec4(a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345,0.0,0.0,1.0);
}
</script>
<script id="fshaderWith257CharacterIdentifier" type="text/something-not-javascript">
precision mediump float;
uniform float a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456 = 2.0;
void main()
{
gl_FragColor = vec4(a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456,0.0,0.0,1.0);
}
</script>
<canvas id="canvas" width="2" height="2"> </canvas> <canvas id="canvas" width="2" height="2"> </canvas>
<script> <script>
description("This test ensures WebGL implementations allow proper GLES2 shaders compile and improper ones fail."); description("This test ensures WebGL implementations allow proper GLES2 shaders compile and improper ones fail.");
@ -310,6 +341,20 @@ if (!gl) {
linkSuccess: false, linkSuccess: false,
passMsg: 'fragment shader that uses gl_FragDepth should fail', passMsg: 'fragment shader that uses gl_FragDepth should fail',
}, },
{ vShaderId: 'vshader',
vShaderSuccess: true,
fShaderId: 'fshaderWithdFdx',
fShaderSuccess: false,
linkSuccess: false,
passMsg: 'fragment shader that uses dFdx should fail',
},
{ vShaderId: 'vshader',
vShaderSuccess: true,
fShaderId: 'fshaderWithdFdxNoExt',
fShaderSuccess: false,
linkSuccess: false,
passMsg: 'fragment shader that uses dFdx without #extension should fail',
},
{ vShaderId: 'vshaderWithClipVertex', { vShaderId: 'vshaderWithClipVertex',
vShaderSuccess: false, vShaderSuccess: false,
fShaderId: 'fshader', fShaderId: 'fshader',
@ -415,7 +460,21 @@ if (!gl) {
fShaderSuccess: true, fShaderSuccess: true,
linkSuccess: false, linkSuccess: false,
passMsg: 'vertex shader uses #line directive should report correct line', passMsg: 'vertex shader uses #line directive should report correct line',
} },
{ vShaderId: 'vshader',
vShaderSuccess: true,
fShaderId: 'fshaderWith256CharacterIdentifier',
fShaderSuccess: true,
linkSuccess: true,
passMsg: 'shared that uses 256 character identifier should succeed',
},
{ vShaderId: 'vshader',
vShaderSuccess: true,
fShaderId: 'fshaderWith257CharacterIdentifier',
fShaderSuccess: false,
linkSuccess: false,
passMsg: 'shared that uses 257 character identifier should fail',
},
]; ];
// Read in all the shader source. // Read in all the shader source.

Просмотреть файл

@ -0,0 +1,72 @@
<html>
<head>
<link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script>
<script src="resources/webgl-test.js"></script>
<script src="resources/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<canvas id="canvas">
<script>
var wtu;
var canvas;
var gl;
var shouldGenerateGLError;
var buffer;
var framebuffer;
var program;
var renderbuffer;
var shader;
var texture;
description("Tests 'is' calls against non-bound and deleted objects");
wtu = WebGLTestUtils;
canvas = document.getElementById("canvas");
gl = wtu.create3DContext(canvas);
shouldGenerateGLError = wtu.shouldGenerateGLError;
shouldGenerateGLError(gl, gl.NO_ERROR, "buffer = gl.createBuffer()");
shouldBeFalse("gl.isBuffer(buffer)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
shouldBeTrue("gl.isBuffer(buffer)");
debug("");
shouldGenerateGLError(gl, gl.NO_ERROR, "framebuffer = gl.createFramebuffer()");
shouldBeFalse("gl.isFramebuffer(framebuffer)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)");
shouldBeTrue("gl.isFramebuffer(framebuffer)");
debug("");
shouldGenerateGLError(gl, gl.NO_ERROR, "renderbuffer = gl.createRenderbuffer()");
shouldBeFalse("gl.isRenderbuffer(renderbuffer)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)");
shouldBeTrue("gl.isRenderbuffer(renderbuffer)");
debug("");
shouldGenerateGLError(gl, gl.NO_ERROR, "texture = gl.createTexture()");
shouldBeFalse("gl.isTexture(texture)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, texture)");
shouldBeTrue("gl.isTexture(texture)");
debug("");
shouldGenerateGLError(gl, gl.NO_ERROR, "program = gl.createProgram()");
shouldBeTrue("gl.isProgram(program)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteProgram(program)");
shouldBeFalse("gl.isProgram(program)");
debug("");
shouldGenerateGLError(gl, gl.NO_ERROR, "shader = gl.createShader(gl.VERTEX_SHADER)");
shouldBeTrue("gl.isShader(shader)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteShader(shader)");
shouldBeFalse("gl.isShader(shader)");
debug("");
successfullyParsed = true;
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>

Просмотреть файл

@ -44,8 +44,6 @@ var gl = null;
var array = null; var array = null;
var pixel = [ 0, 0, 0, 0 ]; var pixel = [ 0, 0, 0, 0 ];
var expectedColor = [ 0, 0, 0, 0 ]; var expectedColor = [ 0, 0, 0, 0 ];
var pixelFormat = 0;
var pixelType = 0;
function calculatePixelBytes(format, type) function calculatePixelBytes(format, type)
{ {
@ -168,38 +166,26 @@ function runTestIteration(format, type, packAlignment, width, height)
var bytesPerPixel = calculatePixelBytes(format, type); var bytesPerPixel = calculatePixelBytes(format, type);
var padding = calculatePaddingBytes(bytesPerPixel, packAlignment, width); var padding = calculatePaddingBytes(bytesPerPixel, packAlignment, width);
var size = bytesPerPixel * width * height + padding * (height - 1); var size = bytesPerPixel * width * height + padding * (height - 1);
var isShort = false; if (type != gl.UNSIGNED_BYTE) {
switch (type) { throw "test error: only UNSIGNED_BYTE is valid to ReadPixels";
case gl.UNSIGNED_SHORT_5_6_5:
case gl.UNSIGNED_SHORT_4_4_4_4:
case gl.UNSIGNED_SHORT_5_5_5_1:
isShort = true;
} }
if (isShort)
size /= 2;
if (size < 0) if (size < 0)
size = 0; size = 0;
if (type == gl.UNSIGNED_BYTE)
array = new Uint8Array(size); array = new Uint8Array(size);
else
array = new Uint16Array(size);
gl.readPixels(0, 0, width, height, format, type, array); gl.readPixels(0, 0, width, height, format, type, array);
if (width < 0 || height < 0) { if (width < 0 || height < 0) {
glErrorShouldBe(gl, gl.INVALID_VALUE); glErrorShouldBe(gl, gl.INVALID_VALUE);
return; return;
} else { }
glErrorShouldBe(gl, gl.NO_ERROR); glErrorShouldBe(gl, gl.NO_ERROR);
if (!array.length) if (!array.length)
return; return;
}
// Check the last pixel of the last row. // Check the last pixel of the last row.
var bytesPerRow = width * bytesPerPixel + padding; var bytesPerRow = width * bytesPerPixel + padding;
var pos = bytesPerRow * (height - 1) + (width - 1) * bytesPerPixel; var pos = bytesPerRow * (height - 1) + (width - 1) * bytesPerPixel;
var numComponents = bytesPerPixel; var numComponents = bytesPerPixel;
if (isShort) {
pos /= 2;
numComponents /= 2;
}
for (var i = 0; i < numComponents; ++i) for (var i = 0; i < numComponents; ++i)
pixel[i] = array[pos + i]; pixel[i] = array[pos + i];
for (var i = numComponents; i < 4; ++i) for (var i = numComponents; i < 4; ++i)
@ -209,74 +195,43 @@ function runTestIteration(format, type, packAlignment, width, height)
shouldBe("pixel", "expectedColor"); shouldBe("pixel", "expectedColor");
} }
function checkSupportedPixelFormatAndType()
{
debug("Check supported pixel format/type besides RGBA/UNSIGNED_BYTE");
glErrorShouldBe(gl, gl.NO_ERROR);
pixelFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
pixelType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
glErrorShouldBe(gl, gl.NO_ERROR);
shouldBeFalse("pixelFormat == gl.RGBA && pixelType == gl.UNSIGNED_BYTE");
}
description('Verify readPixels() works fine with various PACK_ALIGNMENT values.'); description('Verify readPixels() works fine with various PACK_ALIGNMENT values.');
shouldBeNonNull("gl = initWebGL('example', 'vshader', 'fshader', [ 'pos', 'colorIn' ], [ 0, 0, 0, 1 ], 1)"); shouldBeNonNull("gl = initWebGL('example', 'vshader', 'fshader', [ 'pos', 'colorIn' ], [ 0, 0, 0, 1 ], 1)");
gl.disable(gl.BLEND); gl.disable(gl.BLEND);
checkSupportedPixelFormatAndType(); var formats = [ gl.RGBA ];
var formatNames = [ "RGBA" ];
debug("Testing format = RGBA and type = UNSIGNED_BYTE"); for (var i = 0; i < formats.length; ++i) {
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, 1, 2); var format = formats[i];
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 1, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 1, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 1, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 2, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 2, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 3, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 3, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 4, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 4, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 5, 1);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 5, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 5, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 6, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 7, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 8, 2);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, 0, 0);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 0, 0);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 0, 0);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 0, 0);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, -1, 1);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 1, -1);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 0, -1);
runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, -1, -1);
debug("Testing the other supported format/type combination"); debug("Testing format = " + formatNames[i] + " and type = UNSIGNED_BYTE");
runTestIteration(pixelFormat, pixelType, 1, 1, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 1, 1, 2);
runTestIteration(pixelFormat, pixelType, 2, 1, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, 2);
runTestIteration(pixelFormat, pixelType, 4, 1, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 4, 1, 2);
runTestIteration(pixelFormat, pixelType, 8, 1, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 1, 2);
runTestIteration(pixelFormat, pixelType, 4, 2, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 4, 2, 2);
runTestIteration(pixelFormat, pixelType, 8, 2, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 2, 2);
runTestIteration(pixelFormat, pixelType, 4, 3, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 4, 3, 2);
runTestIteration(pixelFormat, pixelType, 8, 3, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 3, 2);
runTestIteration(pixelFormat, pixelType, 4, 4, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 4, 4, 2);
runTestIteration(pixelFormat, pixelType, 8, 4, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 4, 2);
runTestIteration(pixelFormat, pixelType, 8, 5, 1); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 1);
runTestIteration(pixelFormat, pixelType, 4, 5, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 4, 5, 2);
runTestIteration(pixelFormat, pixelType, 8, 5, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 2);
runTestIteration(pixelFormat, pixelType, 8, 6, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 6, 2);
runTestIteration(pixelFormat, pixelType, 8, 7, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 7, 2);
runTestIteration(pixelFormat, pixelType, 8, 8, 2); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 8, 2);
runTestIteration(pixelFormat, pixelType, 1, 0, 0); runTestIteration(format, gl.UNSIGNED_BYTE, 1, 0, 0);
runTestIteration(pixelFormat, pixelType, 2, 0, 0); runTestIteration(format, gl.UNSIGNED_BYTE, 2, 0, 0);
runTestIteration(pixelFormat, pixelType, 4, 0, 0); runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, 0);
runTestIteration(pixelFormat, pixelType, 8, 0, 0); runTestIteration(format, gl.UNSIGNED_BYTE, 8, 0, 0);
runTestIteration(pixelFormat, pixelType, 1, -1, 1); runTestIteration(format, gl.UNSIGNED_BYTE, 1, -1, 1);
runTestIteration(pixelFormat, pixelType, 2, 1, -1); runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, -1);
runTestIteration(pixelFormat, pixelType, 4, 0, -1); runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, -1);
runTestIteration(pixelFormat, pixelType, 8, -1, -1); runTestIteration(format, gl.UNSIGNED_BYTE, 8, -1, -1);
}
successfullyParsed = true; successfullyParsed = true;
</script> </script>

Просмотреть файл

@ -11,6 +11,7 @@ found in the LICENSE file.
<link rel="stylesheet" href="../resources/js-test-style.css"/> <link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script> <script src="../resources/js-test-pre.js"></script>
<script src="resources/webgl-test.js"> </script> <script src="resources/webgl-test.js"> </script>
<script src="resources/webgl-test-utils.js"> </script>
</head> </head>
<body> <body>
<canvas id="example" width="200" height="200"></canvas> <canvas id="example" width="200" height="200"></canvas>
@ -19,6 +20,7 @@ found in the LICENSE file.
<script> <script>
description("Checks that ReadPixels works as expected."); description("Checks that ReadPixels works as expected.");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("example"); var canvas = document.getElementById("example");
var gl = create3DContext(canvas); var gl = create3DContext(canvas);
@ -90,6 +92,56 @@ function checkBuffer(checkColor, x, y, oneColor, oneX, oneY) {
} }
} }
var badFormats = [
{
format: gl.RGB,
type: gl.UNSIGNED_BYTE,
dest: new Uint8Array(3)
},
{
format: gl.RGB,
type: gl.UNSIGNED_SHORT_5_6_5,
dest: new Uint8Array(3)
},
{
format: gl.RGBA,
type: gl.UNSIGNED_SHORT_5_5_5_1,
dest: new Uint16Array(1)
},
{
format: gl.RGBA,
type: gl.UNSIGNED_SHORT_4_4_4_4,
dest: new Uint16Array(1)
},
{
format: gl.ALPHA,
type: gl.UNSIGNED_BYTE,
dest: new Uint8Array(1)
},
{
format: gl.LUMINANCE,
type: gl.UNSIGNED_BYTE,
dest: new Uint8Array(1) },
{
format: gl.LUMINANCE_ALPHA,
type: gl.UNSIGNED_BYTE,
dest: new Uint8Array(2)
}
];
for (var tt = 0; tt < badFormats.length; ++ tt) {
var info = badFormats[tt]
var format = info.format;
var type = info.type;
var dest = info.dest;
gl.readPixels(0, 0, 1, 1, format, type, dest);
// note that the GL error is INVALID_OPERATION if both format and type are invalid, but
// INVALID_ENUM if only one is.
glErrorShouldBe(
gl, (format == gl.RGBA || type == gl.UNSIGNED_BYTE) ? gl.INVALID_ENUM : gl.INVALID_OPERATION,
"Should not be able to read as " + wtu.glEnumToString(gl, format) +
" / " + wtu.glEnumToString(gl, type));
}
debug(""); debug("");
successfullyParsed = true; successfullyParsed = true;
</script> </script>

Просмотреть файл

@ -12,7 +12,7 @@ found in the LICENSE file.
function runTest() function runTest()
{ {
var canvas = document.getElementById("testbed"); var canvas = document.getElementById("testbed");
var gl = canvas.getContext("experimental-webgl"); var gl = create3DContext(canvas);
if (!gl) { if (!gl) {
testFailed('canvas.getContext() failed'); testFailed('canvas.getContext() failed');
return false; return false;

Просмотреть файл

@ -9,46 +9,18 @@ found in the LICENSE file.
<script src="../resources/js-test-pre.js"></script> <script src="../resources/js-test-pre.js"></script>
<script src="resources/webgl-test.js"></script> <script src="resources/webgl-test.js"></script>
<script src="resources/webgl-test-utils.js"></script> <script src="resources/webgl-test-utils.js"></script>
</head>
<body>
<canvas id="example" width="1px" height="2px"></canvas>
<div id="description"></div>
<div id="console"></div>
<script> <script>
description('Verifies texImage2D and texSubImage2D code paths taking ArrayBufferView');
var wtu = WebGLTestUtils; var wtu = WebGLTestUtils;
var gl = null; var gl = null;
var textureLoc = null; var textureLoc = null;
var successfullyParsed = false; var successfullyParsed = false;
var imageData = null;
function init()
{
if (window.initNonKhronosFramework) {
window.initNonKhronosFramework(true);
}
description('Verifies texImage2D and texSubImage2D code paths taking ArrayBufferView');
var canvas2d = document.getElementById("texcanvas");
var context2d = canvas2d.getContext("2d");
imageData = context2d.createImageData(1, 2);
var data = imageData.data;
data[0] = 255;
data[1] = 0;
data[2] = 0;
data[3] = 255;
data[4] = 0;
data[5] = 255;
data[6] = 0;
data[7] = 0;
var canvas = document.getElementById("example");
gl = wtu.create3DContext(canvas);
var program = wtu.setupTexturedQuad(gl);
gl.disable(gl.BLEND);
gl.clearColor(0,0,0,1);
gl.clearDepth(1);
textureLoc = gl.getUniformLocation(program, "tex");
runTest();
}
// These two declarations need to be global for "shouldBe" to see them // These two declarations need to be global for "shouldBe" to see them
var buf = null; var buf = null;
@ -199,24 +171,21 @@ function runTest()
} }
} }
successfullyParsed = true;
var epilogue = document.createElement("script");
epilogue.onload = finish;
epilogue.src = "../resources/js-test-post.js";
document.body.appendChild(epilogue);
} }
function finish() { var canvas = document.getElementById("example");
if (window.nonKhronosFrameworkNotifyDone) { gl = wtu.create3DContext(canvas);
window.nonKhronosFrameworkNotifyDone(); var program = wtu.setupTexturedQuad(gl);
} gl.disable(gl.BLEND);
}
gl.clearColor(0,0,0,1);
gl.clearDepth(1);
textureLoc = gl.getUniformLocation(program, "tex");
runTest();
successfullyParsed = true;
</script> </script>
</head> <script src="../resources/js-test-post.js"></script>
<body onload="init()">
<canvas id="texcanvas" width="1px" height="2px"></canvas>
<canvas id="example" width="1px" height="2px"></canvas>
<div id="description"></div>
<div id="console"></div>
</body> </body>
</html> </html>

Просмотреть файл

@ -6,13 +6,12 @@
<link rel="stylesheet" href="../resources/js-test-style.css"/> <link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script> <script src="../resources/js-test-pre.js"></script>
<script src="resources/webgl-test.js"></script> <script src="resources/webgl-test.js"></script>
<script src="resources/testrunner.js"></script>
</head> </head>
<body> <body>
<div id="description"></div> <div id="description"></div>
<div id="console"></div> <div id="console"></div>
<canvas id="canvas" width="2" height="2"> </canvas> <canvas id="canvas" width="2" height="2"> </canvas>
<script><!-- <script type="text/javascript">
description("texImage2D and texSubImage2D tests with invalid data"); description("texImage2D and texSubImage2D tests with invalid data");
var canvas = document.getElementById("canvas"); var canvas = document.getElementById("canvas");
@ -22,63 +21,79 @@ if (!gl)
else else
testPassed("Context created."); testPassed("Context created.");
var tex;
/* object containing all tests in this testsuite */ function setup() {
var bug32619_tests = { tex = gl.createTexture();
setup: function () {
bug32619_tests.tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, bug32619_tests.tex); gl.bindTexture(gl.TEXTURE_2D, bug32619_tests.tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
},
teardown: function () {
gl.deleteTexture(bug32619_tests.tex);
},
"Passing a buffer not large enough to texImage2D should generate an INVALID_OPERATION" : function () {
this.setup = function () {
var tooSmall = new Uint8Array(64);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, tooSmall);
};
this.expects = gl.INVALID_OPERATION;
},
"Passing texImage2D parameter data of Number type should throw a TypeError" : function () {
this.setup = function () {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, 42);
};
this.expects = "TypeError";
},
"Passing texImage2D parameter data of String type should throw a TypeError" : function () {
this.setup = function () {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
};
this.expects = "TypeError";
},
"Passing a buffer not large enough to texSubImage2D should generate an INVALID_OPERATION" : function () {
this.setup = function () {
var tooSmall = new Uint8Array(64);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, tooSmall);
};
this.expects = gl.INVALID_OPERATION;
},
"Passing texSubImage2D parameter data of Number type should throw a TypeError" : function () {
this.setup = function () {
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, 42);
};
this.expects = "TypeError";
},
"Passing texSubImage2D parameter data of String type should throw a TypeError" : function () {
this.setup = function () {
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
};
this.expects = "TypeError";
},
} }
runTestsuite(bug32619_tests); function teardown() {
gl.deleteTexture(tex);
}
function test(desc, func, expected) {
debug(desc);
var exc = null;
try {
func();
} catch (x) {
exc = x;
}
if (expected == gl.INVALID_OPERATION) {
glErrorShouldBe(gl, expected);
} else if (expected == "exception") {
if (exc) {
testPassed("threw exception");
} else {
testFailed("did not throw exception");
}
}
}
test("Passing a buffer not large enough to texImage2D should generate an INVALID_OPERATION",
function () {
var tooSmall = new Uint8Array(64);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, tooSmall);
},
gl.INVALID_OPERATION);
test("Passing texImage2D parameter data of Number type should throw an exception",
function () {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, 42);
},
"exception");
test("Passing texImage2D parameter data of String type should throw a TypeError",
function () {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 64, 64, 0, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
},
"exception");
test("Passing a buffer not large enough to texSubImage2D should generate an INVALID_OPERATION",
function () {
var tooSmall = new Uint8Array(64);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, tooSmall);
},
gl.INVALID_OPERATION);
test("Passing texSubImage2D parameter data of Number type should throw a TypeError",
function () {
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, 42);
},
"exception");
test("Passing texSubImage2D parameter data of String type should throw a TypeError",
function () {
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
},
"exception");
debug(""); debug("");
successfullyParsed = true; successfullyParsed = true;
--></script> </script>
<script src="../resources/js-test-post.js"></script> <script src="../resources/js-test-post.js"></script>
<script> <script>
</script> </script>

Просмотреть файл

@ -51,7 +51,7 @@ function init()
var canvas = document.getElementById("example"); var canvas = document.getElementById("example");
gl = wtu.create3DContext(canvas); gl = wtu.create3DContext(canvas);
var program = wtu.setupTexturedQuad(gl); var program = wtu.setupTexturedQuad(gl);
gl.clearColor(0,0,0,1); gl.clearColor(0.5,0.5,0.5,1);
gl.clearDepth(1); gl.clearDepth(1);
textureLoc = gl.getUniformLocation(program, "tex"); textureLoc = gl.getUniformLocation(program, "tex");
@ -70,7 +70,7 @@ function init()
gl.bindBuffer(gl.ARRAY_BUFFER, vbo); gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW); gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
gl.enableVertexAttribArray(1); gl.enableVertexAttribArray(1);
gl.vertexAttribPointer(1, 2, gl.FLOAT, gl.FALSE, 0, 0); gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
texture = wtu.loadTexture(gl, "resources/bug-32888-texture.png", runTest); texture = wtu.loadTexture(gl, "resources/bug-32888-texture.png", runTest);
} }
@ -82,16 +82,18 @@ var idx = 0;
function runTest() function runTest()
{ {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
// Bind the texture to texture unit 0 // Bind the texture to texture unit 0
gl.bindTexture(gl.TEXTURE_2D, texture); gl.bindTexture(gl.TEXTURE_2D, texture);
// Point the uniform sampler to texture unit 0 // Point the uniform sampler to texture unit 0
gl.uniform1i(textureLoc, 0); gl.uniform1i(textureLoc, 0);
// Draw the triangles // Draw the triangles
wtu.drawQuad(gl, [100, 100, 100, 255]); wtu.drawQuad(gl, [0, 0, 0, 255]);
// Spot check a couple of 2x2 regions in the upper and lower left // Spot check a couple of 2x2 regions in the upper and lower left
// corners; they should be the rgb values in the texture. // corners; they should be the rgb values in the texture.
color = [255, 255, 255] color = [0, 0, 0];
debug("Checking lower left corner"); debug("Checking lower left corner");
wtu.checkCanvasRect(gl, 1, gl.canvas.height - 3, 2, 2, color, wtu.checkCanvasRect(gl, 1, gl.canvas.height - 3, 2, 2, color,
"shouldBe " + color); "shouldBe " + color);

Просмотреть файл

@ -0,0 +1,168 @@
<!--
Copyright (C) 2009 Apple Computer, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<html>
<head>
<link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script>
<script src="resources/webgl-test.js"></script>
<script src="resources/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
var wtu = WebGLTestUtils;
description("Tests calling WebGL APIs with various types");
var context = wtu.create3DContext();
var program = wtu.loadStandardProgram(context);
var shader = wtu.loadStandardVertexShader(context);
var shouldGenerateGLError = wtu.shouldGenerateGLError;
assertMsg(program != null, "Program Compiled");
assertMsg(shader != null, "Shader Compiled");
var loc = context.getUniformLocation(program, "u_modelViewProjMatrix");
assertMsg(loc != null, "getUniformLocation succeeded");
var buffer = context.createBuffer();
context.bindBuffer(context.ARRAY_BUFFER, buffer);
var texture = context.createTexture();
context.bindTexture(context.TEXTURE_2D, texture);
context.useProgram(program);
var args = [
{ type: "number", value: 0 },
{ type: "number", value: 2 },
{ type: "string that is NaN", value: "foo", },
{ type: "string that is number", value: "2", },
{ type: "null", value: null },
{ type: "Empty Array", value: [] },
{ type: "Object", value: {} },
{ type: "Array of Number", value: [2] },
{ type: "Array of String", value: ["foo"] },
{ type: "Array of String that is number", value: ["0"] },
{ type: "Array of String that is number", value: ["2"] },
{ type: "TypedArray", value: new Float32Array(1) }
];
var argument;
for (var i = 0; i < args.length; ++i) {
argument = args[i].value;
var func1 = shouldBeUndefined;
var func2 = shouldBeNonNull;
if (argument == 2) {
func2 = shouldBeNull;
}
func3 = shouldBeNull;
debug("");
debug("testing type of " + args[i].type + " : value = " + argument);
func1("context.bindAttribLocation(program, argument, 'foo')");
func1("context.blendColor(argument, argument, argument, argument)");
func1("context.bufferData(context.ARRAY_BUFFER, argument, context.STATIC_DRAW)");
func1("context.bufferData(context.ARRAY_BUFFER, new Float32Array(10), context.STATIC_DRAW)");
func1("context.bufferSubData(context.ARRAY_BUFFER, argument, new Float32Array(2))");
func1("context.clear(argument)")
func1("context.clearColor(argument, 0, 0, 0)");
func1("context.clearColor(0, argument, 0, 0)");
func1("context.clearColor(0, 0, argument, 0)");
func1("context.clearColor(0, 0, 0, argument)");
func1("context.clearDepth(argument)");
func1("context.clearStencil(argument)");
func1("context.copyTexImage2D(context.TEXTURE_2D, argument, context.RGBA, 0, 0, 1, 1, 0)");
func1("context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, argument, 0, 1, 1, 0)");
func1("context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, argument, 1, 1, 0)");
func1("context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, argument, 1, 0)");
func1("context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, 0, argument, 0)");
func1("context.copyTexSubImage2D(context.TEXTURE_2D, argument, 0, 0, 0, 0, 0, 0)");
func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, argument, 0, 0, 0, 0, 0)");
func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, argument, 0, 0, 0, 0)");
func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, argument, 0, 0, 0)");
func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, argument, 0, 0)");
func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, argument, 0)");
func1("context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, 0, argument)");
func1("context.depthMask(argument)");
func1("context.depthRange(argument, 1)");
func1("context.depthRange(0, argument)");
func1("context.drawArrays(context.POINTS, argument, 1)");
func1("context.drawArrays(context.POINTS, 0, argument)");
//func1("context.drawElements(...)");
func1("context.enableVertexAttribArray(argument)");
func1("context.disableVertexAttribArray(argument)");
func2("context.getActiveAttrib(program, argument)");
func2("context.getActiveUniform(program, argument)");
func3("context.getParameter(argument)");
func1("context.lineWidth(argument)");
func1("context.polygonOffset(argument, 0)");
func1("context.polygonOffset(0, argument)");
//func1("context.readPixels(...)");
//func1("context.renderbufferStorage(...)");
func1("context.sampleCoverage(argument, 0)");
func1("context.sampleCoverage(0, argument)");
func1("context.scissor(argument, 0, 10, 10)");
func1("context.scissor(0, argument, 10, 10)");
func1("context.scissor(0, 0, argument, 10)");
func1("context.scissor(0, 0, 10, argument)");
func1("context.shaderSource(shader, argument)");
func1("context.stencilFunc(context.NEVER, argument, 255)");
func1("context.stencilFunc(context.NEVER, 0, argument)");
//func1("context.stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)");
func1("context.stencilMask(argument)");
//func1("context.stencilMaskSeparate(context.FRONT, argument);
//func1("context.texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView pixels)");
//func1("context.texParameterf(GLenum target, GLenum pname, GLfloat param)");
//func1("context.texParameteri(GLenum target, GLenum pname, GLint param)");
//func1("context.texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,GLsizei width, GLsizei height,GLenum format, GLenum type, ArrayBufferView pixels)");
func1("context.uniform1i(loc, argument)");
func1("context.uniform2i(loc, argument, 0)");
func1("context.uniform2i(loc, 0, argument)");
func1("context.uniform3i(loc, argument, 0, 0)");
func1("context.uniform3i(loc, 0, argument, 0)");
func1("context.uniform3i(loc, 0, 0, argument)");
func1("context.uniform4i(loc, argument, 0, 0, 0)");
func1("context.uniform4i(loc, 0, argument, 0, 0)");
func1("context.uniform4i(loc, 0, 0, argument, 0)");
func1("context.uniform4i(loc, 0, 0, 0, argument)");
func1("context.uniform1f(loc, argument)");
func1("context.uniform2f(loc, argument, 0)");
func1("context.uniform2f(loc, 0, argument)");
func1("context.uniform3f(loc, argument, 0, 0)");
func1("context.uniform3f(loc, 0, argument, 0)");
func1("context.uniform3f(loc, 0, 0, argument)");
func1("context.uniform4f(loc, argument, 0, 0, 0)");
func1("context.uniform4f(loc, 0, argument, 0, 0)");
func1("context.uniform4f(loc, 0, 0, argument, 0)");
func1("context.uniform4f(loc, 0, 0, 0, argument)");
}
successfullyParsed = true;
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>

Просмотреть файл

@ -6,13 +6,12 @@
<link rel="stylesheet" href="../resources/js-test-style.css"/> <link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script> <script src="../resources/js-test-pre.js"></script>
<script src="resources/webgl-test.js"></script> <script src="resources/webgl-test.js"></script>
<script src="resources/testrunner.js"></script>
</head> </head>
<body> <body>
<div id="description"></div> <div id="description"></div>
<div id="console"></div> <div id="console"></div>
<canvas id="canvas" width="2" height="2"> </canvas> <canvas id="canvas" width="2" height="2"> </canvas>
<script><!-- <script>
description("Tests to check user code cannot access uninitialized data from GL resources."); description("Tests to check user code cannot access uninitialized data from GL resources.");
var canvas = document.getElementById("canvas"); var canvas = document.getElementById("canvas");
@ -23,66 +22,71 @@ else
testPassed("Context created."); testPassed("Context created.");
/* object containing all tests in this testsuite */ debug("Reading an uninitialized texture should succeed with all bytes set to 0.");
var uninitializedTests = {
"Reading an uninitialized texture should succeed with all bytes set to 0." : function () {
this._width = 512;
this._height = 512;
this._bpp = 4;
this._expectedDataLength = this._width*this._height*this._bpp;
this.setup = function () { var width = 512;
var tex = gl.createTexture(); var height = 512;
gl.bindTexture(gl.TEXTURE_2D, tex); var bpp = 4;
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this._width, this._height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); var expectedDataLength = width*height*bpp;
// this can be quite undeterministic so to improve odds of seeing uninitialized data write bits var tex = gl.createTexture();
// into tex then delete texture then re-create one with same characteristics (driver will likely reuse mem) gl.bindTexture(gl.TEXTURE_2D, tex);
// with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15% of the time. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
var badData = new Uint8Array(this._expectedDataLength);
for (var i = 0; i < badData.length; ++i) badData[i] = i % 255;
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this._width, this._height, gl.RGBA, gl.UNSIGNED_BYTE, badData);
gl.finish(); // make sure it has been uploaded
gl.deleteTexture(tex);
gl.finish(); // make sure it has been deleted
var tex = gl.createTexture(); // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits
gl.bindTexture(gl.TEXTURE_2D, tex); // into tex then delete texture then re-create one with same characteristics (driver will likely reuse mem)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this._width, this._height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15% of the time.
var fb = gl.createFramebuffer(); var badData = new Uint8Array(expectedDataLength);
gl.bindFramebuffer(gl.FRAMEBUFFER, fb); for (var i = 0; i < badData.length; ++i)
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); badData[i] = i % 255;
this.data = new Uint8Array(this._width * this._height * 4); gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, badData);
gl.readPixels(0, 0, this._width, this._height, gl.RGBA, gl.UNSIGNED_BYTE, this.data); gl.finish(); // make sure it has been uploaded
};
this.expects = function () { gl.deleteTexture(tex);
if (this.data.length !== this._expectedDataLength) { gl.finish(); // make sure it has been deleted
debug("expected data length " + this._expectedDataLength + " but got " + this.data.length + " instead.");
return false; var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
data = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
if (data.length != expectedDataLength) {
testFailed("expected data length " + expectedDataLength + " but got " + data.length + " instead.");
} else {
var k = 0;
for (var i = 0; i < data.length; ++i) {
if (data[i] != 0) {
k++;
} }
for (var i = 0; i < this.data.length; ++i)
if (0 !== this.data[i]) {
debug("byte at offset " + i + " has value " + this.data[i]);
return false;
} }
return true;
}; if (k) {
testFailed("Found " + k + " non-zero bytes");
} else {
testPassed("All data initialized");
} }
//TODO: uninitialized vertex array buffer
//TODO: uninitialized vertex elements buffer
//TODO: uninitialized framebuffer? (implementations would need to do a GL clear at first binding?)
//TODO: uninitialized renderbuffer? (implementations would need to do a GL clear at first binding?)
//TODO: uninitialized uniform arrays?
} }
runTestsuite(uninitializedTests); glErrorShouldBe(gl, gl.NO_ERROR);
//TODO: uninitialized vertex array buffer
//TODO: uninitialized vertex elements buffer
//TODO: uninitialized framebuffer? (implementations would need to do a GL clear at first binding?)
//TODO: uninitialized renderbuffer? (implementations would need to do a GL clear at first binding?)
//TODO: uninitialized uniform arrays?
debug(""); debug("");
successfullyParsed = true; successfullyParsed = true;
--></script> </script>
<script src="../resources/js-test-post.js"></script> <script src="../resources/js-test-post.js"></script>
<script> <script>
</script> </script>

Просмотреть файл

@ -0,0 +1,120 @@
<!--
Copyright (c) 2010 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>WebGL GLES2 difference test.</title>
<link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/js-test-pre.js"></script>
<script src="resources/webgl-test.js"></script>
<script src="resources/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script>
var wtu = WebGLTestUtils;
description("Tests the a few differences between WebGL and GLES2");
var gl = wtu.create3DContext();
gl.blendFunc(gl.CONSTANT_COLOR, gl.CONSTANT_ALPHA);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFunc(gl.ONE_MINUS_CONSTANT_COLOR, gl.CONSTANT_ALPHA);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFunc(gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_ALPHA);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFunc(gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_ALPHA);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFunc(gl.CONSTANT_ALPHA, gl.CONSTANT_COLOR);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFunc(gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_COLOR);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFunc(gl.ONE_MINUS_CONSTANT_ALPHA, gl.CONSTANT_COLOR);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFunc(gl.ONE_MINUS_CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_COLOR);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFuncSeparate(gl.CONSTANT_COLOR, gl.CONSTANT_ALPHA, gl.ONE, gl.ZERO);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFuncSeparate(gl.ONE_MINUS_CONSTANT_COLOR, gl.CONSTANT_ALPHA, gl.ONE, gl.ZERO);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFuncSeparate(gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_ALPHA, gl.ONE, gl.ZERO);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFuncSeparate(gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_ALPHA, gl.ONE, gl.ZERO);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFuncSeparate(gl.CONSTANT_ALPHA, gl.CONSTANT_COLOR, gl.ONE, gl.ZERO);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFuncSeparate(gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE, gl.ZERO);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFuncSeparate(gl.ONE_MINUS_CONSTANT_ALPHA, gl.CONSTANT_COLOR, gl.ONE, gl.ZERO);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.blendFuncSeparate(gl.ONE_MINUS_CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_COLOR, gl.ONE, gl.ZERO);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"constant color and constant alpha cannot be used together as source and destination factors in the blend function");
gl.depthRange(20, 10);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"depthRange should generate INVALID_OPERATION if zNear is greater than zFar");
gl.stencilMask(255);
glErrorShouldBe(gl, gl.NO_ERROR,
"stencilMask should generate no error");
gl.stencilMaskSeparate(gl.FRONT, 1);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"a different mask value for front and back facing is illegal");
gl.stencilMaskSeparate(gl.BACK, 1);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"a different mask value for front and back facing is illegal");
gl.stencilFunc(gl.ALWAYS, 0, 255);
glErrorShouldBe(gl, gl.NO_ERROR,
"stencilFunc should generate no error");
gl.stencilFuncSeparate(gl.FRONT, gl.ALWAYS, 1, 255);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"a different reference value for front and back facing is illegal");
gl.stencilFuncSeparate(gl.BACK, gl.ALWAYS, 1, 255);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"a different reference value for front and back facing is illegal");
gl.stencilFuncSeparate(gl.FRONT, gl.ALWAYS, 0, 1);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"a different mask value for front and back facing is illegal");
gl.stencilFuncSeparate(gl.BACK, gl.ALWAYS, 0, 1);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"a different mask value for front and back facing is illegal");
shouldBeUndefined(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
shouldBeUndefined(gl.IMPLEMENTATION_COLOR_READ_TYPE);
shouldBe("gl.getParameter(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL)", "gl.BROWSER_DEFAULT_WEBGL");
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
shouldBe("gl.getParameter(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL)", "gl.NONE");
glErrorShouldBe(gl, gl.NO_ERROR,
"set/get UNPACK_COLORSPACE_CONVERSION_WEBGL should generate no error");
successfullyParsed = true;
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>

Просмотреть файл

@ -93,6 +93,7 @@ static const char* const sEventNames[] = {
#endif // MOZ_MEDIA #endif // MOZ_MEDIA
"MozAfterPaint", "MozAfterPaint",
"MozBeforePaint", "MozBeforePaint",
"MozBeforeResize",
"MozSwipeGesture", "MozSwipeGesture",
"MozMagnifyGestureStart", "MozMagnifyGestureStart",
"MozMagnifyGestureUpdate", "MozMagnifyGestureUpdate",
@ -1316,6 +1317,8 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return sEventNames[eDOMEvents_afterpaint]; return sEventNames[eDOMEvents_afterpaint];
case NS_BEFOREPAINT: case NS_BEFOREPAINT:
return sEventNames[eDOMEvents_beforepaint]; return sEventNames[eDOMEvents_beforepaint];
case NS_BEFORERESIZE_EVENT:
return sEventNames[eDOMEvents_beforeresize];
case NS_SIMPLE_GESTURE_SWIPE: case NS_SIMPLE_GESTURE_SWIPE:
return sEventNames[eDOMEvents_MozSwipeGesture]; return sEventNames[eDOMEvents_MozSwipeGesture];
case NS_SIMPLE_GESTURE_MAGNIFY_START: case NS_SIMPLE_GESTURE_MAGNIFY_START:

Просмотреть файл

@ -175,6 +175,7 @@ public:
#endif #endif
eDOMEvents_afterpaint, eDOMEvents_afterpaint,
eDOMEvents_beforepaint, eDOMEvents_beforepaint,
eDOMEvents_beforeresize,
eDOMEvents_MozSwipeGesture, eDOMEvents_MozSwipeGesture,
eDOMEvents_MozMagnifyGestureStart, eDOMEvents_MozMagnifyGestureStart,
eDOMEvents_MozMagnifyGestureUpdate, eDOMEvents_MozMagnifyGestureUpdate,

Просмотреть файл

@ -110,6 +110,8 @@ _CHROME_FILES = \
test_bug415498.xul \ test_bug415498.xul \
bug415498-doc1.html \ bug415498-doc1.html \
bug415498-doc2.html \ bug415498-doc2.html \
bug602962.xul \
test_bug602962.xul \
$(NULL) $(NULL)
libs:: $(_TEST_FILES) libs:: $(_TEST_FILES)

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window onload="window.opener.doTest()" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<scrollbox id="page-scrollbox" style="border: 1px solid red; background-color: black;overflow: auto" flex="1">
<box id="page-box" style="border: 1px solid green;"/>
</scrollbox>
</window>

Просмотреть файл

@ -0,0 +1,94 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=602962
-->
<window title="Mozilla Bug 602962" onload="openWindow()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<title>Test for Bug 602962</title>
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"/>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602962">Mozilla Bug 602962</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
</body>
<script class="testbody" type="application/javascript;version=1.8"><![CDATA[
/** Test for Bug 602962 **/
var scrollbox, sbo, content;
var scrollX = 0, scrollY = 0;
var mozBeforeResizeHasFired = false;
var oldWidth = 0, oldHeight = 0;
var win = null;
function openWindow() {
win = window.open("chrome://mochitests/content/chrome/content/events/test/bug602962.xul", "_blank", "width=600,height=600");
}
function doTest() {
scrollbox = win.document.getElementById("page-scrollbox");
sbo = scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
content = win.document.getElementById("page-box");
content.style.width = 400 + "px";
win.addEventListener("resize", function() {
win.removeEventListener("resize", arguments.callee, false);
sbo.scrollBy(200, 0);
setTimeout(function() { resize(); }, 0);
}, false);
oldWidth = win.outerWidth;
oldHeight = win.outerHeight;
win.resizeTo(200, 400);
}
function resize() {
win.addEventListener("MozBeforeResize", function() {
win.removeEventListener("MozBeforeResize", arguments.callee, false);
mozBeforeResizeHasFired = true;
let x = {}, y = {};
sbo.getPosition(x, y);
scrollX = x.value, scrollY = y.value;
is(scrollX, 200, "Scroll X should not have changed yet");
is(scrollY, 0, "Scroll Y should not have changed yet");
}, false);
win.addEventListener("resize", function() {
content.style.width = (oldWidth + 400) + "px";
win.removeEventListener("resize", arguments.callee, true);
setTimeout(function() {
finish();
}, 0);
}, true);
win.resizeTo(oldWidth, oldHeight);
}
function finish() {
is(mozBeforeResizeHasFired, true, "The MozBeforeResize event should already have fired");
sbo.scrollBy(scrollX, scrollY);
let x = {}, y = {};
sbo.getPosition(x, y);
is(x.value, 200, "Scroll X should have been restored to the value before the resize");
is(y.value, 0, "Scroll Y should have been restored to the value before the resize");
is(win.outerWidth, oldWidth, "Width should be resized");
is(win.outerHeight, oldHeight, "Height should be resized");
win.close();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
]]></script>
</window>

Просмотреть файл

@ -169,7 +169,7 @@ public:
protected: protected:
nsIntSize GetWidthHeight(); nsIntSize GetWidthHeight();
nsresult UpdateContext(); nsresult UpdateContext(nsIPropertyBag *aNewContextOptions = nsnull);
nsresult ExtractData(const nsAString& aType, nsresult ExtractData(const nsAString& aType,
const nsAString& aOptions, const nsAString& aOptions,
char*& aData, char*& aData,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше