From: Gabriel Ivăncescu gabrielopcode@gmail.com
We have to introduce special handling for jscript, as it's probably integrated on native mshtml. We can't use GetScriptDispatch/GetDispID or GetMemberName or whatever on every lookup, as existing tests will fail (and they fail even if we change the compat mode, so it's not a compat mode thing).
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 5 ++ dlls/jscript/jscript.c | 7 +++ dlls/jscript/jscript.h | 1 + dlls/jscript/jsdisp.idl | 1 + dlls/mshtml/htmlscript.h | 1 + dlls/mshtml/htmlwindow.c | 6 ++- dlls/mshtml/script.c | 51 +++++++++++++++++++ dlls/mshtml/tests/documentmode.js | 83 ++++++++++++++++++++++++++++++- 8 files changed, 152 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index ab7d004bf04..0777bc10671 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2529,6 +2529,11 @@ jsdisp_t *iface_to_jsdisp(IDispatch *iface) : NULL; }
+HRESULT jsdisp_has_prop(jsdisp_t *jsdisp, DISPID id) +{ + return get_prop(jsdisp, id) ? S_OK : DISP_E_UNKNOWNNAME; +} + HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id) { dispex_prop_t *prop; diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index c42109b4143..9d71793f6d5 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -1451,6 +1451,12 @@ static ULONG WINAPI WineJScript_Release(IWineJScript *iface) return IActiveScript_Release(&This->IActiveScript_iface); }
+static HRESULT WINAPI WineJScript_GlobalPropExists(IWineJScript *iface, DISPID id) +{ + JScript *This = impl_from_IWineJScript(iface); + return jsdisp_has_prop(This->ctx->global, id); +} + static HRESULT WINAPI WineJScript_InitHostObject(IWineJScript *iface, IWineJSDispatchHost *host_obj, IWineJSDispatch *prototype, UINT32 flags, IWineJSDispatch **ret) { @@ -1469,6 +1475,7 @@ static const IWineJScriptVtbl WineJScriptVtbl = { WineJScript_QueryInterface, WineJScript_AddRef, WineJScript_Release, + WineJScript_GlobalPropExists, WineJScript_InitHostObject, WineJScript_InitHostConstructor, }; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index e9207c231d8..bede7ca135b 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -246,6 +246,7 @@ HRESULT init_host_constructor(script_ctx_t*,IWineJSDispatchHost*,IWineJSDispatch HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*); HRESULT disp_call_name(script_ctx_t*,IDispatch*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*); HRESULT disp_call_value_with_caller(script_ctx_t*,IDispatch*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*); +HRESULT jsdisp_has_prop(jsdisp_t*,DISPID); HRESULT jsdisp_call_value(jsdisp_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*); HRESULT jsdisp_call(jsdisp_t*,DISPID,WORD,unsigned,jsval_t*,jsval_t*); HRESULT jsdisp_call_name(jsdisp_t*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*); diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index b49d0c9b30d..97a4e398522 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -82,6 +82,7 @@ interface IWineJSDispatchHost : IDispatchEx ] interface IWineJScript : IUnknown { + HRESULT GlobalPropExists(DISPID id); HRESULT InitHostObject(IWineJSDispatchHost *host_obj, IWineJSDispatch *prototype, UINT32 flags, IWineJSDispatch **ret); HRESULT InitHostConstructor(IWineJSDispatchHost *constr, IWineJSDispatch *prototype, IWineJSDispatch **ret); } 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 2409b3a1288..3fbcc7dd660 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; } }
diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index 7ac26e63a3b..0cdadfa5fbc 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -1825,6 +1825,57 @@ 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: { + IWineJScript *jscript; + + if(!prop->script_host->script) + return E_UNEXPECTED; + + if(!IsEqualGUID(&CLSID_JScript, &prop->script_host->guid) || + IActiveScript_QueryInterface(prop->script_host->script, &IID_IWineJScript, (void **)&jscript) != S_OK) + return S_OK; + + hres = IWineJScript_GlobalPropExists(jscript, prop->id); + IWineJScript_Release(jscript); + return hres; + } + case GLOBAL_ELEMENTVAR: { + IHTMLElement *elem; + BSTR bstr; + + if(!(bstr = SysAllocString(prop->name))) + return E_OUTOFMEMORY; + hres = IHTMLDocument3_getElementById(&window->doc->IHTMLDocument3_iface, bstr, &elem); + SysFreeString(bstr); + if(FAILED(hres)) + return hres; + + if(!elem) + return DISP_E_UNKNOWNNAME; + 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 == DISP_E_MEMBERNOTFOUND) ? DISP_E_UNKNOWNNAME : hres; + + return frame ? S_OK : DISP_E_UNKNOWNNAME; + } + 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 cc1ec1aa964..ed2ad8cd187 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1447,8 +1447,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 = '<div id="winetest"/>'; + 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 = '<div id="foobar"/>'; + 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 = '<div id="barfoo"/>'; + 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 = '<iframe id="testwine"/>'; + ok("testwine" in obj, "testwine not in obj"); + try { + r = (delete window.testwine); + ok(v >= 9, "did not get an expected exception deleting testwine"); + ok(r, "delete returned " + r); + }catch(ex) { + ok(v < 9, "expected exception deleting testwine"); + ok(ex.number === 0xa01bd - 0x80000000, "deleting testwine threw " + ex.number); + } + ok("testwine" in obj, "testwine is not in obj"); + + document.body.innerHTML = ""; + ok(!("testwine" in obj), "testwine is still in obj"); });
sync_test("detached arguments", function() {