diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index 363a89add07..3037c1028a6 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -907,8 +907,10 @@ static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pC
static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, LONG *p)
{
HTMLElement *This = impl_from_IHTMLElement(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ return get_elem_source_index(This, p);
}
static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
diff --git a/dlls/mshtml/htmlelemcol.c b/dlls/mshtml/htmlelemcol.c
index 8fd61edd2bf..1542926c330 100644
--- a/dlls/mshtml/htmlelemcol.c
+++ b/dlls/mshtml/htmlelemcol.c
@@ -17,6 +17,7 @@
*/
#include
+#include
#define COBJMACROS
@@ -746,6 +747,75 @@ IHTMLElementCollection *create_collection_from_htmlcol(HTMLDocumentNode *doc, ns
return HTMLElementCollection_Create(buf.buf, buf.len);
}
+HRESULT get_elem_source_index(HTMLElement *elem, LONG *ret)
+{
+ elem_vector_t buf = {NULL, 0, 8};
+ nsIDOMNode *parent_node, *iter;
+ UINT16 parent_type;
+ HTMLDOMNode *node;
+ int i;
+ nsresult nsres;
+ HRESULT hres;
+
+ iter = elem->node.nsnode;
+ nsIDOMNode_AddRef(iter);
+
+ /* Find document or document fragment parent. */
+ while(1) {
+ nsres = nsIDOMNode_GetParentNode(iter, &parent_node);
+ nsIDOMNode_Release(iter);
+ assert(nsres == NS_OK);
+ if(!parent_node)
+ break;
+
+ nsres = nsIDOMNode_GetNodeType(parent_node, &parent_type);
+ assert(nsres == NS_OK);
+
+ if(parent_type != ELEMENT_NODE) {
+ if(parent_type != DOCUMENT_NODE && parent_type != DOCUMENT_FRAGMENT_NODE)
+ FIXME("Unexpected parent_type %d\n", parent_type);
+ break;
+ }
+
+ iter = parent_node;
+ }
+
+ if(!parent_node) {
+ *ret = -1;
+ return S_OK;
+ }
+
+ hres = get_node(elem->node.doc, parent_node, TRUE, &node);
+ nsIDOMNode_Release(parent_node);
+ if(FAILED(hres))
+ return hres;
+
+
+ /* Create all children collection and find the element in it.
+ * This could be optimized if we ever find the reason. */
+ buf.buf = heap_alloc(buf.size*sizeof(*buf.buf));
+ if(!buf.buf) {
+ IHTMLDOMNode_Release(&node->IHTMLDOMNode_iface);
+ return E_OUTOFMEMORY;
+ }
+
+ create_all_list(elem->node.doc, node, &buf);
+
+ for(i=0; i < buf.len; i++) {
+ if(buf.buf[i] == elem)
+ break;
+ }
+ IHTMLDOMNode_Release(&node->IHTMLDOMNode_iface);
+ heap_free(buf.buf);
+ if(i == buf.len) {
+ FIXME("The element is not in parent's child list?\n");
+ return E_UNEXPECTED;
+ }
+
+ *ret = i;
+ return S_OK;
+}
+
static IHTMLElementCollection *HTMLElementCollection_Create(HTMLElement **elems, DWORD len)
{
HTMLElementCollection *ret = heap_alloc_zero(sizeof(HTMLElementCollection));
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 19e424f4288..78d61f08e38 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -961,6 +961,7 @@ HRESULT wrap_iface(IUnknown*,IUnknown*,IUnknown**) DECLSPEC_HIDDEN;
IHTMLElementCollection *create_all_collection(HTMLDOMNode*,BOOL) DECLSPEC_HIDDEN;
IHTMLElementCollection *create_collection_from_nodelist(HTMLDocumentNode*,nsIDOMNodeList*) DECLSPEC_HIDDEN;
IHTMLElementCollection *create_collection_from_htmlcol(HTMLDocumentNode*,nsIDOMHTMLCollection*) DECLSPEC_HIDDEN;
+HRESULT get_elem_source_index(HTMLElement*,LONG*) DECLSPEC_HIDDEN;
nsresult get_elem_attr_value(nsIDOMHTMLElement*,const WCHAR*,nsAString*,const PRUnichar**) DECLSPEC_HIDDEN;
HRESULT elem_string_attr_getter(HTMLElement*,const WCHAR*,BOOL,BSTR*) DECLSPEC_HIDDEN;
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index 17f39ce70d6..9f352f6ad40 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -1142,6 +1142,17 @@ static void _test_elem_offset(unsigned line, IUnknown *unk, const char *parent_t
IHTMLElement_Release(elem);
}
+#define test_elem_source_index(a,b) _test_elem_source_index(__LINE__,a,b)
+static void _test_elem_source_index(unsigned line, IHTMLElement *elem, int index)
+{
+ LONG l = 0xdeadbeef;
+ HRESULT hres;
+
+ hres = IHTMLElement_get_sourceIndex(elem, &l);
+ ok_(__FILE__,line)(hres == S_OK, "get_sourceIndex failed: %08x\n", hres);
+ ok_(__FILE__,line)(l == index, "sourceIndex = %d, expected %d\n", l, index);
+}
+
#define get_doc_node(d) _get_doc_node(__LINE__,d)
static IHTMLDocument2 *_get_doc_node(unsigned line, IHTMLDocument2 *doc)
{
@@ -2105,6 +2116,26 @@ static void _test_range_parent(unsigned line, IHTMLTxtRange *range, elem_type_t
IHTMLElement_Release(elem);
}
+#define get_elem_col_item_idx(a,b) _get_elem_col_item_idx(__LINE__,a,b)
+static IHTMLElement *_get_elem_col_item_idx(unsigned line, IHTMLElementCollection *col, int i)
+{
+ VARIANT name, index;
+ IHTMLElement *elem;
+ IDispatch *disp;
+ HRESULT hres;
+
+ V_VT(&index) = VT_EMPTY;
+ V_VT(&name) = VT_I4;
+ V_I4(&name) = i;
+ hres = IHTMLElementCollection_item(col, name, index, &disp);
+ ok_(__FILE__,line)(hres == S_OK, "item failed: %08x\n", hres);
+ ok_(__FILE__,line)(disp != NULL, "disp == NULL\n");
+
+ elem = _get_elem_iface(line, (IUnknown*)disp);
+ IDispatch_Release(disp);
+ return elem;
+}
+
#define test_elem_collection(c,t,l) _test_elem_collection(__LINE__,c,t,l)
static void _test_elem_collection(unsigned line, IUnknown *unk,
const elem_type_t *elem_types, LONG exlen)
@@ -2290,20 +2321,8 @@ static void _test_elem_getelembytag(unsigned line, IUnknown *unk, elem_type_t ty
HeapFree(GetProcessHeap(), 0, types);
- if(ret) {
- IDispatch *disp;
- VARIANT v;
-
- V_VT(&v) = VT_I4;
- V_I4(&v) = 0;
- disp = NULL;
- hres = IHTMLElementCollection_item(col, v, v, &disp);
- ok(hres == S_OK, "item failed: %08x\n", hres);
- ok(disp != NULL, "disp == NULL\n");
- *ret = _get_elem_iface(line, (IUnknown*)disp);
- IDispatch_Release(disp);
- }
-
+ if(ret)
+ *ret = get_elem_col_item_idx(col, 0);
IHTMLElementCollection_Release(col);
}
@@ -6909,6 +6928,15 @@ static void test_elems(IHTMLDocument2 *doc)
ok(hres == S_OK, "get_all failed: %08x\n", hres);
test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
test_elem_col_item(col, "x", item_types, sizeof(item_types)/sizeof(item_types[0]));
+
+ elem = get_elem_col_item_idx(col, 0);
+ test_elem_source_index(elem, 0);
+ IHTMLElement_Release(elem);
+
+ elem = get_elem_col_item_idx(col, 3);
+ test_elem_source_index(elem, 3);
+ IHTMLElement_Release(elem);
+
IHTMLElementCollection_Release(col);
hres = IHTMLDocument2_get_images(doc, &collection);
@@ -7012,6 +7040,7 @@ static void test_elems(IHTMLDocument2 *doc)
elem2 = test_elem_get_parent((IUnknown*)elem3);
ok(elem2 == NULL, "elem2 != NULL\n");
+ test_elem_source_index(elem3, 0);
IHTMLElement_Release(elem3);
test_elem_getelembytag((IUnknown*)elem, ET_OPTION, 2, NULL);
@@ -7737,6 +7766,7 @@ static void test_create_elems(IHTMLDocument2 *doc)
ok(type == 1, "type=%d\n", type);
test_ifaces((IUnknown*)elem, elem_iids);
test_disp((IUnknown*)elem, &DIID_DispHTMLGenericElement, "[object]");
+ test_elem_source_index(elem, -1);
body = doc_get_body(doc);
test_node_has_child((IUnknown*)body, VARIANT_FALSE);
@@ -8333,7 +8363,9 @@ static void test_docfrag(IHTMLDocument2 *doc)
ok(location == (void*)0xdeadbeef, "location changed\n");
br = test_create_elem(doc, "BR");
+ test_elem_source_index(br, -1);
test_node_append_child((IUnknown*)frag, (IUnknown*)br);
+ test_elem_source_index(br, 0);
IHTMLElement_Release(br);
div = get_elem_by_id(doc, "divid", TRUE);