mshtml: Allow setting event handlers to strings.

oldstable
Jacek Caban 2015-03-10 18:27:31 +01:00 committed by Alexandre Julliard
parent c61407f651
commit 144056bce0
5 changed files with 75 additions and 21 deletions

View File

@ -1367,23 +1367,29 @@ void detach_events(HTMLDocumentNode *doc)
}
static HRESULT remove_event_handler(event_target_t **event_target, eventid_t eid)
static void remove_event_handler(DispatchEx *dispex, event_target_t **event_target, eventid_t eid)
{
VARIANT *store;
HRESULT hres;
hres = dispex_get_dprop_ref(dispex, event_info[eid].attr_name, FALSE, &store);
if(SUCCEEDED(hres))
VariantClear(store);
if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) {
IDispatch_Release((*event_target)->event_table[eid]->handler_prop);
(*event_target)->event_table[eid]->handler_prop = NULL;
}
return S_OK;
}
static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, HTMLDocumentNode *doc,
static HRESULT set_event_handler_disp(DispatchEx *dispex, event_target_t **event_target_ptr, HTMLDocumentNode *doc,
eventid_t eid, IDispatch *disp)
{
event_target_t *event_target;
remove_event_handler(dispex, event_target_ptr, eid);
if(!disp)
return remove_event_handler(event_target_ptr, eid);
return S_OK;
event_target = get_event_target(event_target_ptr);
if(!event_target)
@ -1392,23 +1398,44 @@ static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, HTMLDoc
if(!alloc_handler_vector(event_target, eid, 0))
return E_OUTOFMEMORY;
if(event_target->event_table[eid]->handler_prop)
IDispatch_Release(event_target->event_table[eid]->handler_prop);
event_target->event_table[eid]->handler_prop = disp;
IDispatch_AddRef(disp);
return ensure_nsevent_handler(doc, event_target, eid);
}
HRESULT set_event_handler(event_target_t **event_target, HTMLDocumentNode *doc, eventid_t eid, VARIANT *var)
HRESULT set_event_handler(DispatchEx *dispex, event_target_t **event_target, HTMLDocumentNode *doc, eventid_t eid, VARIANT *var)
{
switch(V_VT(var)) {
case VT_NULL:
return remove_event_handler(event_target, eid);
remove_event_handler(dispex, event_target, eid);
return S_OK;
case VT_DISPATCH:
return set_event_handler_disp(event_target, doc, eid, V_DISPATCH(var));
return set_event_handler_disp(dispex, event_target, doc, eid, V_DISPATCH(var));
case VT_BSTR: {
VARIANT *v;
HRESULT hres;
/*
* Setting event handler to string is a rare case and we don't want to
* complicate nor increase memory of event_target_t for that. Instead,
* we store the value in DispatchEx, which can already handle custom
* properties.
*/
remove_event_handler(dispex, event_target, eid);
hres = dispex_get_dprop_ref(dispex, event_info[eid].attr_name, TRUE, &v);
if(FAILED(hres))
return hres;
V_BSTR(v) = SysAllocString(V_BSTR(var));
if(!V_BSTR(v))
return E_OUTOFMEMORY;
V_VT(v) = VT_BSTR;
return S_OK;
}
default:
FIXME("not handler %s\n", debugstr_variant(var));
@ -1420,8 +1447,15 @@ HRESULT set_event_handler(event_target_t **event_target, HTMLDocumentNode *doc,
return S_OK;
}
HRESULT get_event_handler(event_target_t **event_target, eventid_t eid, VARIANT *var)
HRESULT get_event_handler(DispatchEx *dispex, event_target_t **event_target, eventid_t eid, VARIANT *var)
{
VARIANT *v;
HRESULT hres;
hres = dispex_get_dprop_ref(dispex, event_info[eid].attr_name, FALSE, &v);
if(SUCCEEDED(hres) && V_VT(v) != VT_EMPTY)
return VariantCopy(var, v);
if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) {
V_VT(var) = VT_DISPATCH;
V_DISPATCH(var) = (*event_target)->event_table[eid]->handler_prop;
@ -1507,7 +1541,7 @@ void bind_node_event(HTMLDocumentNode *doc, event_target_t **event_target, HTMLD
return;
}
set_event_handler_disp(event_target, doc, eid, disp);
set_event_handler_disp(&node->dispex, event_target, doc, eid, disp);
}
void update_cp_events(HTMLInnerWindow *window, event_target_t **event_target_ptr, cp_static_data_t *cp)
@ -1547,7 +1581,7 @@ void check_event_attr(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem)
if(disp) {
hres = get_node(doc, (nsIDOMNode*)nselem, TRUE, &node);
if(SUCCEEDED(hres)) {
set_event_handler_disp(get_node_event_target(node), node->doc, i, disp);
set_event_handler_disp(&node->dispex, get_node_event_target(node), node->doc, i, disp);
node_release(node);
}
IDispatch_Release(disp);

View File

@ -54,8 +54,8 @@ eventid_t str_to_eid(LPCWSTR) DECLSPEC_HIDDEN;
void check_event_attr(HTMLDocumentNode*,nsIDOMHTMLElement*) DECLSPEC_HIDDEN;
void release_event_target(event_target_t*) DECLSPEC_HIDDEN;
void fire_event(HTMLDocumentNode*,eventid_t,BOOL,nsIDOMNode*,nsIDOMEvent*,IDispatch*) DECLSPEC_HIDDEN;
HRESULT set_event_handler(event_target_t**,HTMLDocumentNode*,eventid_t,VARIANT*) DECLSPEC_HIDDEN;
HRESULT get_event_handler(event_target_t**,eventid_t,VARIANT*) DECLSPEC_HIDDEN;
HRESULT set_event_handler(DispatchEx*,event_target_t**,HTMLDocumentNode*,eventid_t,VARIANT*) DECLSPEC_HIDDEN;
HRESULT get_event_handler(DispatchEx*,event_target_t**,eventid_t,VARIANT*) DECLSPEC_HIDDEN;
HRESULT attach_event(event_target_t**,HTMLDocument*,BSTR,IDispatch*,VARIANT_BOOL*) DECLSPEC_HIDDEN;
HRESULT detach_event(event_target_t*,HTMLDocument*,BSTR,IDispatch*) DECLSPEC_HIDDEN;
HRESULT dispatch_event(HTMLDOMNode*,const WCHAR*,VARIANT*,VARIANT_BOOL*) DECLSPEC_HIDDEN;
@ -78,12 +78,12 @@ static inline event_target_t **get_node_event_target(HTMLDOMNode *node)
static inline HRESULT set_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var)
{
return set_event_handler(get_node_event_target(node), node->doc, eid, var);
return set_event_handler(&node->dispex, get_node_event_target(node), node->doc, eid, var);
}
static inline HRESULT get_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var)
{
return get_event_handler(get_node_event_target(node), eid, var);
return get_event_handler(&node->dispex, get_node_event_target(node), eid, var);
}
static inline HRESULT set_doc_event(HTMLDocument *doc, eventid_t eid, VARIANT *var)

View File

@ -95,7 +95,8 @@ static inline HRESULT set_window_event(HTMLWindow *window, eventid_t eid, VARIAN
return E_FAIL;
}
return set_event_handler(&window->inner_window->doc->body_event_target, window->inner_window->doc, eid, var);
return set_event_handler(&window->inner_window->dispex, &window->inner_window->doc->body_event_target,
window->inner_window->doc, eid, var);
}
static inline HRESULT get_window_event(HTMLWindow *window, eventid_t eid, VARIANT *var)
@ -105,7 +106,7 @@ static inline HRESULT get_window_event(HTMLWindow *window, eventid_t eid, VARIAN
return E_FAIL;
}
return get_event_handler(&window->inner_window->doc->body_event_target, eid, var);
return get_event_handler(&window->inner_window->dispex, &window->inner_window->doc->body_event_target, eid, var);
}
static void detach_inner_window(HTMLInnerWindow *window)

View File

@ -1571,7 +1571,7 @@ static void test_onclick(IHTMLDocument2 *doc)
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = a2bstr("function();");
hres = IHTMLElement_put_onclick(div, v);
todo_wine ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
if(hres == S_OK) {
V_VT(&v) = VT_EMPTY;

View File

@ -139,6 +139,24 @@ function test_insert_script() {
readystatechange_log = "append";
}
var string_handler_called = false;
function test_string_event_handler() {
var e = document.createElement("div");
var event_str = "string_handler_called = true;";
document.body.appendChild(e);
e.onclick = event_str;
ok(e.onclick === event_str, "e.onclick = " + e.onclick);
e.click();
ok(string_handler_called === false, "string handler called");
e.setAttribute("onclick", event_str);
ok(e.onclick === event_str, "e.onclick = " + e.onclick);
e.click();
ok(string_handler_called === false, "string handler called");
}
window.onload = function() {
try {
ok(inlscr_complete_called, "onreadystatechange not fired");
@ -159,6 +177,7 @@ window.onload = function() {
ondataavailable_test();
test_handler_this();
test_insert_script();
test_string_event_handler();
}catch(e) {
ok(false, "Got an exception: " + e.message);
}