Commit d44a32ba authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

mshtml: Implement props enumeration for Storage.

parent c3c55c7f
......@@ -1888,21 +1888,29 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex,
return next_dynamic_id(This, idx+1, pid);
}
if(id == DISPID_STARTENUM) {
func = This->info->funcs;
}else {
hres = get_builtin_func(This->info, id, &func);
if(FAILED(hres))
return hres;
func++;
}
if(!is_custom_dispid(id)) {
if(id == DISPID_STARTENUM) {
func = This->info->funcs;
}else {
hres = get_builtin_func(This->info, id, &func);
if(FAILED(hres))
return hres;
func++;
}
while(func < This->info->funcs + This->info->func_cnt) {
if(func->func_disp_idx == -1) {
*pid = func->id;
return S_OK;
while(func < This->info->funcs + This->info->func_cnt) {
if(func->func_disp_idx == -1) {
*pid = func->id;
return S_OK;
}
func++;
}
func++;
}
if(This->info->desc->vtbl && This->info->desc->vtbl->next_dispid) {
hres = This->info->desc->vtbl->next_dispid(This, id, pid);
if(hres != S_FALSE)
return hres;
}
if(get_dynamic_data(This) && This->dynamic_data->prop_cnt)
......
......@@ -5935,6 +5935,7 @@ static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = {
HTMLDocumentNode_get_name,
HTMLDocumentNode_invoke,
NULL,
NULL,
HTMLDocumentNode_get_compat_mode,
NULL
},
......
......@@ -7212,6 +7212,7 @@ static event_target_vtbl_t HTMLElement_event_target_vtbl = {
HTMLElement_invoke,
NULL,
NULL,
NULL,
HTMLElement_populate_props
},
HTMLElement_get_gecko_target,
......
......@@ -1010,12 +1010,100 @@ static HRESULT HTMLStorage_delete(DispatchEx *dispex, DISPID id)
return HTMLStorage_removeItem(&This->IHTMLStorage_iface, This->props[idx]);
}
static HRESULT HTMLStorage_next_dispid(DispatchEx *dispex, DISPID id, DISPID *pid)
{
DWORD idx = (id == DISPID_STARTENUM) ? 0 : id - MSHTML_DISPID_CUSTOM_MIN + 1;
HTMLStorage *This = impl_from_DispatchEx(dispex);
HRESULT hres;
DISPID tmp;
if(idx > MSHTML_CUSTOM_DISPID_CNT)
return S_FALSE;
while(idx < This->num_props) {
hres = check_item(This, This->props[idx]);
if(hres == S_OK) {
*pid = idx + MSHTML_DISPID_CUSTOM_MIN;
return S_OK;
}
if(FAILED(hres))
return hres;
idx++;
}
/* Populate possibly missing DISPIDs */
if(!This->filename) {
struct session_entry *session_entry;
LIST_FOR_EACH_ENTRY(session_entry, &This->session_storage->data_list, struct session_entry, list_entry) {
hres = get_prop(This, session_entry->key, &tmp);
if(FAILED(hres))
return hres;
}
}else {
IXMLDOMNodeList *node_list;
IXMLDOMElement *elem;
IXMLDOMNode *node;
LONG index = 0;
HRESULT hres;
VARIANT key;
hres = get_node_list(This->filename, &node_list);
if(FAILED(hres))
return hres;
for(;;) {
hres = IXMLDOMNodeList_get_item(node_list, index++, &node);
if(hres != S_OK) {
IXMLDOMNodeList_Release(node_list);
if(FAILED(hres))
return hres;
break;
}
hres = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
IXMLDOMNode_Release(node);
if(hres != S_OK)
continue;
hres = IXMLDOMElement_getAttribute(elem, (BSTR)L"name", &key);
IXMLDOMElement_Release(elem);
if(hres != S_OK) {
if(SUCCEEDED(hres))
continue;
IXMLDOMNodeList_Release(node_list);
return hres;
}
if(V_VT(&key) != VT_BSTR) {
FIXME("non-string key %s\n", debugstr_variant(&key));
VariantClear(&key);
continue;
}
hres = get_prop(This, V_BSTR(&key), &tmp);
SysFreeString(V_BSTR(&key));
if(FAILED(hres)) {
IXMLDOMNodeList_Release(node_list);
return hres;
}
}
}
if(idx >= This->num_props)
return S_FALSE;
*pid = idx + MSHTML_DISPID_CUSTOM_MIN;
return S_OK;
}
static const dispex_static_data_vtbl_t HTMLStorage_dispex_vtbl = {
NULL,
HTMLStorage_get_dispid,
HTMLStorage_get_name,
HTMLStorage_invoke,
HTMLStorage_delete,
HTMLStorage_next_dispid,
NULL
};
......
......@@ -3967,6 +3967,7 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = {
HTMLWindow_get_name,
HTMLWindow_invoke,
NULL,
NULL,
HTMLWindow_get_compat_mode,
NULL
},
......
......@@ -336,6 +336,7 @@ typedef struct {
HRESULT (*get_name)(DispatchEx*,DISPID,BSTR*);
HRESULT (*invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
HRESULT (*delete)(DispatchEx*,DISPID);
HRESULT (*next_dispid)(DispatchEx*,DISPID,DISPID*);
compat_mode_t (*get_compat_mode)(DispatchEx*);
HRESULT (*populate_props)(DispatchEx*);
} dispex_static_data_vtbl_t;
......
......@@ -1202,7 +1202,10 @@ sync_test("map_obj", function() {
});
sync_test("storage", function() {
var v = document.documentMode, r;
var v = document.documentMode, i, r, list;
sessionStorage["add-at-end"] = 0;
sessionStorage.removeItem("add-at-end");
sessionStorage.setItem("foobar", "1234");
ok("foobar" in sessionStorage, "foobar not in sessionStorage");
......@@ -1211,6 +1214,29 @@ sync_test("storage", function() {
sessionStorage.barfoo = 4321;
r = sessionStorage.getItem("barfoo");
ok(r === "4321", "sessionStorage.barfoo = " + r);
sessionStorage.setItem("abcd", "blah");
sessionStorage.dcba = "test";
// Order isn't consistent, but changes are reflected during the enumeration.
// Elements that were already traversed in DISPID (even if removed before
// the enumeration) are not enumerated, even if re-added during the enum.
i = 0; list = [ "foobar", "barfoo", "abcd", "dcba" ];
for(r in sessionStorage) {
for(var j = 0; j < list.length; j++)
if(r === list[j])
break;
ok(j < list.length, "got '" + r + "' enumerating");
list.splice(j, 1);
if(i === 1) {
sessionStorage.removeItem(list[0]);
sessionStorage.setItem("new", "new");
list.splice(0, 1, "new");
}
if(!list.length)
sessionStorage.setItem("add-at-end", "0");
i++;
}
ok(i === 4, "enum did " + i + " iterations");
try {
delete sessionStorage.foobar;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment