Bug 1020548 - update aria-orientation impl to ARIA 1.1, r=tbsaunde, sr=neil
authorAlexander Surkov <surkov.alexander@gmail.com>
Mon, 11 Aug 2014 08:13:44 -0400
changeset 198846 2ecfd77b0b8c74f16ecf556ca7e0fa2050c459a9
parent 198845 9b5ee0d5af09dffd29202af2e40818a7875ce499
child 198847 2e0e4d841f0f45c0958022e78f6a565764dc7e75
push id47505
push usersurkov.alexander@gmail.com
push dateMon, 11 Aug 2014 12:12:44 +0000
treeherdermozilla-inbound@2ecfd77b0b8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde, neil
bugs1020548
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1020548 - update aria-orientation impl to ARIA 1.1, r=tbsaunde, sr=neil
accessible/base/ARIAMap.cpp
accessible/base/ARIAMap.h
accessible/base/ARIAStateMap.cpp
accessible/generic/Accessible.cpp
accessible/tests/mochitest/states/test_aria.html
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -117,19 +117,20 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   { // combobox
     &nsGkAtoms::combobox,
     roles::COMBOBOX,
     kUseMapRole,
     eNoValue,
     eOpenCloseAction,
     eNoLiveAttr,
     kGenericAccType,
-    states::COLLAPSED | states::HASPOPUP,
+    states::COLLAPSED | states::HASPOPUP | states::VERTICAL,
     eARIAAutoComplete,
-    eARIAReadonly
+    eARIAReadonly,
+    eARIAOrientation
   },
   { // dialog
     &nsGkAtoms::dialog,
     roles::DIALOG,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
@@ -256,20 +257,21 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   { // listbox
     &nsGkAtoms::listbox,
     roles::LISTBOX,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eListControl | eSelect,
-    kNoReqStates,
+    states::VERTICAL,
     eARIAMultiSelectable,
     eARIAReadonly,
-    eFocusableUntilDisabled
+    eFocusableUntilDisabled,
+    eARIAOrientation
   },
   { // listitem
     &nsGkAtoms::listitem,
     roles::LISTITEM,
     kUseMapRole,
     eNoValue,
     eNoAction, // XXX: should depend on state, parent accessible
     eNoLiveAttr,
@@ -310,27 +312,29 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     &nsGkAtoms::menu,
     roles::MENUPOPUP,
     kUseMapRole,
     eNoValue,
     eNoAction, // XXX: technically accessibles of menupopup role haven't
                // any action, but menu can be open or close.
     eNoLiveAttr,
     kGenericAccType,
-    kNoReqStates
+    states::VERTICAL,
+    eARIAOrientation
   },
   { // menubar
     &nsGkAtoms::menubar,
     roles::MENUBAR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
-    kNoReqStates
+    states::HORIZONTAL,
+    eARIAOrientation
   },
   { // menuitem
     &nsGkAtoms::menuitem,
     roles::MENUITEM,
     kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
@@ -417,17 +421,18 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   { // radiogroup
     &nsGkAtoms::radiogroup,
     roles::GROUPING,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
-    kNoReqStates
+    kNoReqStates,
+    eARIAOrientation
   },
   { // region
     &nsGkAtoms::region,
     roles::PANE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
@@ -470,40 +475,40 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   { // scrollbar
     &nsGkAtoms::scrollbar,
     roles::SCROLLBAR,
     kUseMapRole,
     eHasValueMinMax,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
-    kNoReqStates,
+    states::VERTICAL,
     eARIAOrientation,
     eARIAReadonly
   },
   { // separator
     &nsGkAtoms::separator_,
     roles::SEPARATOR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
-    kNoReqStates,
+    states::HORIZONTAL,
     eARIAOrientation
   },
   { // slider
     &nsGkAtoms::slider,
     roles::SLIDER,
     kUseMapRole,
     eHasValueMinMax,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
-    kNoReqStates,
+    states::HORIZONTAL,
     eARIAOrientation,
     eARIAReadonly
   },
   { // spinbutton
     &nsGkAtoms::spinbutton,
     roles::SPINBUTTON,
     kUseMapRole,
     eHasValueMinMax,
@@ -537,17 +542,18 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   { // tablist
     &nsGkAtoms::tablist,
     roles::PAGETABLIST,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eSelect,
-    kNoReqStates
+    states::HORIZONTAL,
+    eARIAOrientation
   },
   { // tabpanel
     &nsGkAtoms::tabpanel,
     roles::PROPERTYPAGE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
@@ -579,17 +585,18 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   { // toolbar
     &nsGkAtoms::toolbar,
     roles::TOOLBAR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
-    kNoReqStates
+    states::HORIZONTAL,
+    eARIAOrientation
   },
   { // tooltip
     &nsGkAtoms::tooltip,
     roles::TOOLTIP,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
@@ -599,33 +606,35 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   { // tree
     &nsGkAtoms::tree,
     roles::OUTLINE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eSelect,
-    kNoReqStates,
+    states::VERTICAL,
     eARIAReadonly,
     eARIAMultiSelectable,
-    eFocusableUntilDisabled
+    eFocusableUntilDisabled,
+    eARIAOrientation
   },
   { // treegrid
     &nsGkAtoms::treegrid,
     roles::TREE_TABLE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eSelect | eTable,
-    kNoReqStates,
+    states::VERTICAL,
     eARIAReadonlyOrEditable,
     eARIAMultiSelectable,
-    eFocusableUntilDisabled
+    eFocusableUntilDisabled,
+    eARIAOrientation
   },
   { // treeitem
     &nsGkAtoms::treeitem,
     roles::OUTLINEITEM,
     kUseMapRole,
     eNoValue,
     eActivateAction, // XXX: should expose second 'expand/collapse' action based
                      // on states
--- a/accessible/base/ARIAMap.h
+++ b/accessible/base/ARIAMap.h
@@ -175,16 +175,17 @@ struct nsRoleMapEntry
   // ARIA properties supported for this role
   // (in other words, the aria-foo attribute to nsIAccessibleStates mapping rules)
   // Currently you cannot have unlimited mappings, because
   // a variable sized array would not allow the use of
   // C++'s struct initialization feature.
   mozilla::a11y::aria::EStateRule attributeMap1;
   mozilla::a11y::aria::EStateRule attributeMap2;
   mozilla::a11y::aria::EStateRule attributeMap3;
+  mozilla::a11y::aria::EStateRule attributeMap4;
 };
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // ARIA map
 
 /**
  *  These provide the mappings for WAI-ARIA roles, states and properties using
--- a/accessible/base/ARIAStateMap.cpp
+++ b/accessible/base/ARIAStateMap.cpp
@@ -14,49 +14,28 @@ using namespace mozilla;
 using namespace mozilla::a11y;
 using namespace mozilla::a11y::aria;
 
 /**
  * Used to store state map rule data for ARIA attribute of enum type.
  */
 struct EnumTypeData
 {
-  EnumTypeData(nsIAtom* aAttrName,
-               nsIAtom** aValue1, uint64_t aState1,
-               nsIAtom** aValue2, uint64_t aState2,
-               nsIAtom** aValue3 = 0, uint64_t aState3 = 0) :
-    mState1(aState1), mState2(aState2), mState3(aState3), mDefaultState(0),
-    mAttrName(aAttrName), mValue1(aValue1), mValue2(aValue2), mValue3(aValue3),
-    mNullValue(nullptr)
-  { }
-
-  EnumTypeData(nsIAtom* aAttrName, uint64_t aDefaultState,
-               nsIAtom** aValue1, uint64_t aState1) :
-    mState1(aState1), mState2(0), mState3(0), mDefaultState(aDefaultState),
-    mAttrName(aAttrName), mValue1(aValue1), mValue2(nullptr), mValue3(nullptr),
-    mNullValue(nullptr)
-  { }
-
-  // States applied if corresponding enum values are matched.
-  const uint64_t mState1;
-  const uint64_t mState2;
-  const uint64_t mState3;
-
-  // Default state if no one enum value is matched.
-  const uint64_t mDefaultState;
-
   // ARIA attribute name.
   nsIAtom* const mAttrName;
 
   // States if the attribute value is matched to the enum value. Used as
-  // nsIContent::AttrValuesArray.
-  nsIAtom* const* const mValue1;
-  nsIAtom* const* const mValue2;
-  nsIAtom* const* const mValue3;
-  nsIAtom* const* const mNullValue;
+  // nsIContent::AttrValuesArray, last item must be nullptr.
+  nsIAtom* const* const mValues[4];
+
+  // States applied if corresponding enum values are matched.
+  const uint64_t mStates[3];
+
+  // States to clear in case of match.
+  const uint64_t mClearState;
 };
 
 enum ETokenType
 {
   eBoolType = 0,
   eMixedType = 1, // can take 'mixed' value
   eDefinedIfAbsent = 2 // permanent and false state are applied if absent
 };
@@ -103,32 +82,39 @@ static void MapTokenType(dom::Element* a
                          const TokenTypeData& aData);
 
 bool
 aria::MapToState(EStateRule aRule, dom::Element* aElement, uint64_t* aState)
 {
   switch (aRule) {
     case eARIAAutoComplete:
     {
-      static const EnumTypeData data(
+      static const EnumTypeData data = {
         nsGkAtoms::aria_autocomplete,
-        &nsGkAtoms::inlinevalue, states::SUPPORTS_AUTOCOMPLETION,
-        &nsGkAtoms::list, states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION,
-        &nsGkAtoms::both, states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION);
+        { &nsGkAtoms::inlinevalue,
+          &nsGkAtoms::list,
+          &nsGkAtoms::both, nullptr },
+        { states::SUPPORTS_AUTOCOMPLETION,
+          states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION,
+          states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION }, 0
+      };
 
       MapEnumType(aElement, aState, data);
       return true;
     }
 
     case eARIABusy:
     {
-      static const EnumTypeData data(
+      static const EnumTypeData data = {
         nsGkAtoms::aria_busy,
-        &nsGkAtoms::_true, states::BUSY,
-        &nsGkAtoms::error, states::INVALID);
+        { &nsGkAtoms::_true,
+          &nsGkAtoms::error, nullptr },
+        { states::BUSY,
+          states::INVALID }, 0
+      };
 
       MapEnumType(aElement, aState, data);
       return true;
     }
 
     case eARIACheckableBool:
     {
       static const TokenTypeData data(
@@ -216,33 +202,26 @@ aria::MapToState(EStateRule aRule, dom::
         0, states::MULTISELECTABLE | states::EXTSELECTABLE);
 
       MapTokenType(aElement, aState, data);
       return true;
     }
 
     case eARIAOrientation:
     {
-      if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_orientation,
-                                NS_LITERAL_STRING("horizontal"), eCaseMatters)) {
-        *aState &= ~states::VERTICAL;
-        *aState |= states::HORIZONTAL;
-      } else if (aElement->AttrValueIs(kNameSpaceID_None,
-                                       nsGkAtoms::aria_orientation,
-                                       NS_LITERAL_STRING("vertical"),
-                                       eCaseMatters)) {
-        *aState &= ~states::HORIZONTAL;
-        *aState |= states::VERTICAL;
-      } else {
-        NS_ASSERTION(!(*aState & (states::HORIZONTAL | states::VERTICAL)),
-                     "orientation state on role with default aria-orientation!");
-        *aState |= GetRoleMap(aElement)->Is(nsGkAtoms::scrollbar) ?
-          states::VERTICAL : states::HORIZONTAL;
-      }
+      static const EnumTypeData data = {
+        nsGkAtoms::aria_orientation,
+        { &nsGkAtoms::horizontal,
+          &nsGkAtoms::vertical, nullptr },
+        { states::HORIZONTAL,
+          states::VERTICAL },
+        states::HORIZONTAL | states::VERTICAL
+      };
 
+      MapEnumType(aElement, aState, data);
       return true;
     }
 
     case eARIAPressed:
     {
       static const TokenTypeData data(
         nsGkAtoms::aria_pressed, eMixedType,
         0, states::PRESSED);
@@ -342,29 +321,27 @@ aria::MapToState(EStateRule aRule, dom::
       return false;
   }
 }
 
 static void
 MapEnumType(dom::Element* aElement, uint64_t* aState, const EnumTypeData& aData)
 {
   switch (aElement->FindAttrValueIn(kNameSpaceID_None, aData.mAttrName,
-                                    &aData.mValue1, eCaseMatters)) {
+                                    aData.mValues, eCaseMatters)) {
     case 0:
-      *aState |= aData.mState1;
+      *aState = (*aState & ~aData.mClearState) | aData.mStates[0];
       return;
     case 1:
-      *aState |= aData.mState2;
+      *aState = (*aState & ~aData.mClearState) | aData.mStates[1];
       return;
     case 2:
-      *aState |= aData.mState3;
+      *aState = (*aState & ~aData.mClearState) | aData.mStates[2];
       return;
   }
-
-  *aState |= aData.mDefaultState;
 }
 
 static void
 MapTokenType(dom::Element* aElement, uint64_t* aState,
              const TokenTypeData& aData)
 {
   if (nsAccUtils::HasDefinedARIAToken(aElement, aData.mAttrName)) {
     if ((aData.mType & eMixedType) &&
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -1587,18 +1587,19 @@ Accessible::ApplyARIAState(uint64_t* aSt
     aria::MapToState(aria::eARIAPressed, element, aState);
 
   if (!mRoleMapEntry)
     return;
 
   *aState |= mRoleMapEntry->state;
 
   if (aria::MapToState(mRoleMapEntry->attributeMap1, element, aState) &&
-      aria::MapToState(mRoleMapEntry->attributeMap2, element, aState))
-    aria::MapToState(mRoleMapEntry->attributeMap3, element, aState);
+      aria::MapToState(mRoleMapEntry->attributeMap2, element, aState) &&
+      aria::MapToState(mRoleMapEntry->attributeMap3, element, aState))
+    aria::MapToState(mRoleMapEntry->attributeMap4, element, aState);
 
   // ARIA gridcell inherits editable/readonly states from the grid until it's
   // overridden.
   if ((mRoleMapEntry->Is(nsGkAtoms::gridcell) ||
        mRoleMapEntry->Is(nsGkAtoms::columnheader) ||
        mRoleMapEntry->Is(nsGkAtoms::rowheader)) &&
       !(*aState & (states::READONLY | states::EDITABLE))) {
     const TableCellAccessible* cell = AsTableCell();
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -43,17 +43,17 @@
       }
 
       // Iterate over its children to see if the state got propagated.
       var children = null;
       try {
         children = acc.children;
       } catch(e) {}
       ok(children, "Could not get children for " + aAccOrElmOrID +"!");
-  
+
       if (children) {
         for (var i = 0; i < children.length; i++) {
           var childAcc = children.queryElementAt(i, nsIAccessible);
           testAriaDisabledTree(childAcc);
         }
       }
     }
 
@@ -208,26 +208,53 @@
       testStates("aria_link_anchor", STATE_SELECTABLE);
 
       // some weak landmarks
       testStates("aria_main_link", STATE_LINKED);
       testStates("aria_navigation_link", STATE_LINKED);
       testStates("aria_main_anchor", STATE_SELECTABLE);
       testStates("aria_navigation_anchor", STATE_SELECTABLE);
 
-      // aria-orientation (applied to scrollbar, separator, slider)
+      // aria-orientation
+      testStates("aria_combobox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_hcombobox", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vcombobox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_listbox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_hlistbox", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vlistbox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_menu", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_hmenu", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vmenu", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_menubar", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_hmenubar", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vmenubar", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_radiogroup", 0, 0, 0, EXT_STATE_HORIZONTAL | EXT_STATE_VERTICAL);
+      testStates("aria_hradiogroup", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vradiogroup", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
       testStates("aria_scrollbar", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
       testStates("aria_hscrollbar", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
       testStates("aria_vscrollbar", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
       testStates("aria_separator", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
       testStates("aria_hseparator", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
       testStates("aria_vseparator", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
       testStates("aria_slider", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
       testStates("aria_hslider", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
       testStates("aria_vslider", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_tablist", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_htablist", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vtablist", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_toolbar", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_htoolbar", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vtoolbar", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_tree", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_htree", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vtree", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_treegrid", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_htreegrid", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
+      testStates("aria_vtreegrid", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
 
       // indeterminate ARIA progressbars (no aria-valuenow or aria-valuetext attribute)
       // should expose mixed state
       testStates("aria_progressbar", STATE_MIXED);
       testStates("aria_progressbar_valuenow", 0, 0, STATE_MIXED);
       testStates("aria_progressbar_valuetext", 0, 0, STATE_MIXED);
 
       testStates("aria_listbox", STATE_FOCUSABLE);
@@ -493,26 +520,54 @@
   <a id="aria_navigation_link" role="navigation" href="foo">nav</a>
 
   <!-- landmarks: anchors -->
   <a id="aria_application_anchor" role="application" name="app_anchor">app</a>
   <a id="aria_main_anchor" role="main" name="main_anchor">main</a>
   <a id="aria_navigation_anchor" role="navigation" name="nav_anchor">nav</a>
 
   <!-- aria-orientation -->
+  <div id="aria_combobox" role="combobox">combobox</div>
+  <div id="aria_hcombobox" role="combobox" aria-orientation="horizontal">horizontal combobox</div>
+  <div id="aria_vcombobox" role="combobox" aria-orientation="vertical">vertical combobox</div>
+  <div id="aria_listbox" role="listbox">listbox</div>
+  <div id="aria_hlistbox" role="listbox" aria-orientation="horizontal">horizontal listbox</div>
+  <div id="aria_vlistbox" role="listbox" aria-orientation="vertical">vertical listbox</div>
+  <div id="aria_menu" role="menu">menu</div>
+  <div id="aria_hmenu" role="menu" aria-orientation="horizontal">horizontal menu</div>
+  <div id="aria_vmenu" role="menu" aria-orientation="vertical">vertical menu</div>
+  <div id="aria_menubar" role="menubar">menubar</div>
+  <div id="aria_hmenubar" role="menubar" aria-orientation="horizontal">horizontal menubar</div>
+  <div id="aria_vmenubar" role="menubar" aria-orientation="vertical">vertical menubar</div>
+  <div id="aria_radiogroup" role="radiogroup">radiogroup</div>
+  <div id="aria_hradiogroup" role="radiogroup" aria-orientation="horizontal">horizontal radiogroup</div>
+  <div id="aria_vradiogroup" role="radiogroup" aria-orientation="vertical">vertical radiogroup</div>
   <div id="aria_scrollbar" role="scrollbar">scrollbar</div>
   <div id="aria_hscrollbar" role="scrollbar" aria-orientation="horizontal">horizontal scrollbar</div>
   <div id="aria_vscrollbar" role="scrollbar" aria-orientation="vertical">vertical scrollbar</div>
   <div id="aria_separator" role="separator">separator</div>
   <div id="aria_hseparator" role="separator" aria-orientation="horizontal">horizontal separator</div>
   <div id="aria_vseparator" role="separator" aria-orientation="vertical">vertical separator</div>
   <div id="aria_slider" role="slider">slider</div>
   <div id="aria_hslider" role="slider" aria-orientation="horizontal">horizontal slider</div>
   <div id="aria_vslider" role="slider" aria-orientation="vertical">vertical slider</div>
-  
+
+  <div id="aria_tablist" role="tablist">tablist</div>
+  <div id="aria_htablist" role="tablist" aria-orientation="horizontal">horizontal tablist</div>
+  <div id="aria_vtablist" role="tablist" aria-orientation="vertical">vertical tablist</div>
+  <div id="aria_toolbar" role="toolbar">toolbar</div>
+  <div id="aria_htoolbar" role="toolbar" aria-orientation="horizontal">horizontal toolbar</div>
+  <div id="aria_vtoolbar" role="toolbar" aria-orientation="vertical">vertical toolbar</div>
+  <div id="aria_tree" role="tree">tree</div>
+  <div id="aria_htree" role="tree" aria-orientation="horizontal">horizontal tree</div>
+  <div id="aria_vtree" role="tree" aria-orientation="vertical">vertical tree</div>
+  <div id="aria_treegrid" role="treegrid">treegrid</div>
+  <div id="aria_htreegrid" role="treegrid" aria-orientation="horizontal">horizontal treegrid</div>
+  <div id="aria_vtreegrid" role="treegrid" aria-orientation="vertical">vertical treegrid</div>
+
   <!-- indeterminate ARIA progressbars should expose mixed state -->
   <div id="aria_progressbar" role="progressbar"></div>
   <div id="aria_progressbar_valuenow" role="progressbar" aria-valuenow="1"></div>
   <div id="aria_progressbar_valuetext" role="progressbar" aria-valuetext="value"></div>
 
   <!-- ARIA select widget should expose focusable state regardless the way they manage its children -->
   <div id="aria_listbox" role="listbox">
     <div role="option" tabindex="0">A</div>