From 12755eeb1c72e83c785b56e17f6ad1b7ce36011c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= Date: Wed, 13 Nov 2024 19:32:43 +0200 Subject: [PATCH] mshtml: Reset builtin function props to their default values when deleted. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous tests bailed out too early on IE8, and did not test builtin props. Also added todos for tests that we did not even test because of returning early. Signed-off-by: Gabriel Ivăncescu --- dlls/mshtml/dispex.c | 62 ++++++++++++++++++++----------- dlls/mshtml/tests/documentmode.js | 47 +++++++++++++++++++---- 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index e194024607d..65c54ed8aec 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1764,6 +1764,26 @@ HRESULT dispex_call_builtin(DispatchEx *dispex, DISPID id, DISPPARAMS *dp, return call_builtin_function(dispex, func, dp, res, ei, caller); } +static VARIANT_BOOL reset_builtin_func(DispatchEx *dispex, func_info_t *func) +{ + func_obj_entry_t *entry; + + if(!dispex->dynamic_data || !dispex->dynamic_data->func_disps || + !dispex->dynamic_data->func_disps[func->func_disp_idx].func_obj) + return VARIANT_FALSE; + + entry = dispex->dynamic_data->func_disps + func->func_disp_idx; + if(V_VT(&entry->val) == VT_DISPATCH && + V_DISPATCH(&entry->val) == (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface) + return VARIANT_FALSE; + + VariantClear(&entry->val); + V_VT(&entry->val) = VT_DISPATCH; + V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface; + IDispatch_AddRef(V_DISPATCH(&entry->val)); + return VARIANT_TRUE; +} + HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) { switch(get_dispid_type(id)) { @@ -1793,26 +1813,7 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) /* For builtin functions, we set their value to the original function. */ if(func->func_disp_idx >= 0) { - func_obj_entry_t *entry; - - if(!This->dynamic_data || !This->dynamic_data->func_disps - || !This->dynamic_data->func_disps[func->func_disp_idx].func_obj) { - *success = VARIANT_FALSE; - return S_OK; - } - - entry = This->dynamic_data->func_disps + func->func_disp_idx; - if(V_VT(&entry->val) == VT_DISPATCH - && V_DISPATCH(&entry->val) == (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface) { - *success = VARIANT_FALSE; - return S_OK; - } - - VariantClear(&entry->val); - V_VT(&entry->val) = VT_DISPATCH; - V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface; - IDispatch_AddRef(V_DISPATCH(&entry->val)); - *success = VARIANT_TRUE; + *success = reset_builtin_func(This, func); return S_OK; } *success = VARIANT_TRUE; @@ -2304,7 +2305,8 @@ static HRESULT dispex_prop_delete(DispatchEx *dispex, DISPID id) return E_NOTIMPL; } - if(is_dynamic_dispid(id)) { + switch(get_dispid_type(id)) { + case DISPEXPROP_DYNAMIC: { DWORD idx = id - DISPID_DYNPROP_0; dynamic_prop_t *prop; @@ -2316,6 +2318,24 @@ static HRESULT dispex_prop_delete(DispatchEx *dispex, DISPID id) prop->flags |= DYNPROP_DELETED; return S_OK; } + case DISPEXPROP_BUILTIN: { + func_info_t *func; + HRESULT hres; + + if(!ensure_real_info(dispex)) + return E_OUTOFMEMORY; + + hres = get_builtin_func(dispex->info, id, &func); + if(FAILED(hres)) + return hres; + + if(func->func_disp_idx >= 0) + reset_builtin_func(dispex, func); + return S_OK; + } + default: + break; + } return S_OK; } diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 306d65e5768..ae5e68126dd 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1301,7 +1301,7 @@ sync_test("navigator", function() { sync_test("delete_prop", function() { var v = document.documentMode; - var obj = document.createElement("div"), r, obj2; + var obj = document.createElement("div"), r, obj2, func, prop; obj.prop1 = true; r = false; @@ -1317,6 +1317,40 @@ sync_test("delete_prop", function() { ok(!r, "got an unexpected exception"); ok(!("prop1" in obj), "prop1 is still in obj"); + /* builtin properties don't throw any exception, but are not really deleted */ + r = (delete obj.tagName); + ok(r, "delete returned " + r); + ok("tagName" in obj, "tagName deleted from obj"); + ok(obj.tagName === "DIV", "tagName = " + obj.tagName); + + prop = obj.id; + r = (delete obj.id); + ok(r, "delete returned " + r); + ok("id" in obj, "id deleted from obj"); + ok(obj.id === prop, "id = " + obj.id); + + obj.id = "1234"; + ok(obj.id === "1234", "id after set to 1234 = " + obj.id); + r = (delete obj.id); + ok(r, "delete returned " + r); + ok("id" in obj, "id deleted from obj"); + ok(obj.id === "1234", "id = " + obj.id); + + /* builtin functions get reset to their original values */ + func = function() { } + prop = obj.setAttribute; + r = (delete obj.setAttribute); + ok(r, "delete returned " + r); + ok("setAttribute" in obj, "setAttribute deleted from obj"); + ok(obj.setAttribute === prop, "setAttribute = " + obj.setAttribute); + + obj.setAttribute = func; + ok(obj.setAttribute === func, "setAttribute after set to func = " + obj.setAttribute); + r = (delete obj.setAttribute); + ok(r, "delete returned " + r); + ok("setAttribute" in obj, "setAttribute deleted from obj"); + ok(obj.setAttribute === prop, "setAttribute = " + obj.setAttribute); + /* again, this time prop1 does not exist */ r = false; try { @@ -1326,7 +1360,6 @@ sync_test("delete_prop", function() { } if(v < 9) { ok(r, "did not get an expected exception"); - return; }else { ok(!r, "got an unexpected exception"); ok(!("prop1" in obj), "prop1 is still in obj"); @@ -1337,12 +1370,6 @@ sync_test("delete_prop", function() { ok("className" in obj, "className deleted from obj"); ok(obj.className === "", "className = " + obj.className); - /* builtin propertiles don't throw any exception, but are not really deleted */ - r = (delete obj.tagName); - ok(r, "delete returned " + r); - ok("tagName" in obj, "tagName deleted from obj"); - ok(obj.tagName === "DIV", "tagName = " + obj.tagName); - obj = document.querySelectorAll("*"); ok("0" in obj, "0 is not in obj"); obj2 = obj[0]; @@ -1362,6 +1389,7 @@ sync_test("delete_prop", function() { r = true; } if(v < 9) { + todo_wine. ok(r, "did not get an expected exception"); }else { ok(!r, "got an unexpected globalprop1 exception"); @@ -1377,6 +1405,7 @@ sync_test("delete_prop", function() { r = true; } if(v < 9) { + todo_wine. ok(r, "did not get an expected globalprop2 exception"); }else { ok(!r, "got an unexpected exception"); @@ -1393,7 +1422,9 @@ sync_test("delete_prop", function() { r = true; } if(v < 9) { + todo_wine. ok(r, "did not get an expected exception"); + todo_wine. ok("globalprop3" in obj, "globalprop3 is not in obj"); }else { ok(!r, "got an unexpected globalprop3 exception");