[PATCH 3/4] mshtml: Implement IWineDOMTokenList_add() method.

Paul Gofman pgofman at codeweavers.com
Mon Jul 19 04:55:45 CDT 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/mshtml/htmlelem.c               | 127 +++++++++++++++++++++++++++
 dlls/mshtml/mshtml_private_iface.idl |   2 +
 dlls/mshtml/tests/dom.js             |  50 +++++++++++
 3 files changed, 179 insertions(+)

diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index 5bb3f1eaf15..b5b0daa2539 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -6490,6 +6490,132 @@ static HRESULT WINAPI token_list_Invoke(IWineDOMTokenList *iface, DISPID dispIdM
             pDispParams, pVarResult, pExcepInfo, puArgErr);
 }
 
+static const WCHAR *find_token(const WCHAR *list, const WCHAR *token, unsigned int token_len)
+{
+    const WCHAR *ptr, *next;
+
+    if (!list || !token)
+        return NULL;
+
+    ptr = list;
+    while (*ptr)
+    {
+        while (iswspace(*ptr))
+            ++ptr;
+        if (!*ptr)
+            break;
+        next = ptr + 1;
+        while (*next && !iswspace(*next))
+            ++next;
+
+        if (next - ptr == token_len && !wcsncmp(ptr, token, token_len))
+            return ptr;
+        ptr = next;
+    }
+    return NULL;
+}
+
+static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_array)
+{
+    struct token_list *token_list = impl_from_IWineDOMTokenList(iface);
+    unsigned int i, len, old_len, new_len;
+    WCHAR *token, *old, *new;
+    VARIANT *var, tmp;
+    HRESULT hr;
+
+    TRACE("iface %p, token_array %p.\n", iface, token_array);
+
+    hr = SafeArrayAccessData(token_array, (void**)&var);
+    if(FAILED(hr)) {
+        WARN("SafeArrayAccessData failed: %08x\n", hr);
+        return hr;
+    }
+
+    if (!token_array->rgsabound[0].cElements)
+    {
+        FIXME("No arguments given.");
+        SafeArrayUnaccessData(token_array);
+        return E_INVALIDARG;
+    }
+
+    if(V_VT(var) != VT_BSTR)
+    {
+        hr = VariantChangeTypeEx(&tmp, var, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR);
+        if(FAILED(hr))
+        {
+            WARN("Could not convert %s to string\n", debugstr_variant(var));
+            SafeArrayUnaccessData(token_array);
+            return hr;
+        }
+        token = V_BSTR(&tmp);
+    }
+    else
+    {
+        token = V_BSTR(var);
+    }
+
+    if (token_array->rgsabound[0].cElements > 1)
+        WARN("%u tokens given, using first one only.\n", token_array->rgsabound[0].cElements);
+
+    len = lstrlenW(token);
+    if (!len)
+    {
+        WARN("Empty token.\n");
+        hr = E_INVALIDARG;
+        goto done;
+    }
+
+    for (i = 0; i < len; ++i)
+        if (iswspace(token[i]))
+        {
+            WARN("Token has spaces.\n");
+            hr = E_INVALIDARG;
+            goto done;
+        }
+
+    if (FAILED(hr = IHTMLElement_get_className(token_list->element, &old)))
+        goto done;
+
+    TRACE("old %s.\n", debugstr_w(old));
+
+    if (find_token(old, token, len))
+    {
+        SysFreeString(old);
+        hr = S_OK;
+        goto done;
+    }
+
+    old_len = old ? lstrlenW(old) : 0;
+    new_len = old_len + len + !!old_len;
+
+    if (!(new = heap_alloc(sizeof(*new) * (new_len + 1))))
+    {
+        ERR("No memory.\n");
+        SysFreeString(old);
+        hr = E_OUTOFMEMORY;
+        goto done;
+    }
+
+    memcpy(new, old, sizeof(*new) * old_len);
+    if (old_len)
+        new[old_len++]= L' ';
+    memcpy(new + old_len, token, sizeof(*new) * len);
+    new[old_len + len] = 0;
+
+    SysFreeString(old);
+
+    TRACE("new %s.\n", debugstr_w(new));
+
+    hr = IHTMLElement_put_className(token_list->element, new);
+    heap_free(new);
+done:
+    SafeArrayUnaccessData(token_array);
+    if(V_VT(var) != VT_BSTR)
+        VariantClear(&tmp);
+
+    return hr;
+}
+
 static const IWineDOMTokenListVtbl WineDOMTokenListVtbl = {
     token_list_QueryInterface,
     token_list_AddRef,
@@ -6498,6 +6624,7 @@ static const IWineDOMTokenListVtbl WineDOMTokenListVtbl = {
     token_list_GetTypeInfo,
     token_list_GetIDsOfNames,
     token_list_Invoke,
+    token_list_add,
 };
 
 static const tid_t token_list_iface_tids[] = {
diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl
index 1764b0a8c9d..b50d2f9502b 100644
--- a/dlls/mshtml/mshtml_private_iface.idl
+++ b/dlls/mshtml/mshtml_private_iface.idl
@@ -111,6 +111,8 @@ interface IWineHTMLElementPrivate : IDispatch
 ]
 interface IWineDOMTokenList : IDispatch
 {
+    [vararg, id(1)]
+    HRESULT add([in] SAFEARRAY(VARIANT) token);
 }
 
 } /* library MSHTML_private */
diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js
index f54cb0f7088..ae6d49da26c 100644
--- a/dlls/mshtml/tests/dom.js
+++ b/dlls/mshtml/tests/dom.js
@@ -512,4 +512,54 @@ sync_test("hasAttribute", function() {
 sync_test("classList", function() {
     var elem = document.createElement("div");
     var classList = elem.classList;
+
+    classList.add("a");
+    ok(elem.className === "a", "Expected className 'a', got " + elem.className);
+
+    classList.add("b");
+    ok(elem.className === "a b", "Expected className 'a b', got " + elem.className);
+
+    classList.add("c", "d");
+    ok(elem.className === "a b c", "Expected className 'a b c', got " + elem.className);
+
+    classList.add(4);
+    ok(elem.className === "a b c 4", "Expected className 'a b c 4', got " + elem.className);
+
+    classList.add("c", "d");
+    ok(elem.className === "a b c 4", "(2) Expected className 'a b c 4', got " + elem.className);
+
+    var exception = false
+
+    try
+    {
+        classList.add();
+    }
+    catch(e)
+    {
+        exception = true;
+    }
+    ok(exception && elem.className === "a b c 4", "Expected exception, className 'a b c 4', got exception "
+            + exception + ", className" + elem.className);
+
+    exception = false
+    try
+    {
+        classList.add("");
+    }
+    catch(e)
+    {
+        exception = true;
+    }
+    ok(exception, "Expected exception for classList.add(\"\")");
+
+    exception = false
+    try
+    {
+        classList.add("e f");
+    }
+    catch(e)
+    {
+        exception = true;
+    }
+    ok(exception, "Expected exception for classList.add(\"e f\")");
 });
-- 
2.31.1




More information about the wine-devel mailing list