diff --git a/dlls/mshtml/htmlscript.h b/dlls/mshtml/htmlscript.h index 6d608d525a1..30b46677395 100644 --- a/dlls/mshtml/htmlscript.h +++ b/dlls/mshtml/htmlscript.h @@ -48,6 +48,7 @@ IDispatch *script_parse_event(HTMLInnerWindow*,LPCWSTR); HRESULT exec_script(HTMLInnerWindow*,const WCHAR*,const WCHAR*,VARIANT*); void update_browser_script_mode(GeckoBrowser*,IUri*); BOOL find_global_prop(HTMLInnerWindow*,const WCHAR*,DWORD,ScriptHost**,DISPID*); +HRESULT global_prop_still_exists(HTMLInnerWindow*,global_prop_t*); IDispatch *get_script_disp(ScriptHost*); IActiveScriptSite *get_first_script_site(HTMLInnerWindow*); void initialize_script_global(HTMLInnerWindow*); diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 1343c75ba34..d9ecf9d3d29 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3324,8 +3324,10 @@ HRESULT search_window_props(HTMLInnerWindow *This, const WCHAR *name, DWORD grfd for(i=0; i < This->global_prop_cnt; i++) { /* FIXME: case sensitivity */ if(!wcscmp(This->global_props[i].name, name)) { - *pid = MSHTML_DISPID_CUSTOM_MIN+i; - return S_OK; + HRESULT hres = global_prop_still_exists(This, &This->global_props[i]); + if(hres == S_OK) + *pid = MSHTML_DISPID_CUSTOM_MIN + i; + return (hres == DISP_E_MEMBERNOTFOUND) ? DISP_E_UNKNOWNNAME : hres; } } diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index 7ac26e63a3b..73bb8e1d5c6 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -85,6 +85,7 @@ struct ScriptHost { SCRIPTSTATE script_state; HTMLInnerWindow *window; + IDispatchEx *script_dispex; GUID guid; struct list entry; @@ -255,6 +256,18 @@ static BOOL init_script_engine(ScriptHost *script_host, IActiveScript *script) if(is_second_init) set_script_prop(first_host->script, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); } + + if(IsEqualGUID(&script_host->guid, &CLSID_JScript)) { + IDispatch *script_disp; + + hres = IActiveScript_GetScriptDispatch(script, NULL, &script_disp); + if(FAILED(hres)) + WARN("GetScriptDispatch failed: %08lx\n", hres); + else { + IDispatch_QueryInterface(script_disp, &IID_IDispatchEx, (void**)&script_host->script_dispex); + IDispatch_Release(script_disp); + } + } }else { WARN("AddNamedItem failed: %08lx\n", hres); } @@ -288,6 +301,8 @@ static void release_script_engine(ScriptHost *This) unlink_ref(&This->parse); } + if(This->script_dispex) + IDispatchEx_Release(This->script_dispex); IActiveScript_Release(This->script); This->script = NULL; This->script_state = SCRIPTSTATE_UNINITIALIZED; @@ -1825,6 +1840,48 @@ BOOL find_global_prop(HTMLInnerWindow *window, const WCHAR *name, DWORD flags, S return FALSE; } +HRESULT global_prop_still_exists(HTMLInnerWindow *window, global_prop_t *prop) +{ + HRESULT hres; + + switch(prop->type) { + case GLOBAL_SCRIPTVAR: { + DWORD properties; + + if(!prop->script_host->script) + return E_UNEXPECTED; + if(!prop->script_host->script_dispex) + return S_OK; + return IDispatchEx_GetMemberProperties(prop->script_host->script_dispex, prop->id, 0, &properties); + } + case GLOBAL_ELEMENTVAR: { + IHTMLElement *elem; + + hres = IHTMLDocument3_getElementById(&window->doc->IHTMLDocument3_iface, prop->name, &elem); + if(FAILED(hres)) + return hres; + + if(!elem) + return DISP_E_MEMBERNOTFOUND; + IHTMLElement_Release(elem); + return S_OK; + } + case GLOBAL_FRAMEVAR: { + HTMLOuterWindow *frame; + + hres = get_frame_by_name(window->base.outer_window, prop->name, FALSE, &frame); + if(FAILED(hres)) + return hres; + + return frame ? S_OK : DISP_E_MEMBERNOTFOUND; + } + default: + break; + } + + return S_OK; +} + static BOOL is_jscript_available(void) { static BOOL available, checked; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 53372ac7752..ca89fdadbdb 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1449,8 +1449,89 @@ sync_test("delete_prop", function() { ok(obj.globalprop4, "globalprop4 = " + globalprop4); r = (delete globalprop4); ok(r, "delete returned " + r); - todo_wine. ok(!("globalprop4" in obj), "globalprop4 is still in obj"); + + globalprop5 = true; + ok(obj.globalprop5, "globalprop5 = " + globalprop5); + try { + r = (delete window.globalprop5); + ok(v >= 9, "did not get an expected exception deleting globalprop5"); + ok(r, "delete returned " + r); + todo_wine. + ok(!("globalprop5" in obj), "globalprop5 is still in obj"); + }catch(ex) { + ok(v < 9, "expected exception deleting globalprop5"); + ok(ex.number === 0xa01bd - 0x80000000, "deleting globalprop5 threw " + ex.number); + ok("globalprop5" in obj, "globalprop5 is not in obj"); + } + + document.body.innerHTML = '
'; + ok("winetest" in obj, "winetest not in obj"); + try { + r = (delete window.winetest); + ok(v >= 9, "did not get an expected exception deleting winetest"); + ok(r, "delete returned " + r); + }catch(ex) { + ok(v < 9, "expected exception deleting winetest"); + ok(ex.number === 0xa01bd - 0x80000000, "deleting winetest threw " + ex.number); + } + ok("winetest" in obj, "winetest is not in obj"); + document.body.innerHTML = ""; + ok(!("winetest" in obj), "winetest is still in obj"); + + document.body.innerHTML = '
'; + ok("foobar" in obj, "foobar not in obj"); + window.foobar = "1234"; + ok(obj.foobar === "1234", "foobar = " + obj.foobar); + document.body.innerHTML = ""; + ok("foobar" in obj, "foobar is not in obj"); + ok(obj.foobar === "1234", "foobar = " + obj.foobar); + try { + r = (delete window.foobar); + ok(v >= 9, "did not get an expected exception deleting foobar"); + ok(r, "delete returned " + r); + ok(!("foobar" in obj), "foobar is still in obj"); + }catch(ex) { + ok(v < 9, "expected exception deleting foobar"); + ok(ex.number === 0xa01bd - 0x80000000, "deleting foobar threw " + ex.number); + ok("foobar" in obj, "foobar is not in obj"); + } + + document.body.innerHTML = '
'; + ok("barfoo" in obj, "barfoo not in obj"); + window.barfoo = "5678"; + ok(obj.barfoo === "5678", "barfoo = " + obj.barfoo); + try { + r = (delete window.barfoo); + ok(v >= 9, "did not get an expected exception deleting barfoo"); + ok(r, "delete returned " + r); + ok(obj.barfoo !== "5678", "barfoo is still 5678"); + }catch(ex) { + ok(v < 9, "expected exception deleting barfoo"); + ok(ex.number === 0xa01bd - 0x80000000, "deleting barfoo threw " + ex.number); + ok(obj.barfoo === "5678", "barfoo = " + obj.barfoo); + } + ok("barfoo" in obj, "barfoo is not in obj"); + document.body.innerHTML = ""; + if(v < 9) + ok("barfoo" in obj, "barfoo is not in obj"); + else + ok(!("barfoo" in obj), "barfoo is still in obj"); + + document.body.innerHTML = '