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");