From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 61 +++++++++++++++++++++++++++++++++++- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/dom.js | 33 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 6f3d6c37aa4..21a1ad69254 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -7710,6 +7710,9 @@ static const IWineDOMTokenListVtbl WineDOMTokenListVtbl = { token_list_toString };
+/* idx can be negative, so offset it halfway through custom dispids */ +#define DISPID_TOKENLIST_0 (MSHTML_DISPID_CUSTOM_MIN + (MSHTML_DISPID_CUSTOM_MAX+1 - MSHTML_DISPID_CUSTOM_MIN) / 2) + static inline struct token_list *token_list_from_DispatchEx(DispatchEx *iface) { return CONTAINING_RECORD(iface, struct token_list, dispex); @@ -7736,8 +7739,64 @@ static HRESULT token_list_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPP return S_OK; }
+static HRESULT token_list_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid) +{ + WCHAR *end; + LONG idx; + ULONG i; + + idx = wcstol(name, &end, 10); + if(*end) + return DISP_E_UNKNOWNNAME; + + i = idx + DISPID_TOKENLIST_0 - MSHTML_DISPID_CUSTOM_MIN; + if(i > MSHTML_CUSTOM_DISPID_CNT) + return DISP_E_UNKNOWNNAME; + + *dispid = MSHTML_DISPID_CUSTOM_MIN + i; + return S_OK; +} + +static HRESULT token_list_get_name(DispatchEx *dispex, DISPID id, BSTR *name) +{ + LONG idx = id - MSHTML_DISPID_CUSTOM_MIN; + WCHAR buf[12]; + UINT len; + + len = swprintf(buf, ARRAY_SIZE(buf), L"%d", idx); + return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; +} + +static HRESULT token_list_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + struct token_list *token_list = token_list_from_DispatchEx(dispex); + + TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", token_list, id, lcid, flags, params, res, ei, caller); + + switch(flags) { + case DISPATCH_PROPERTYGET: + return token_list_item(&token_list->IWineDOMTokenList_iface, id - DISPID_TOKENLIST_0, res); + case DISPATCH_PROPERTYPUTREF|DISPATCH_PROPERTYPUT: + case DISPATCH_PROPERTYPUTREF: + case DISPATCH_PROPERTYPUT: + /* Ignored by IE */ + return S_OK; + case DISPATCH_METHOD|DISPATCH_PROPERTYGET: + case DISPATCH_METHOD: + return MSHTML_E_NOT_FUNC; + default: + break; + } + + return MSHTML_E_INVALID_ACTION; +} + static const dispex_static_data_vtbl_t token_list_dispex_vtbl = { - token_list_value + token_list_value, + token_list_get_dispid, + token_list_get_name, + token_list_invoke };
static const tid_t token_list_iface_tids[] = { diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 8a14d2ee47f..4bc492f7532 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -75,6 +75,7 @@ #define MSHTML_E_INVALID_PROPERTY 0x800a01b6 #define MSHTML_E_INVALID_ACTION 0x800a01bd #define MSHTML_E_NODOC 0x800a025c +#define MSHTML_E_NOT_FUNC 0x800a138a
typedef struct DOMEvent DOMEvent; typedef struct HTMLDOMNode HTMLDOMNode; diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index 8a60cb2e1e4..4f2d1a5edc5 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -840,6 +840,39 @@ sync_test("classList", function() { ok(classList.length === 2, "Expected length 2 for className ' testclass foobar ', got " + classList.length); ok(("" + classList) === " testclass foobar ", "Expected classList value ' testclass foobar ', got " + classList); ok(classList.toString() === " testclass foobar ", "Expected classList toString ' testclass foobar ', got " + classList.toString()); + + r = classList[-1]; + ok(r === null, "classList[-1] = " + r); + r = classList[0]; + ok(r === "testclass", "classList[0] = " + r); + r = classList[1]; + ok(r === "foobar", "classList[1] = " + r); + r = classList[2]; + ok(r === null, "classList[2] = " + r); + + classList[0] = "barfoo"; + classList[2] = "added"; + ok(classList.toString() === " testclass foobar ", "Expected classList toString to not be changed after setting indexed props, got " + classList.toString()); + + try + { + classList[0](); + ok(false, "Expected exception calling classList[0]"); + } + catch(e) + { + ok(e.number === 0xa138a - 0x80000000, "Calling classList[0] threw " + e.number); + } + + try + { + new classList[0](); + ok(false, "Expected exception calling classList[0] as constructor"); + } + catch(e) + { + ok(e.number === 0xa01bd - 0x80000000, "Calling classList[0] as constructor threw " + e.number); + } });
sync_test("importNode", function() {