mshtml: Send load event synchronously for img elements that loaded instantly in legac...
[wine.git] / dlls / mshtml / htmlscript.c
blobe2ca3fb9b2a3e50069fa9c84bcbec711fb29839a
1 /*
2 * Copyright 2008 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
32 #include "htmlscript.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
36 static inline HTMLScriptElement *impl_from_IHTMLScriptElement(IHTMLScriptElement *iface)
38 return CONTAINING_RECORD(iface, HTMLScriptElement, IHTMLScriptElement_iface);
41 static HRESULT WINAPI HTMLScriptElement_QueryInterface(IHTMLScriptElement *iface,
42 REFIID riid, void **ppv)
44 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
46 return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
49 static ULONG WINAPI HTMLScriptElement_AddRef(IHTMLScriptElement *iface)
51 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
53 return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
56 static ULONG WINAPI HTMLScriptElement_Release(IHTMLScriptElement *iface)
58 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
60 return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
63 static HRESULT WINAPI HTMLScriptElement_GetTypeInfoCount(IHTMLScriptElement *iface, UINT *pctinfo)
65 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
66 return IDispatchEx_GetTypeInfoCount(&This->element.node.event_target.dispex.IDispatchEx_iface, pctinfo);
69 static HRESULT WINAPI HTMLScriptElement_GetTypeInfo(IHTMLScriptElement *iface, UINT iTInfo,
70 LCID lcid, ITypeInfo **ppTInfo)
72 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
73 return IDispatchEx_GetTypeInfo(&This->element.node.event_target.dispex.IDispatchEx_iface, iTInfo, lcid,
74 ppTInfo);
77 static HRESULT WINAPI HTMLScriptElement_GetIDsOfNames(IHTMLScriptElement *iface, REFIID riid,
78 LPOLESTR *rgszNames, UINT cNames,
79 LCID lcid, DISPID *rgDispId)
81 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
82 return IDispatchEx_GetIDsOfNames(&This->element.node.event_target.dispex.IDispatchEx_iface, riid, rgszNames,
83 cNames, lcid, rgDispId);
86 static HRESULT WINAPI HTMLScriptElement_Invoke(IHTMLScriptElement *iface, DISPID dispIdMember,
87 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
88 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
90 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
91 return IDispatchEx_Invoke(&This->element.node.event_target.dispex.IDispatchEx_iface, dispIdMember, riid,
92 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
95 static HRESULT WINAPI HTMLScriptElement_put_src(IHTMLScriptElement *iface, BSTR v)
97 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
98 nsAString src_str;
99 nsresult nsres;
100 HRESULT hres;
102 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
104 nsAString_InitDepend(&src_str, v);
105 nsres = nsIDOMHTMLScriptElement_SetSrc(This->nsscript, &src_str);
106 nsAString_Finish(&src_str);
107 if(NS_FAILED(nsres)) {
108 ERR("SetSrc failed: %08lx\n", nsres);
109 return E_FAIL;
112 if(This->parsed) {
113 WARN("already parsed\n");
114 return S_OK;
117 if(This->binding) {
118 FIXME("binding in progress\n");
119 return E_FAIL;
122 nsAString_Init(&src_str, NULL);
123 nsres = nsIDOMHTMLScriptElement_GetSrc(This->nsscript, &src_str);
124 if(NS_SUCCEEDED(nsres)) {
125 const PRUnichar *src;
126 nsAString_GetData(&src_str, &src);
127 hres = load_script(This, src, TRUE);
128 }else {
129 ERR("SetSrc failed: %08lx\n", nsres);
130 hres = E_FAIL;
132 nsAString_Finish(&src_str);
133 return hres;
136 static HRESULT WINAPI HTMLScriptElement_get_src(IHTMLScriptElement *iface, BSTR *p)
138 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
139 nsAString src_str;
140 nsresult nsres;
142 TRACE("(%p)->(%p)\n", This, p);
144 nsAString_Init(&src_str, NULL);
145 nsres = nsIDOMHTMLScriptElement_GetSrc(This->nsscript, &src_str);
146 return return_nsstr(nsres, &src_str, p);
149 static HRESULT WINAPI HTMLScriptElement_put_htmlFor(IHTMLScriptElement *iface, BSTR v)
151 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
152 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
153 return E_NOTIMPL;
156 static HRESULT WINAPI HTMLScriptElement_get_htmlFor(IHTMLScriptElement *iface, BSTR *p)
158 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
159 nsAString html_str;
160 nsresult nsres;
162 TRACE("(%p)->(%p)\n", This, p);
164 nsAString_Init(&html_str, NULL);
165 nsres = nsIDOMHTMLScriptElement_GetHtmlFor(This->nsscript, &html_str);
166 return return_nsstr(nsres, &html_str, p);
169 static HRESULT WINAPI HTMLScriptElement_put_event(IHTMLScriptElement *iface, BSTR v)
171 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
172 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
173 return E_NOTIMPL;
176 static HRESULT WINAPI HTMLScriptElement_get_event(IHTMLScriptElement *iface, BSTR *p)
178 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
179 FIXME("(%p)->(%p)\n", This, p);
180 return E_NOTIMPL;
183 static HRESULT WINAPI HTMLScriptElement_put_text(IHTMLScriptElement *iface, BSTR v)
185 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
186 HTMLInnerWindow *window;
187 nsIDOMNode *parent;
188 nsAString text_str;
189 nsresult nsres;
191 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
193 if(!This->element.node.doc || !This->element.node.doc->window) {
194 WARN("no window\n");
195 return E_UNEXPECTED;
198 window = This->element.node.doc->window;
200 nsAString_InitDepend(&text_str, v);
201 nsres = nsIDOMHTMLScriptElement_SetText(This->nsscript, &text_str);
202 nsAString_Finish(&text_str);
203 if(NS_FAILED(nsres)) {
204 ERR("SetSrc failed: %08lx\n", nsres);
205 return E_FAIL;
208 nsres = nsIDOMElement_GetParentNode(This->element.dom_element, &parent);
209 if(NS_FAILED(nsres) || !parent) {
210 TRACE("No parent, not executing\n");
211 This->parse_on_bind = TRUE;
212 return S_OK;
215 nsIDOMNode_Release(parent);
216 doc_insert_script(window, This, FALSE);
217 return S_OK;
220 static HRESULT WINAPI HTMLScriptElement_get_text(IHTMLScriptElement *iface, BSTR *p)
222 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
223 nsAString nsstr;
224 nsresult nsres;
226 TRACE("(%p)->(%p)\n", This, p);
228 nsAString_Init(&nsstr, NULL);
229 nsres = nsIDOMHTMLScriptElement_GetText(This->nsscript, &nsstr);
230 return return_nsstr(nsres, &nsstr, p);
233 static HRESULT WINAPI HTMLScriptElement_put_defer(IHTMLScriptElement *iface, VARIANT_BOOL v)
235 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
236 HRESULT hr = S_OK;
237 nsresult nsres;
239 TRACE("(%p)->(%x)\n", This, v);
241 nsres = nsIDOMHTMLScriptElement_SetDefer(This->nsscript, v != VARIANT_FALSE);
242 if(NS_FAILED(nsres))
244 hr = E_FAIL;
247 return hr;
250 static HRESULT WINAPI HTMLScriptElement_get_defer(IHTMLScriptElement *iface, VARIANT_BOOL *p)
252 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
253 cpp_bool defer = FALSE;
254 nsresult nsres;
256 TRACE("(%p)->(%p)\n", This, p);
258 if(!p)
259 return E_INVALIDARG;
261 nsres = nsIDOMHTMLScriptElement_GetDefer(This->nsscript, &defer);
262 if(NS_FAILED(nsres)) {
263 ERR("GetSrc failed: %08lx\n", nsres);
266 *p = variant_bool(defer);
267 return S_OK;
270 static HRESULT WINAPI HTMLScriptElement_get_readyState(IHTMLScriptElement *iface, BSTR *p)
272 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
274 TRACE("(%p)->(%p)\n", This, p);
276 return get_readystate_string(This->readystate, p);
279 static HRESULT WINAPI HTMLScriptElement_put_onerror(IHTMLScriptElement *iface, VARIANT v)
281 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
283 FIXME("(%p)->(%s) semi-stub\n", This, debugstr_variant(&v));
285 return set_node_event(&This->element.node, EVENTID_ERROR, &v);
288 static HRESULT WINAPI HTMLScriptElement_get_onerror(IHTMLScriptElement *iface, VARIANT *p)
290 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
292 TRACE("(%p)->(%p)\n", This, p);
294 return get_node_event(&This->element.node, EVENTID_ERROR, p);
297 static HRESULT WINAPI HTMLScriptElement_put_type(IHTMLScriptElement *iface, BSTR v)
299 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
300 nsAString nstype_str;
301 nsresult nsres;
303 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
305 nsAString_Init(&nstype_str, v);
306 nsres = nsIDOMHTMLScriptElement_SetType(This->nsscript, &nstype_str);
307 if (NS_FAILED(nsres))
308 ERR("SetType failed: %08lx\n", nsres);
309 nsAString_Finish (&nstype_str);
311 return S_OK;
314 static HRESULT WINAPI HTMLScriptElement_get_type(IHTMLScriptElement *iface, BSTR *p)
316 HTMLScriptElement *This = impl_from_IHTMLScriptElement(iface);
317 nsAString nstype_str;
318 nsresult nsres;
320 TRACE("(%p)->(%p)\n", This, p);
322 nsAString_Init(&nstype_str, NULL);
323 nsres = nsIDOMHTMLScriptElement_GetType(This->nsscript, &nstype_str);
324 return return_nsstr(nsres, &nstype_str, p);
327 static const IHTMLScriptElementVtbl HTMLScriptElementVtbl = {
328 HTMLScriptElement_QueryInterface,
329 HTMLScriptElement_AddRef,
330 HTMLScriptElement_Release,
331 HTMLScriptElement_GetTypeInfoCount,
332 HTMLScriptElement_GetTypeInfo,
333 HTMLScriptElement_GetIDsOfNames,
334 HTMLScriptElement_Invoke,
335 HTMLScriptElement_put_src,
336 HTMLScriptElement_get_src,
337 HTMLScriptElement_put_htmlFor,
338 HTMLScriptElement_get_htmlFor,
339 HTMLScriptElement_put_event,
340 HTMLScriptElement_get_event,
341 HTMLScriptElement_put_text,
342 HTMLScriptElement_get_text,
343 HTMLScriptElement_put_defer,
344 HTMLScriptElement_get_defer,
345 HTMLScriptElement_get_readyState,
346 HTMLScriptElement_put_onerror,
347 HTMLScriptElement_get_onerror,
348 HTMLScriptElement_put_type,
349 HTMLScriptElement_get_type
352 static inline HTMLScriptElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
354 return CONTAINING_RECORD(iface, HTMLScriptElement, element.node);
357 static HRESULT HTMLScriptElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
359 HTMLScriptElement *This = impl_from_HTMLDOMNode(iface);
361 *ppv = NULL;
363 if(IsEqualGUID(&IID_IUnknown, riid)) {
364 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
365 *ppv = &This->IHTMLScriptElement_iface;
366 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
367 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
368 *ppv = &This->IHTMLScriptElement_iface;
369 }else if(IsEqualGUID(&IID_IHTMLScriptElement, riid)) {
370 TRACE("(%p)->(IID_IHTMLScriptElement %p)\n", This, ppv);
371 *ppv = &This->IHTMLScriptElement_iface;
374 if(*ppv) {
375 IUnknown_AddRef((IUnknown*)*ppv);
376 return S_OK;
379 return HTMLElement_QI(&This->element.node, riid, ppv);
382 static void HTMLScriptElement_destructor(HTMLDOMNode *iface)
384 HTMLScriptElement *This = impl_from_HTMLDOMNode(iface);
385 free(This->src_text);
386 HTMLElement_destructor(&This->element.node);
389 static HRESULT HTMLScriptElement_get_readystate(HTMLDOMNode *iface, BSTR *p)
391 HTMLScriptElement *This = impl_from_HTMLDOMNode(iface);
393 return IHTMLScriptElement_get_readyState(&This->IHTMLScriptElement_iface, p);
396 static HRESULT HTMLScriptElement_bind_to_tree(HTMLDOMNode *iface)
398 HTMLScriptElement *This = impl_from_HTMLDOMNode(iface);
400 TRACE("(%p)\n", This);
402 if(!This->parse_on_bind)
403 return S_OK;
405 if(!This->element.node.doc || !This->element.node.doc->window) {
406 ERR("No window\n");
407 return E_UNEXPECTED;
410 This->parse_on_bind = FALSE;
411 doc_insert_script(This->element.node.doc->window, This, FALSE);
412 return S_OK;
415 static void HTMLScriptElement_traverse(HTMLDOMNode *iface, nsCycleCollectionTraversalCallback *cb)
417 HTMLScriptElement *This = impl_from_HTMLDOMNode(iface);
419 if(This->nsscript)
420 note_cc_edge((nsISupports*)This->nsscript, "This->nsscript", cb);
423 static void HTMLScriptElement_unlink(HTMLDOMNode *iface)
425 HTMLScriptElement *This = impl_from_HTMLDOMNode(iface);
427 if(This->nsscript) {
428 nsIDOMHTMLScriptElement *nsscript = This->nsscript;
430 This->nsscript = NULL;
431 nsIDOMHTMLScriptElement_Release(nsscript);
435 static const NodeImplVtbl HTMLScriptElementImplVtbl = {
436 &CLSID_HTMLScriptElement,
437 HTMLScriptElement_QI,
438 HTMLScriptElement_destructor,
439 HTMLElement_cpc,
440 HTMLElement_clone,
441 HTMLElement_dispatch_nsevent_hook,
442 HTMLElement_handle_event,
443 HTMLElement_get_attr_col,
444 NULL,
445 NULL,
446 NULL,
447 NULL,
448 HTMLScriptElement_get_readystate,
449 NULL,
450 NULL,
451 NULL,
452 HTMLScriptElement_bind_to_tree,
453 HTMLScriptElement_traverse,
454 HTMLScriptElement_unlink
457 HRESULT script_elem_from_nsscript(nsIDOMHTMLScriptElement *nsscript, HTMLScriptElement **ret)
459 nsIDOMNode *nsnode;
460 HTMLDOMNode *node;
461 nsresult nsres;
462 HRESULT hres;
464 nsres = nsIDOMHTMLScriptElement_QueryInterface(nsscript, &IID_nsIDOMNode, (void**)&nsnode);
465 assert(nsres == NS_OK);
467 hres = get_node(nsnode, TRUE, &node);
468 nsIDOMNode_Release(nsnode);
469 if(FAILED(hres))
470 return hres;
472 assert(node->vtbl == &HTMLScriptElementImplVtbl);
473 *ret = impl_from_HTMLDOMNode(node);
474 return S_OK;
477 static const tid_t HTMLScriptElement_iface_tids[] = {
478 HTMLELEMENT_TIDS,
479 IHTMLScriptElement_tid,
483 static dispex_static_data_t HTMLScriptElement_dispex = {
484 L"HTMLScriptElement",
485 NULL,
486 DispHTMLScriptElement_tid,
487 HTMLScriptElement_iface_tids,
488 HTMLElement_init_dispex_info
491 HRESULT HTMLScriptElement_Create(HTMLDocumentNode *doc, nsIDOMElement *nselem, HTMLElement **elem)
493 HTMLScriptElement *ret;
494 nsresult nsres;
496 ret = calloc(1, sizeof(HTMLScriptElement));
497 if(!ret)
498 return E_OUTOFMEMORY;
500 ret->IHTMLScriptElement_iface.lpVtbl = &HTMLScriptElementVtbl;
501 ret->element.node.vtbl = &HTMLScriptElementImplVtbl;
503 HTMLElement_Init(&ret->element, doc, nselem, &HTMLScriptElement_dispex);
505 nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMHTMLScriptElement, (void**)&ret->nsscript);
506 assert(nsres == NS_OK);
508 *elem = &ret->element;
509 return S_OK;