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