mshtml: Check if window global prop still exists before returning its id.

We have to introduce special handling for jscript, as it's probably integrated
on native mshtml.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
Gabriel Ivăncescu 2024-11-13 19:32:43 +02:00 committed by Alexandre Julliard
parent 055bf9f5a2
commit 9b264c948f
Notes: Alexandre Julliard 2024-11-14 23:12:21 +01:00
Approved-by: Jacek Caban (@jacek)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/wine/merge_requests/6721
4 changed files with 144 additions and 3 deletions

View file

@ -48,6 +48,7 @@ IDispatch *script_parse_event(HTMLInnerWindow*,LPCWSTR);
HRESULT exec_script(HTMLInnerWindow*,const WCHAR*,const WCHAR*,VARIANT*); HRESULT exec_script(HTMLInnerWindow*,const WCHAR*,const WCHAR*,VARIANT*);
void update_browser_script_mode(GeckoBrowser*,IUri*); void update_browser_script_mode(GeckoBrowser*,IUri*);
BOOL find_global_prop(HTMLInnerWindow*,const WCHAR*,DWORD,ScriptHost**,DISPID*); BOOL find_global_prop(HTMLInnerWindow*,const WCHAR*,DWORD,ScriptHost**,DISPID*);
HRESULT global_prop_still_exists(HTMLInnerWindow*,global_prop_t*);
IDispatch *get_script_disp(ScriptHost*); IDispatch *get_script_disp(ScriptHost*);
IActiveScriptSite *get_first_script_site(HTMLInnerWindow*); IActiveScriptSite *get_first_script_site(HTMLInnerWindow*);
void initialize_script_global(HTMLInnerWindow*); void initialize_script_global(HTMLInnerWindow*);

View file

@ -3324,8 +3324,10 @@ HRESULT search_window_props(HTMLInnerWindow *This, const WCHAR *name, DWORD grfd
for(i=0; i < This->global_prop_cnt; i++) { for(i=0; i < This->global_prop_cnt; i++) {
/* FIXME: case sensitivity */ /* FIXME: case sensitivity */
if(!wcscmp(This->global_props[i].name, name)) { if(!wcscmp(This->global_props[i].name, name)) {
*pid = MSHTML_DISPID_CUSTOM_MIN+i; HRESULT hres = global_prop_still_exists(This, &This->global_props[i]);
return S_OK; if(hres == S_OK)
*pid = MSHTML_DISPID_CUSTOM_MIN + i;
return (hres == DISP_E_MEMBERNOTFOUND) ? DISP_E_UNKNOWNNAME : hres;
} }
} }

View file

@ -85,6 +85,7 @@ struct ScriptHost {
SCRIPTSTATE script_state; SCRIPTSTATE script_state;
HTMLInnerWindow *window; HTMLInnerWindow *window;
IDispatchEx *script_dispex;
GUID guid; GUID guid;
struct list entry; struct list entry;
@ -255,6 +256,18 @@ static BOOL init_script_engine(ScriptHost *script_host, IActiveScript *script)
if(is_second_init) if(is_second_init)
set_script_prop(first_host->script, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); 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 { }else {
WARN("AddNamedItem failed: %08lx\n", hres); WARN("AddNamedItem failed: %08lx\n", hres);
} }
@ -288,6 +301,8 @@ static void release_script_engine(ScriptHost *This)
unlink_ref(&This->parse); unlink_ref(&This->parse);
} }
if(This->script_dispex)
IDispatchEx_Release(This->script_dispex);
IActiveScript_Release(This->script); IActiveScript_Release(This->script);
This->script = NULL; This->script = NULL;
This->script_state = SCRIPTSTATE_UNINITIALIZED; This->script_state = SCRIPTSTATE_UNINITIALIZED;
@ -1825,6 +1840,48 @@ BOOL find_global_prop(HTMLInnerWindow *window, const WCHAR *name, DWORD flags, S
return FALSE; 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 is_jscript_available(void)
{ {
static BOOL available, checked; static BOOL available, checked;

View file

@ -1449,8 +1449,89 @@ sync_test("delete_prop", function() {
ok(obj.globalprop4, "globalprop4 = " + globalprop4); ok(obj.globalprop4, "globalprop4 = " + globalprop4);
r = (delete globalprop4); r = (delete globalprop4);
ok(r, "delete returned " + r); ok(r, "delete returned " + r);
todo_wine.
ok(!("globalprop4" in obj), "globalprop4 is still in obj"); 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() { sync_test("detached arguments", function() {