This implements props access to the underlying items in the storage, which is supported on native (although quirky). Unlike most normal props, the underlying storage for the props is asynchronous, so it can disappear or appear at any point, so they have to be re-checked as needed. The props themselves just map a name to a DISPID, but other than that, DISP_E_MEMBERNOTFOUND can return even after a successful GetDispID for example, even if GetDispID already checked for the item (which it has to, for e.g. (x in y) check).
It also contains some fixes for enumerating props, which are needed now because these props also have to be enumerated. They are custom props, so it's needed to have GetMemberName work for them. And since they are asynchronous it makes it even more complicated when enumerating.
-- v2: mshtml: Implement props enumeration for Storage. mshtml: Implement GetMemberName for custom props. mshtml: Do not enumerate hidden builtin props. mshtml: Implement deleting props for Storage. mshtml: Implement props for Storage by forwarding to the underlying storage.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlstorage.c | 159 ++++++++++++++++++++++++++++++++++- dlls/mshtml/mshtml_private.h | 5 ++ dlls/mshtml/tests/dom.js | 22 ++++- 3 files changed, 184 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index f4413ba2a3a..716a306ee6b 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -39,6 +39,8 @@ typedef struct { DispatchEx dispex; IHTMLStorage IHTMLStorage_iface; LONG ref; + unsigned num_props; + BSTR *props; struct session_map_entry *session_storage; WCHAR *filename; HANDLE mutex; @@ -178,6 +180,16 @@ void destroy_session_storage(thread_data_t *thread_data) } }
+static void release_props(HTMLStorage *This) +{ + BSTR *prop = This->props, *end = prop + This->num_props; + while(prop != end) { + SysFreeString(*prop); + prop++; + } + heap_free(This->props); +} + static inline HTMLStorage *impl_from_IHTMLStorage(IHTMLStorage *iface) { return CONTAINING_RECORD(iface, HTMLStorage, IHTMLStorage_iface); @@ -227,6 +239,7 @@ static ULONG WINAPI HTMLStorage_Release(IHTMLStorage *iface) release_dispex(&This->dispex); heap_free(This->filename); CloseHandle(This->mutex); + release_props(This); heap_free(This); }
@@ -835,13 +848,157 @@ static const IHTMLStorageVtbl HTMLStorageVtbl = { HTMLStorage_clear };
+static inline HTMLStorage *impl_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, HTMLStorage, dispex); +} + +static HRESULT check_item(HTMLStorage *This, const WCHAR *key) +{ + struct session_entry *session_entry; + IXMLDOMNode *root, *node; + IXMLDOMDocument *doc; + HRESULT hres; + BSTR query; + + if(!This->filename) { + hres = get_session_entry(This->session_storage, key, FALSE, &session_entry); + if(SUCCEEDED(hres)) + hres = (session_entry && session_entry->value) ? S_OK : S_FALSE; + return hres; + } + + WaitForSingleObject(This->mutex, INFINITE); + + hres = open_document(This->filename, &doc); + if(hres == S_OK) { + hres = get_root_node(doc, &root); + IXMLDOMDocument_Release(doc); + if(hres == S_OK) { + if(!(query = build_query(key))) + hres = E_OUTOFMEMORY; + else { + hres = IXMLDOMNode_selectSingleNode(root, query, &node); + SysFreeString(query); + if(hres == S_OK) + IXMLDOMNode_Release(node); + } + IXMLDOMNode_Release(root); + } + } + + ReleaseMutex(This->mutex); + + return hres; +} + +static HRESULT get_prop(HTMLStorage *This, const WCHAR *name, DISPID *dispid) +{ + UINT name_len = wcslen(name); + BSTR p, *prop, *end; + + for(prop = This->props, end = prop + This->num_props; prop != end; prop++) { + if(SysStringLen(*prop) == name_len && !memcmp(*prop, name, name_len * sizeof(WCHAR))) { + *dispid = MSHTML_DISPID_CUSTOM_MIN + (prop - This->props); + return S_OK; + } + } + + if(is_power_of_2(This->num_props)) { + BSTR *new_props = heap_realloc(This->props, max(This->num_props * 2 * sizeof(BSTR*), 1)); + if(!new_props) + return E_OUTOFMEMORY; + This->props = new_props; + } + + if(!(p = SysAllocStringLen(name, name_len))) + return E_OUTOFMEMORY; + + This->props[This->num_props] = p; + *dispid = MSHTML_DISPID_CUSTOM_MIN + This->num_props++; + return S_OK; +} + +static HRESULT HTMLStorage_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid) +{ + HTMLStorage *This = impl_from_DispatchEx(dispex); + HRESULT hres; + + if(flags & fdexNameCaseInsensitive) + FIXME("case insensitive not supported\n"); + + if(!(flags & fdexNameEnsure)) { + hres = check_item(This, name); + if(hres != S_OK) + return FAILED(hres) ? hres : DISP_E_UNKNOWNNAME; + } + + return get_prop(This, name, dispid); +} + +static HRESULT HTMLStorage_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLStorage *This = impl_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + HRESULT hres; + BSTR bstr; + + if(idx >= This->num_props) + return DISP_E_MEMBERNOTFOUND; + + switch(flags) { + case DISPATCH_PROPERTYGET: + hres = HTMLStorage_getItem(&This->IHTMLStorage_iface, This->props[idx], res); + if(FAILED(hres)) + return hres; + if(V_VT(res) == VT_NULL) + return DISP_E_MEMBERNOTFOUND; + break; + case DISPATCH_PROPERTYPUTREF: + case DISPATCH_PROPERTYPUT: + if(params->cArgs != 1 || (params->cNamedArgs && params->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT)) { + FIXME("unimplemented args %u %u\n", params->cArgs, params->cNamedArgs); + return E_NOTIMPL; + } + + bstr = V_BSTR(params->rgvarg); + if(V_VT(params->rgvarg) != VT_BSTR) { + VARIANT var; + hres = change_type(&var, params->rgvarg, VT_BSTR, caller); + if(FAILED(hres)) + return hres; + bstr = V_BSTR(&var); + } + + hres = HTMLStorage_setItem(&This->IHTMLStorage_iface, This->props[idx], bstr); + + if(V_VT(params->rgvarg) != VT_BSTR) + SysFreeString(bstr); + return hres; + + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static const dispex_static_data_vtbl_t HTMLStorage_dispex_vtbl = { + NULL, + HTMLStorage_get_dispid, + HTMLStorage_invoke, + NULL +}; + static const tid_t HTMLStorage_iface_tids[] = { IHTMLStorage_tid, 0 }; static dispex_static_data_t HTMLStorage_dispex = { L"Storage", - NULL, + &HTMLStorage_dispex_vtbl, IHTMLStorage_tid, HTMLStorage_iface_tids }; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index cbaa3f15232..aee57456c3a 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1423,6 +1423,11 @@ static inline BOOL is_digit(WCHAR c) return '0' <= c && c <= '9'; }
+static inline BOOL is_power_of_2(unsigned x) +{ + return !(x & (x - 1)); +} + #ifdef __i386__ extern void *call_thiscall_func; #endif diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index fcbca0f4b2f..e82424e5c55 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -473,7 +473,27 @@ sync_test("storage", function() { "typeof(window.localStorage) = " + typeof(window.localStorage));
var item = sessionStorage.getItem("nonexisting"); - ok(item === null, "item = " + item); + ok(item === null, "'nonexisting' item = " + item); + item = sessionStorage["nonexisting"]; + ok(item === undefined, "[nonexisting] item = " + item); + ok(!("nonexisting" in sessionStorage), "nonexisting in sessionStorage"); + + sessionStorage.setItem("foobar", 42); + ok("foobar" in sessionStorage, "foobar not in sessionStorage"); + item = sessionStorage.getItem("foobar"); + ok(item === "42", "'foobar' item = " + item); + item = sessionStorage["foobar"]; + ok(item === "42", "[foobar] item = " + item); + sessionStorage.removeItem("foobar"); + item = sessionStorage["foobar"]; + ok(item === undefined, "[foobar] item after removal = " + item); + + sessionStorage["barfoo"] = true; + ok("barfoo" in sessionStorage, "barfoo not in sessionStorage"); + item = sessionStorage["barfoo"]; + ok(item === "true", "[barfoo] item = " + item); + item = sessionStorage.getItem("barfoo"); + ok(item === "true", "'barfoo' item = " + item); });
async_test("animation", function() {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=122401
Your paranoid android.
=== w10pro64_zh_CN (64 bit report) ===
mshtml: htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 12 ++++++------ dlls/mshtml/htmldoc.c | 1 + dlls/mshtml/htmlelem.c | 1 + dlls/mshtml/htmlstorage.c | 15 +++++++++++++++ dlls/mshtml/htmlwindow.c | 1 + dlls/mshtml/mshtml_private.h | 4 +++- dlls/mshtml/tests/documentmode.js | 25 +++++++++++++++++++++++++ 7 files changed, 52 insertions(+), 7 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 3f5d4bbce76..cd6a81f4659 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1763,15 +1763,12 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR nam
TRACE("(%p)->(%s %lx)\n", This, debugstr_w(name), grfdex);
- if(dispex_compat_mode(This) < COMPAT_MODE_IE8) { - /* Not implemented by IE */ - return E_NOTIMPL; - } - hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, name, grfdex & ~fdexNameEnsure, &id); if(FAILED(hres)) { + compat_mode_t compat_mode = dispex_compat_mode(This); TRACE("property %s not found\n", debugstr_w(name)); - return dispex_compat_mode(This) < COMPAT_MODE_IE9 ? hres : S_OK; + return compat_mode < COMPAT_MODE_IE8 ? E_NOTIMPL : + compat_mode < COMPAT_MODE_IE9 ? hres : S_OK; }
return IDispatchEx_DeleteMemberByDispID(&This->IDispatchEx_iface, id); @@ -1783,6 +1780,9 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID
TRACE("(%p)->(%lx)\n", This, id);
+ if(is_custom_dispid(id) && This->info->desc->vtbl && This->info->desc->vtbl->delete) + return This->info->desc->vtbl->delete(This, id); + if(dispex_compat_mode(This) < COMPAT_MODE_IE8) { /* Not implemented by IE */ return E_NOTIMPL; diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index e7074952983..0c7a074ca35 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -5921,6 +5921,7 @@ static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = { NULL, NULL, HTMLDocumentNode_invoke, + NULL, HTMLDocumentNode_get_compat_mode, NULL }, diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index d341623d4d5..165db9dedfc 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -7183,6 +7183,7 @@ static event_target_vtbl_t HTMLElement_event_target_vtbl = { HTMLElement_get_dispid, HTMLElement_invoke, NULL, + NULL, HTMLElement_populate_props }, HTMLElement_get_gecko_target, diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 716a306ee6b..365a7bd34f3 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -985,10 +985,25 @@ static HRESULT HTMLStorage_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD return S_OK; }
+static HRESULT HTMLStorage_delete(DispatchEx *dispex, DISPID id) +{ + HTMLStorage *This = impl_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + + if(idx >= This->num_props) + return DISP_E_MEMBERNOTFOUND; + + if(dispex_compat_mode(dispex) < COMPAT_MODE_IE8) + return MSHTML_E_INVALID_ACTION; + + return HTMLStorage_removeItem(&This->IHTMLStorage_iface, This->props[idx]); +} + static const dispex_static_data_vtbl_t HTMLStorage_dispex_vtbl = { NULL, HTMLStorage_get_dispid, HTMLStorage_invoke, + HTMLStorage_delete, NULL };
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index b9dcfa6e913..1a7ae479321 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3954,6 +3954,7 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = { NULL, NULL, HTMLWindow_invoke, + NULL, HTMLWindow_get_compat_mode, NULL }, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index aee57456c3a..97715c45b93 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -72,7 +72,8 @@
#define NSAPI WINAPI
-#define MSHTML_E_NODOC 0x800a025c +#define MSHTML_E_INVALID_ACTION 0x800a01bd +#define MSHTML_E_NODOC 0x800a025c
typedef struct HTMLDOMNode HTMLDOMNode; typedef struct ConnectionPoint ConnectionPoint; @@ -333,6 +334,7 @@ typedef struct { HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); HRESULT (*get_dispid)(DispatchEx*,BSTR,DWORD,DISPID*); HRESULT (*invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); + HRESULT (*delete)(DispatchEx*,DISPID); compat_mode_t (*get_compat_mode)(DispatchEx*); HRESULT (*populate_props)(DispatchEx*); } dispex_static_data_vtbl_t; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 5b746598dba..24adb08005c 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1201,6 +1201,31 @@ sync_test("map_obj", function() { ok(r === 1, "r = " + r); });
+sync_test("storage", function() { + var v = document.documentMode, r; + + sessionStorage.setItem("foobar", "1234"); + ok("foobar" in sessionStorage, "foobar not in sessionStorage"); + r = sessionStorage.foobar; + ok(r === "1234", "sessionStorage.foobar = " + r); + sessionStorage.barfoo = 4321; + r = sessionStorage.getItem("barfoo"); + ok(r === "4321", "sessionStorage.barfoo = " + r); + + try { + delete sessionStorage.foobar; + ok(v >= 8, "expected exception deleting sessionStorage.foobar"); + ok(!("foobar" in sessionStorage), "foobar in sessionStorage after deletion"); + r = sessionStorage.getItem("foobar"); + ok(r === null, "sessionStorage.foobar after deletion = " + r); + }catch(e) { + ok(v < 8, "did not expect exception deleting sessionStorage.foobar"); + ok(e.number === 0xa01bd - 0x80000000, "deleting sessionStorage.foobar threw = " + e.number); + } + + sessionStorage.clear(); +}); + sync_test("elem_attr", function() { var v = document.documentMode; var elem = document.createElement("div"), r;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=122402
Your paranoid android.
=== w10pro64 (64 bit report) ===
mshtml: htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
=== w10pro64_en_AE_u8 (64 bit report) ===
mshtml: htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index cd6a81f4659..d14ab5a13d4 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -396,6 +396,9 @@ static void add_func_info(dispex_data_t *data, tid_t tid, const FUNCDESC *desc, }else if(desc->invkind & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYGET)) { VARTYPE vt = VT_EMPTY;
+ if(desc->wFuncFlags & FUNCFLAG_FHIDDEN) + info->func_disp_idx = -2; + if(desc->invkind & DISPATCH_PROPERTYGET) { vt = desc->elemdescFunc.tdesc.vt; info->get_vtbl_off = desc->oVft/sizeof(void*); @@ -1371,7 +1374,7 @@ static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD if(FAILED(hres)) return hres;
- if(func->func_disp_idx != -1) + if(func->func_disp_idx >= 0) return function_invoke(This, func, flags, dp, res, ei, caller);
if(func->hook) { @@ -1460,7 +1463,7 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) return hres;
/* For builtin functions, we set their value to the original function. */ - if(func->func_disp_idx != -1) { + if(func->func_disp_idx >= 0) { func_obj_entry_t *entry;
if(!This->dynamic_data || !This->dynamic_data->func_disps @@ -1889,7 +1892,6 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, }
while(func < This->info->funcs + This->info->func_cnt) { - /* FIXME: Skip hidden properties */ if(func->func_disp_idx == -1) { *pid = func->id; return S_OK;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 6 +++++ dlls/mshtml/htmlanchor.c | 1 + dlls/mshtml/htmlbody.c | 1 + dlls/mshtml/htmldoc.c | 13 ++++++++++ dlls/mshtml/htmlelem.c | 49 ++++++++++++++++++++++++++++++++++++ dlls/mshtml/htmlelemcol.c | 15 +++++++++++ dlls/mshtml/htmlform.c | 26 +++++++++++++++++++ dlls/mshtml/htmlframe.c | 28 +++++++++++++++++++++ dlls/mshtml/htmlhead.c | 1 + dlls/mshtml/htmlimg.c | 1 + dlls/mshtml/htmlinput.c | 2 ++ dlls/mshtml/htmllink.c | 1 + dlls/mshtml/htmlnode.c | 16 ++++++++++++ dlls/mshtml/htmlobject.c | 10 ++++++++ dlls/mshtml/htmlscript.c | 1 + dlls/mshtml/htmlselect.c | 15 +++++++++++ dlls/mshtml/htmlstorage.c | 12 +++++++++ dlls/mshtml/htmlstyleelem.c | 1 + dlls/mshtml/htmlstylesheet.c | 32 +++++++++++++++++++++++ dlls/mshtml/htmltable.c | 3 +++ dlls/mshtml/htmltextarea.c | 1 + dlls/mshtml/htmlwindow.c | 12 +++++++++ dlls/mshtml/mshtml_private.h | 2 ++ 23 files changed, 249 insertions(+)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index d14ab5a13d4..357549698fc 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1825,6 +1825,12 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BS if(!ensure_real_info(This)) return E_OUTOFMEMORY;
+ if(is_custom_dispid(id)) { + if(This->info->desc->vtbl && This->info->desc->vtbl->get_name) + return This->info->desc->vtbl->get_name(This, id, pbstrName); + return DISP_E_MEMBERNOTFOUND; + } + if(is_dynamic_dispid(id)) { DWORD idx = id - DISPID_DYNPROP_0;
diff --git a/dlls/mshtml/htmlanchor.c b/dlls/mshtml/htmlanchor.c index 813d4eb3b2d..7b4ee80778f 100644 --- a/dlls/mshtml/htmlanchor.c +++ b/dlls/mshtml/htmlanchor.c @@ -889,6 +889,7 @@ static const NodeImplVtbl HTMLAnchorElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLAnchorElement_traverse, HTMLAnchorElement_unlink }; diff --git a/dlls/mshtml/htmlbody.c b/dlls/mshtml/htmlbody.c index 663a75d2e2a..c431551e489 100644 --- a/dlls/mshtml/htmlbody.c +++ b/dlls/mshtml/htmlbody.c @@ -993,6 +993,7 @@ static const NodeImplVtbl HTMLBodyElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLBodyElement_traverse, HTMLBodyElement_unlink, HTMLBodyElement_is_text_edit, diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 0c7a074ca35..2537a316500 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -5800,6 +5800,7 @@ static const NodeImplVtbl HTMLDocumentNodeImplVtbl = { NULL, NULL, NULL, + NULL, HTMLDocumentNode_traverse, HTMLDocumentNode_unlink }; @@ -5823,6 +5824,17 @@ static inline HTMLDocumentNode *impl_from_DispatchEx(DispatchEx *iface) return CONTAINING_RECORD(iface, HTMLDocumentNode, node.event_target.dispex); }
+static HRESULT HTMLDocumentNode_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLDocumentNode *This = impl_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + + if(!This->nsdoc || idx >= This->elem_vars_cnt) + return DISP_E_MEMBERNOTFOUND; + + return (*name = SysAllocString(This->elem_vars[idx])) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLDocumentNode_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -5920,6 +5932,7 @@ static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = { { NULL, NULL, + HTMLDocumentNode_get_name, HTMLDocumentNode_invoke, NULL, HTMLDocumentNode_get_compat_mode, diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 165db9dedfc..d3704ccbb5c 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -1107,6 +1107,21 @@ static HRESULT HTMLRectCollection_get_dispid(DispatchEx *dispex, BSTR name, DWOR return S_OK; }
+static HRESULT HTMLRectCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLRectCollection *This = HTMLRectCollection_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + UINT32 len = 0; + WCHAR buf[11]; + + nsIDOMClientRectList_GetLength(This->rect_list, &len); + if(idx >= len) + return DISP_E_MEMBERNOTFOUND; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLRectCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -1148,6 +1163,7 @@ static HRESULT HTMLRectCollection_invoke(DispatchEx *dispex, DISPID id, LCID lci static const dispex_static_data_vtbl_t HTMLRectCollection_dispex_vtbl = { NULL, HTMLRectCollection_get_dispid, + HTMLRectCollection_get_name, HTMLRectCollection_invoke, NULL }; @@ -6808,6 +6824,17 @@ static HRESULT HTMLElement_get_dispid(DispatchEx *dispex, BSTR name, return DISP_E_UNKNOWNNAME; }
+static HRESULT HTMLElement_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLElement *This = impl_from_DispatchEx(dispex); + + if(This->node.vtbl->get_name) + return This->node.vtbl->get_name(&This->node, id, name); + + ERR("(%p): element has no get_name method\n", This); + return DISP_E_MEMBERNOTFOUND; +} + static HRESULT HTMLElement_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) @@ -7181,6 +7208,7 @@ static event_target_vtbl_t HTMLElement_event_target_vtbl = { { NULL, HTMLElement_get_dispid, + HTMLElement_get_name, HTMLElement_invoke, NULL, NULL, @@ -7852,6 +7880,16 @@ static HRESULT HTMLFiltersCollection_get_dispid(DispatchEx *dispex, BSTR name, D return S_OK; }
+static HRESULT HTMLFiltersCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + WCHAR buf[11]; + UINT len; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLFiltersCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -7868,6 +7906,7 @@ static HRESULT HTMLFiltersCollection_invoke(DispatchEx *dispex, DISPID id, LCID static const dispex_static_data_vtbl_t HTMLFiltersCollection_dispex_vtbl = { NULL, HTMLFiltersCollection_get_dispid, + HTMLFiltersCollection_get_name, HTMLFiltersCollection_invoke, NULL }; @@ -8577,6 +8616,15 @@ static HRESULT HTMLAttributeCollection_get_dispid(DispatchEx *dispex, BSTR name, return S_OK; }
+static HRESULT HTMLAttributeCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLAttributeCollection *This = HTMLAttributeCollection_from_DispatchEx(dispex); + + FIXME("(%p)->(%lx %p)\n", This, id, name); + + return E_NOTIMPL; +} + static HRESULT HTMLAttributeCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -8614,6 +8662,7 @@ static HRESULT HTMLAttributeCollection_invoke(DispatchEx *dispex, DISPID id, LCI static const dispex_static_data_vtbl_t HTMLAttributeCollection_dispex_vtbl = { NULL, HTMLAttributeCollection_get_dispid, + HTMLAttributeCollection_get_name, HTMLAttributeCollection_invoke, NULL }; diff --git a/dlls/mshtml/htmlelemcol.c b/dlls/mshtml/htmlelemcol.c index 180f75d630b..cd3341b3946 100644 --- a/dlls/mshtml/htmlelemcol.c +++ b/dlls/mshtml/htmlelemcol.c @@ -581,6 +581,20 @@ static HRESULT HTMLElementCollection_get_dispid(DispatchEx *dispex, BSTR name, D return S_OK; }
+static HRESULT HTMLElementCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLElementCollection *This = impl_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + WCHAR buf[11]; + UINT len; + + if(idx >= This->len) + return DISP_E_MEMBERNOTFOUND; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLElementCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -610,6 +624,7 @@ static HRESULT HTMLElementCollection_invoke(DispatchEx *dispex, DISPID id, LCID static const dispex_static_data_vtbl_t HTMLElementColection_dispex_vtbl = { NULL, HTMLElementCollection_get_dispid, + HTMLElementCollection_get_name, HTMLElementCollection_invoke, NULL }; diff --git a/dlls/mshtml/htmlform.c b/dlls/mshtml/htmlform.c index 18b56ae54a8..d6e4b2d8424 100644 --- a/dlls/mshtml/htmlform.c +++ b/dlls/mshtml/htmlform.c @@ -898,6 +898,31 @@ static HRESULT HTMLFormElement_get_dispid(HTMLDOMNode *iface, return hres; }
+static HRESULT HTMLFormElement_dispex_get_name(HTMLDOMNode *iface, DISPID id, BSTR *name) +{ + HTMLFormElement *This = impl_from_HTMLDOMNode(iface); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + nsIDOMHTMLCollection *elements; + nsresult nsres; + UINT32 len = 0; + WCHAR buf[11]; + + nsres = nsIDOMHTMLFormElement_GetElements(This->nsform, &elements); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + + nsres = nsIDOMHTMLCollection_GetLength(elements, &len); + nsIDOMHTMLCollection_Release(elements); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + + if(idx >= len) + return DISP_E_MEMBERNOTFOUND; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLFormElement_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) @@ -967,6 +992,7 @@ static const NodeImplVtbl HTMLFormElementImplVtbl = { NULL, NULL, HTMLFormElement_get_dispid, + HTMLFormElement_dispex_get_name, HTMLFormElement_invoke, NULL, HTMLFormElement_traverse, diff --git a/dlls/mshtml/htmlframe.c b/dlls/mshtml/htmlframe.c index 7a49e60bf8f..985ac13cc2f 100644 --- a/dlls/mshtml/htmlframe.c +++ b/dlls/mshtml/htmlframe.c @@ -942,6 +942,19 @@ static HRESULT HTMLFrameElement_get_dispid(HTMLDOMNode *iface, BSTR name, return search_window_props(This->framebase.content_window->base.inner_window, name, grfdex, pid); }
+static HRESULT HTMLFrameElement_get_name(HTMLDOMNode *iface, DISPID id, BSTR *name) +{ + HTMLFrameElement *This = frame_from_HTMLDOMNode(iface); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + + if(!This->framebase.content_window || + idx >= This->framebase.content_window->base.inner_window->global_prop_cnt) + return DISP_E_MEMBERNOTFOUND; + + *name = SysAllocString(This->framebase.content_window->base.inner_window->global_props[idx].name); + return *name ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLFrameElement_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -1008,6 +1021,7 @@ static const NodeImplVtbl HTMLFrameElementImplVtbl = { HTMLFrameElement_get_document, HTMLFrameElement_get_readystate, HTMLFrameElement_get_dispid, + HTMLFrameElement_get_name, HTMLFrameElement_invoke, HTMLFrameElement_bind_to_tree, HTMLFrameElement_traverse, @@ -1514,6 +1528,19 @@ static HRESULT HTMLIFrame_get_dispid(HTMLDOMNode *iface, BSTR name, return search_window_props(This->framebase.content_window->base.inner_window, name, grfdex, pid); }
+static HRESULT HTMLIFrame_get_name(HTMLDOMNode *iface, DISPID id, BSTR *name) +{ + HTMLIFrame *This = iframe_from_HTMLDOMNode(iface); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + + if(!This->framebase.content_window || + idx >= This->framebase.content_window->base.inner_window->global_prop_cnt) + return DISP_E_MEMBERNOTFOUND; + + *name = SysAllocString(This->framebase.content_window->base.inner_window->global_props[idx].name); + return *name ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLIFrame_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -1587,6 +1614,7 @@ static const NodeImplVtbl HTMLIFrameImplVtbl = { HTMLIFrame_get_document, HTMLIFrame_get_readystate, HTMLIFrame_get_dispid, + HTMLIFrame_get_name, HTMLIFrame_invoke, HTMLIFrame_bind_to_tree, HTMLIFrame_traverse, diff --git a/dlls/mshtml/htmlhead.c b/dlls/mshtml/htmlhead.c index 786d60ae227..9460d186e58 100644 --- a/dlls/mshtml/htmlhead.c +++ b/dlls/mshtml/htmlhead.c @@ -358,6 +358,7 @@ static const NodeImplVtbl HTMLHtmlElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLHtmlElement_is_settable };
diff --git a/dlls/mshtml/htmlimg.c b/dlls/mshtml/htmlimg.c index 4483a5ed5ac..966ea3f39c0 100644 --- a/dlls/mshtml/htmlimg.c +++ b/dlls/mshtml/htmlimg.c @@ -720,6 +720,7 @@ static const NodeImplVtbl HTMLImgElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLImgElement_traverse, HTMLImgElement_unlink }; diff --git a/dlls/mshtml/htmlinput.c b/dlls/mshtml/htmlinput.c index 757a85e4290..bd71cea88bd 100644 --- a/dlls/mshtml/htmlinput.c +++ b/dlls/mshtml/htmlinput.c @@ -1429,6 +1429,7 @@ static const NodeImplVtbl HTMLInputElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLInputElement_traverse, HTMLInputElement_unlink, HTMLInputElement_is_text_edit @@ -1973,6 +1974,7 @@ static const NodeImplVtbl HTMLButtonElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLButtonElement_traverse, HTMLButtonElement_unlink, HTMLButtonElement_is_text_edit diff --git a/dlls/mshtml/htmllink.c b/dlls/mshtml/htmllink.c index f4f5e2eb943..190d2a6bdb4 100644 --- a/dlls/mshtml/htmllink.c +++ b/dlls/mshtml/htmllink.c @@ -436,6 +436,7 @@ static const NodeImplVtbl HTMLLinkElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLLinkElement_traverse, HTMLLinkElement_unlink }; diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index e10af6c1436..e1b8e0aca7c 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -386,6 +386,21 @@ static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR nam return S_OK; }
+static HRESULT HTMLDOMChildrenCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex); + DWORD idx = id - DISPID_CHILDCOL_0; + UINT32 len = 0; + WCHAR buf[11]; + + nsIDOMNodeList_GetLength(This->nslist, &len); + if(idx >= len) + return DISP_E_MEMBERNOTFOUND; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -419,6 +434,7 @@ static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, L static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = { NULL, HTMLDOMChildrenCollection_get_dispid, + HTMLDOMChildrenCollection_get_name, HTMLDOMChildrenCollection_invoke, NULL }; diff --git a/dlls/mshtml/htmlobject.c b/dlls/mshtml/htmlobject.c index 787dd3762ee..1ad907338e7 100644 --- a/dlls/mshtml/htmlobject.c +++ b/dlls/mshtml/htmlobject.c @@ -709,6 +709,15 @@ static HRESULT HTMLObjectElement_get_dispid(HTMLDOMNode *iface, BSTR name, return get_plugin_dispid(&This->plugin_container, name, pid); }
+static HRESULT HTMLObjectElement_dispex_get_name(HTMLDOMNode *iface, DISPID id, BSTR *name) +{ + HTMLObjectElement *This = impl_from_HTMLDOMNode(iface); + + FIXME("(%p)->(%lx %p)\n", This, id, name); + + return E_NOTIMPL; +} + static HRESULT HTMLObjectElement_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -753,6 +762,7 @@ static const NodeImplVtbl HTMLObjectElementImplVtbl = { NULL, HTMLObjectElement_get_readystate, HTMLObjectElement_get_dispid, + HTMLObjectElement_dispex_get_name, HTMLObjectElement_invoke, NULL, HTMLObjectElement_traverse, diff --git a/dlls/mshtml/htmlscript.c b/dlls/mshtml/htmlscript.c index f28a9d3a29d..efacefaaaf4 100644 --- a/dlls/mshtml/htmlscript.c +++ b/dlls/mshtml/htmlscript.c @@ -447,6 +447,7 @@ static const NodeImplVtbl HTMLScriptElementImplVtbl = { HTMLScriptElement_get_readystate, NULL, NULL, + NULL, HTMLScriptElement_bind_to_tree, HTMLScriptElement_traverse, HTMLScriptElement_unlink diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index ae6543a3d13..f8305542fae 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -406,6 +406,7 @@ static const NodeImplVtbl HTMLOptionElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLOptionElement_traverse, HTMLOptionElement_unlink }; @@ -1400,6 +1401,19 @@ static HRESULT HTMLSelectElement_get_dispid(HTMLDOMNode *iface, BSTR name, DWORD return S_OK; }
+static HRESULT HTMLSelectElement_dispex_get_name(HTMLDOMNode *iface, DISPID id, BSTR *name) +{ + DWORD idx = id - DISPID_OPTIONCOL_0; + WCHAR buf[11]; + UINT len; + + if(idx > MSHTML_CUSTOM_DISPID_CNT) + return DISP_E_MEMBERNOTFOUND; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLSelectElement_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -1467,6 +1481,7 @@ static const NodeImplVtbl HTMLSelectElementImplVtbl = { NULL, NULL, HTMLSelectElement_get_dispid, + HTMLSelectElement_dispex_get_name, HTMLSelectElement_invoke, NULL, HTMLSelectElement_traverse, diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 365a7bd34f3..12ad4443e93 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -936,6 +936,17 @@ static HRESULT HTMLStorage_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags return get_prop(This, name, dispid); }
+static HRESULT HTMLStorage_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLStorage *This = impl_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + + if(idx >= This->num_props) + return DISP_E_MEMBERNOTFOUND; + + return (*name = SysAllocString(This->props[idx])) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLStorage_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -1002,6 +1013,7 @@ static HRESULT HTMLStorage_delete(DispatchEx *dispex, DISPID id) static const dispex_static_data_vtbl_t HTMLStorage_dispex_vtbl = { NULL, HTMLStorage_get_dispid, + HTMLStorage_get_name, HTMLStorage_invoke, HTMLStorage_delete, NULL diff --git a/dlls/mshtml/htmlstyleelem.c b/dlls/mshtml/htmlstyleelem.c index 1b1297ea5eb..eee854d7e44 100644 --- a/dlls/mshtml/htmlstyleelem.c +++ b/dlls/mshtml/htmlstyleelem.c @@ -453,6 +453,7 @@ static const NodeImplVtbl HTMLStyleElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLStyleElement_traverse, HTMLStyleElement_unlink }; diff --git a/dlls/mshtml/htmlstylesheet.c b/dlls/mshtml/htmlstylesheet.c index 2d76e370ed2..8546a5c9519 100644 --- a/dlls/mshtml/htmlstylesheet.c +++ b/dlls/mshtml/htmlstylesheet.c @@ -410,6 +410,21 @@ static HRESULT HTMLStyleSheetRulesCollection_get_dispid(DispatchEx *dispex, BSTR return S_OK; }
+static HRESULT HTMLStyleSheetRulesCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLStyleSheetRulesCollection *This = HTMLStyleSheetRulesCollection_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + UINT32 len = 0; + WCHAR buf[11]; + + nsIDOMCSSRuleList_GetLength(This->nslist, &len); + if(idx >= len) + return DISP_E_MEMBERNOTFOUND; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLStyleSheetRulesCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -453,6 +468,7 @@ static HRESULT HTMLStyleSheetRulesCollection_invoke(DispatchEx *dispex, DISPID i static const dispex_static_data_vtbl_t HTMLStyleSheetRulesCollection_dispex_vtbl = { NULL, HTMLStyleSheetRulesCollection_get_dispid, + HTMLStyleSheetRulesCollection_get_name, HTMLStyleSheetRulesCollection_invoke }; static const tid_t HTMLStyleSheetRulesCollection_iface_tids[] = { @@ -821,6 +837,21 @@ static HRESULT HTMLStyleSheetsCollection_get_dispid(DispatchEx *dispex, BSTR nam return S_OK; }
+static HRESULT HTMLStyleSheetsCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLStyleSheetsCollection *This = HTMLStyleSheetsCollection_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + UINT32 len = 0; + WCHAR buf[11]; + + nsIDOMStyleSheetList_GetLength(This->nslist, &len); + if(idx >= len) + return DISP_E_MEMBERNOTFOUND; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLStyleSheetsCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -864,6 +895,7 @@ static HRESULT HTMLStyleSheetsCollection_invoke(DispatchEx *dispex, DISPID id, L static const dispex_static_data_vtbl_t HTMLStyleSheetsCollection_dispex_vtbl = { NULL, HTMLStyleSheetsCollection_get_dispid, + HTMLStyleSheetsCollection_get_name, HTMLStyleSheetsCollection_invoke }; static const tid_t HTMLStyleSheetsCollection_iface_tids[] = { diff --git a/dlls/mshtml/htmltable.c b/dlls/mshtml/htmltable.c index 6a64672a83a..f489d7592e7 100644 --- a/dlls/mshtml/htmltable.c +++ b/dlls/mshtml/htmltable.c @@ -509,6 +509,7 @@ static const NodeImplVtbl HTMLTableCellImplVtbl = { NULL, NULL, NULL, + NULL, HTMLTableCell_traverse, HTMLTableCell_unlink }; @@ -954,6 +955,7 @@ static const NodeImplVtbl HTMLTableRowImplVtbl = { NULL, NULL, NULL, + NULL, HTMLTableRow_traverse, HTMLTableRow_unlink }; @@ -1985,6 +1987,7 @@ static const NodeImplVtbl HTMLTableImplVtbl = { NULL, NULL, NULL, + NULL, HTMLTable_traverse, HTMLTable_unlink }; diff --git a/dlls/mshtml/htmltextarea.c b/dlls/mshtml/htmltextarea.c index 32a574ebcd5..cb79fc17d29 100644 --- a/dlls/mshtml/htmltextarea.c +++ b/dlls/mshtml/htmltextarea.c @@ -467,6 +467,7 @@ static const NodeImplVtbl HTMLTextAreaElementImplVtbl = { NULL, NULL, NULL, + NULL, HTMLTextAreaElement_traverse, HTMLTextAreaElement_unlink, HTMLTextAreaElement_is_text_edit diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 1a7ae479321..6be61ba3f4f 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3754,6 +3754,17 @@ static inline HTMLInnerWindow *impl_from_DispatchEx(DispatchEx *iface) return CONTAINING_RECORD(iface, HTMLInnerWindow, event_target.dispex); }
+static HRESULT HTMLWindow_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + HTMLInnerWindow *This = impl_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + + if(idx >= This->global_prop_cnt) + return DISP_E_MEMBERNOTFOUND; + + return (*name = SysAllocString(This->global_props[idx].name)) ? S_OK : E_OUTOFMEMORY; +} + static HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -3953,6 +3964,7 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = { { NULL, NULL, + HTMLWindow_get_name, HTMLWindow_invoke, NULL, HTMLWindow_get_compat_mode, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 97715c45b93..101dd63d9aa 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -333,6 +333,7 @@ typedef struct DispatchEx DispatchEx; typedef struct { HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); HRESULT (*get_dispid)(DispatchEx*,BSTR,DWORD,DISPID*); + HRESULT (*get_name)(DispatchEx*,DISPID,BSTR*); HRESULT (*invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); HRESULT (*delete)(DispatchEx*,DISPID); compat_mode_t (*get_compat_mode)(DispatchEx*); @@ -804,6 +805,7 @@ typedef struct { HRESULT (*get_document)(HTMLDOMNode*,IDispatch**); HRESULT (*get_readystate)(HTMLDOMNode*,BSTR*); HRESULT (*get_dispid)(HTMLDOMNode*,BSTR,DWORD,DISPID*); + HRESULT (*get_name)(HTMLDOMNode*,DISPID,BSTR*); HRESULT (*invoke)(HTMLDOMNode*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); HRESULT (*bind_to_tree)(HTMLDOMNode*); void (*traverse)(HTMLDOMNode*,nsCycleCollectionTraversalCallback*);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 34 +++++++----- dlls/mshtml/htmldoc.c | 1 + dlls/mshtml/htmlelem.c | 1 + dlls/mshtml/htmlstorage.c | 88 +++++++++++++++++++++++++++++++ dlls/mshtml/htmlwindow.c | 1 + dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/documentmode.js | 28 +++++++++- 7 files changed, 140 insertions(+), 14 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 357549698fc..5007f9a5d30 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -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) diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 2537a316500..fe743e666c1 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -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 }, diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index d3704ccbb5c..856f55da6c7 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -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, diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 12ad4443e93..5d56037ff04 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -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 };
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 6be61ba3f4f..00eef4d846a 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -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 }, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 101dd63d9aa..85f34bb4a9f 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -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; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 24adb08005c..8cc1da534e6 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -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;
This merge request was approved by Jacek Caban.