mirror of
https://github.com/reactos/wine.git
synced 2025-02-13 16:59:37 +00:00
mshtml: Added support for recursive script runners.
This commit is contained in:
parent
bfebbbb13e
commit
c8a953c5d0
@ -586,13 +586,6 @@ struct HTMLFrameBase {
|
||||
nsIDOMHTMLIFrameElement *nsiframe;
|
||||
};
|
||||
|
||||
typedef struct _mutation_queue_t {
|
||||
DWORD type;
|
||||
nsISupports *nsiface;
|
||||
|
||||
struct _mutation_queue_t *next;
|
||||
} mutation_queue_t;
|
||||
|
||||
typedef struct nsDocumentEventListener nsDocumentEventListener;
|
||||
|
||||
struct HTMLDocumentNode {
|
||||
@ -602,7 +595,6 @@ struct HTMLDocumentNode {
|
||||
IInternetHostSecurityManager IInternetHostSecurityManager_iface;
|
||||
|
||||
nsIDocumentObserver nsIDocumentObserver_iface;
|
||||
nsIRunnable nsIRunnable_iface;
|
||||
|
||||
LONG ref;
|
||||
|
||||
@ -617,8 +609,6 @@ struct HTMLDocumentNode {
|
||||
BOOL *event_vector;
|
||||
|
||||
BOOL skip_mutation_notif;
|
||||
mutation_queue_t *mutation_queue;
|
||||
mutation_queue_t *mutation_queue_tail;
|
||||
|
||||
struct list bindings;
|
||||
struct list selection_list;
|
||||
|
@ -36,13 +36,6 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
|
||||
|
||||
enum {
|
||||
MUTATION_BINDTOTREE,
|
||||
MUTATION_COMMENT,
|
||||
MUTATION_ENDLOAD,
|
||||
MUTATION_SCRIPT
|
||||
};
|
||||
|
||||
#define IE_MAJOR_VERSION 7
|
||||
#define IE_MINOR_VERSION 0
|
||||
|
||||
@ -182,117 +175,78 @@ static BOOL handle_insert_comment(HTMLDocumentNode *doc, const PRUnichar *commen
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void add_script_runner(HTMLDocumentNode *This)
|
||||
static nsresult run_insert_comment(HTMLDocumentNode *doc, nsISupports *comment_iface, nsISupports *arg2)
|
||||
{
|
||||
nsIDOMNSDocument *nsdoc;
|
||||
const PRUnichar *comment;
|
||||
nsIDOMComment *nscomment;
|
||||
nsAString comment_str;
|
||||
BOOL remove_comment;
|
||||
nsresult nsres;
|
||||
|
||||
nsres = nsIDOMHTMLDocument_QueryInterface(This->nsdoc, &IID_nsIDOMNSDocument, (void**)&nsdoc);
|
||||
nsres = nsISupports_QueryInterface(comment_iface, &IID_nsIDOMComment, (void**)&nscomment);
|
||||
if(NS_FAILED(nsres)) {
|
||||
ERR("Could not get nsIDOMNSDocument: %08x\n", nsres);
|
||||
return;
|
||||
ERR("Could not get nsIDOMComment iface:%08x\n", nsres);
|
||||
return nsres;
|
||||
}
|
||||
|
||||
nsIDOMNSDocument_WineAddScriptRunner(nsdoc, &This->nsIRunnable_iface);
|
||||
nsIDOMNSDocument_Release(nsdoc);
|
||||
}
|
||||
nsAString_Init(&comment_str, NULL);
|
||||
nsres = nsIDOMComment_GetData(nscomment, &comment_str);
|
||||
if(NS_FAILED(nsres))
|
||||
return nsres;
|
||||
|
||||
static inline HTMLDocumentNode *impl_from_nsIRunnable(nsIRunnable *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, HTMLDocumentNode, nsIRunnable_iface);
|
||||
}
|
||||
nsAString_GetData(&comment_str, &comment);
|
||||
remove_comment = handle_insert_comment(doc, comment);
|
||||
nsAString_Finish(&comment_str);
|
||||
|
||||
static nsresult NSAPI nsRunnable_QueryInterface(nsIRunnable *iface,
|
||||
nsIIDRef riid, void **result)
|
||||
{
|
||||
HTMLDocumentNode *This = impl_from_nsIRunnable(iface);
|
||||
if(remove_comment) {
|
||||
nsIDOMNode *nsparent, *tmp;
|
||||
nsAString magic_str;
|
||||
|
||||
if(IsEqualGUID(riid, &IID_nsISupports)) {
|
||||
TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
|
||||
*result = &This->nsIRunnable_iface;
|
||||
}else if(IsEqualGUID(riid, &IID_nsIRunnable)) {
|
||||
TRACE("(%p)->(IID_nsIRunnable %p)\n", This, result);
|
||||
*result = &This->nsIRunnable_iface;
|
||||
}else {
|
||||
*result = NULL;
|
||||
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
|
||||
return NS_NOINTERFACE;
|
||||
static const PRUnichar remove_comment_magicW[] =
|
||||
{'#','!','w','i','n','e', 'r','e','m','o','v','e','!','#',0};
|
||||
|
||||
nsAString_InitDepend(&magic_str, remove_comment_magicW);
|
||||
nsres = nsIDOMComment_SetData(nscomment, &magic_str);
|
||||
nsAString_Finish(&magic_str);
|
||||
if(NS_FAILED(nsres))
|
||||
ERR("SetData failed: %08x\n", nsres);
|
||||
|
||||
nsIDOMComment_GetParentNode(nscomment, &nsparent);
|
||||
if(nsparent) {
|
||||
nsIDOMNode_RemoveChild(nsparent, (nsIDOMNode*)nscomment, &tmp);
|
||||
nsIDOMNode_Release(nsparent);
|
||||
nsIDOMNode_Release(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
nsISupports_AddRef((nsISupports*)*result);
|
||||
nsIDOMComment_Release(nscomment);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsrefcnt NSAPI nsRunnable_AddRef(nsIRunnable *iface)
|
||||
{
|
||||
HTMLDocumentNode *This = impl_from_nsIRunnable(iface);
|
||||
return htmldoc_addref(&This->basedoc);
|
||||
}
|
||||
|
||||
static nsrefcnt NSAPI nsRunnable_Release(nsIRunnable *iface)
|
||||
{
|
||||
HTMLDocumentNode *This = impl_from_nsIRunnable(iface);
|
||||
return htmldoc_release(&This->basedoc);
|
||||
}
|
||||
|
||||
static void push_mutation_queue(HTMLDocumentNode *doc, DWORD type, nsISupports *nsiface)
|
||||
{
|
||||
mutation_queue_t *elem;
|
||||
|
||||
elem = heap_alloc(sizeof(mutation_queue_t));
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
elem->next = NULL;
|
||||
elem->type = type;
|
||||
elem->nsiface = nsiface;
|
||||
if(nsiface)
|
||||
nsISupports_AddRef(nsiface);
|
||||
|
||||
if(doc->mutation_queue_tail) {
|
||||
doc->mutation_queue_tail = doc->mutation_queue_tail->next = elem;
|
||||
}else {
|
||||
doc->mutation_queue = doc->mutation_queue_tail = elem;
|
||||
add_script_runner(doc);
|
||||
}
|
||||
}
|
||||
|
||||
static void pop_mutation_queue(HTMLDocumentNode *doc)
|
||||
{
|
||||
mutation_queue_t *tmp = doc->mutation_queue;
|
||||
|
||||
if(!tmp)
|
||||
return;
|
||||
|
||||
doc->mutation_queue = tmp->next;
|
||||
if(!tmp->next)
|
||||
doc->mutation_queue_tail = NULL;
|
||||
|
||||
if(tmp->nsiface)
|
||||
nsISupports_Release(tmp->nsiface);
|
||||
heap_free(tmp);
|
||||
}
|
||||
|
||||
static void bind_to_tree(HTMLDocumentNode *doc, nsISupports *nsiface)
|
||||
static nsresult run_bind_to_tree(HTMLDocumentNode *doc, nsISupports *nsiface, nsISupports *arg2)
|
||||
{
|
||||
nsIDOMNode *nsnode;
|
||||
HTMLDOMNode *node;
|
||||
nsresult nsres;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("(%p)->(%p)\n", doc, nsiface);
|
||||
|
||||
nsres = nsISupports_QueryInterface(nsiface, &IID_nsIDOMNode, (void**)&nsnode);
|
||||
if(NS_FAILED(nsres))
|
||||
return;
|
||||
return nsres;
|
||||
|
||||
hres = get_node(doc, nsnode, TRUE, &node);
|
||||
nsIDOMNode_Release(nsnode);
|
||||
if(FAILED(hres)) {
|
||||
ERR("Could not get node\n");
|
||||
return;
|
||||
return nsres;
|
||||
}
|
||||
|
||||
if(node->vtbl->bind_to_tree)
|
||||
node->vtbl->bind_to_tree(node);
|
||||
|
||||
return nsres;
|
||||
}
|
||||
|
||||
/* Calls undocumented 69 cmd of CGID_Explorer */
|
||||
@ -332,12 +286,12 @@ static void parse_complete(HTMLDocumentObj *doc)
|
||||
/* FIXME: IE7 calls EnableModelless(TRUE), EnableModelless(FALSE) and sets interactive state here */
|
||||
}
|
||||
|
||||
static void handle_end_load(HTMLDocumentNode *This)
|
||||
static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISupports *arg2)
|
||||
{
|
||||
TRACE("\n");
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
if(!This->basedoc.doc_obj)
|
||||
return;
|
||||
return NS_OK;
|
||||
|
||||
if(This == This->basedoc.doc_obj->basedoc.doc_node) {
|
||||
/*
|
||||
@ -348,95 +302,103 @@ static void handle_end_load(HTMLDocumentNode *This)
|
||||
}
|
||||
|
||||
set_ready_state(This->basedoc.window, READYSTATE_INTERACTIVE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult run_insert_script(HTMLDocumentNode *doc, nsISupports *script_iface, nsISupports *arg)
|
||||
{
|
||||
nsIDOMHTMLScriptElement *nsscript;
|
||||
nsresult nsres;
|
||||
|
||||
TRACE("(%p)->(%p)\n", doc, script_iface);
|
||||
|
||||
nsres = nsISupports_QueryInterface(script_iface, &IID_nsIDOMHTMLScriptElement, (void**)&nsscript);
|
||||
if(NS_FAILED(nsres)) {
|
||||
ERR("Could not get nsIDOMHTMLScriptElement: %08x\n", nsres);
|
||||
return nsres;
|
||||
}
|
||||
|
||||
doc_insert_script(doc->basedoc.window, nsscript);
|
||||
nsIDOMHTMLScriptElement_Release(nsscript);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
typedef struct nsRunnable nsRunnable;
|
||||
|
||||
typedef nsresult (*runnable_proc_t)(HTMLDocumentNode*,nsISupports*,nsISupports*);
|
||||
|
||||
struct nsRunnable {
|
||||
nsIRunnable nsIRunnable_iface;
|
||||
|
||||
LONG ref;
|
||||
|
||||
runnable_proc_t proc;
|
||||
|
||||
HTMLDocumentNode *doc;
|
||||
nsISupports *arg1;
|
||||
nsISupports *arg2;
|
||||
};
|
||||
|
||||
static inline nsRunnable *impl_from_nsIRunnable(nsIRunnable *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, nsRunnable, nsIRunnable_iface);
|
||||
}
|
||||
|
||||
static nsresult NSAPI nsRunnable_QueryInterface(nsIRunnable *iface,
|
||||
nsIIDRef riid, void **result)
|
||||
{
|
||||
nsRunnable *This = impl_from_nsIRunnable(iface);
|
||||
|
||||
if(IsEqualGUID(riid, &IID_nsISupports)) {
|
||||
TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
|
||||
*result = &This->nsIRunnable_iface;
|
||||
}else if(IsEqualGUID(riid, &IID_nsIRunnable)) {
|
||||
TRACE("(%p)->(IID_nsIRunnable %p)\n", This, result);
|
||||
*result = &This->nsIRunnable_iface;
|
||||
}else {
|
||||
*result = NULL;
|
||||
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
nsISupports_AddRef((nsISupports*)*result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsrefcnt NSAPI nsRunnable_AddRef(nsIRunnable *iface)
|
||||
{
|
||||
nsRunnable *This = impl_from_nsIRunnable(iface);
|
||||
LONG ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static nsrefcnt NSAPI nsRunnable_Release(nsIRunnable *iface)
|
||||
{
|
||||
nsRunnable *This = impl_from_nsIRunnable(iface);
|
||||
LONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
|
||||
if(!ref) {
|
||||
htmldoc_release(&This->doc->basedoc);
|
||||
if(This->arg1)
|
||||
nsISupports_Release(This->arg1);
|
||||
if(This->arg2)
|
||||
nsISupports_Release(This->arg2);
|
||||
heap_free(This);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static nsresult NSAPI nsRunnable_Run(nsIRunnable *iface)
|
||||
{
|
||||
HTMLDocumentNode *This = impl_from_nsIRunnable(iface);
|
||||
nsresult nsres;
|
||||
nsRunnable *This = impl_from_nsIRunnable(iface);
|
||||
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
while(This->mutation_queue) {
|
||||
switch(This->mutation_queue->type) {
|
||||
case MUTATION_BINDTOTREE:
|
||||
bind_to_tree(This, This->mutation_queue->nsiface);
|
||||
break;
|
||||
|
||||
case MUTATION_COMMENT: {
|
||||
nsIDOMComment *nscomment;
|
||||
nsAString comment_str;
|
||||
BOOL remove_comment = FALSE;
|
||||
|
||||
nsres = nsISupports_QueryInterface(This->mutation_queue->nsiface, &IID_nsIDOMComment, (void**)&nscomment);
|
||||
if(NS_FAILED(nsres)) {
|
||||
ERR("Could not get nsIDOMComment iface:%08x\n", nsres);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAString_Init(&comment_str, NULL);
|
||||
nsres = nsIDOMComment_GetData(nscomment, &comment_str);
|
||||
if(NS_SUCCEEDED(nsres)) {
|
||||
const PRUnichar *comment;
|
||||
|
||||
nsAString_GetData(&comment_str, &comment);
|
||||
remove_comment = handle_insert_comment(This, comment);
|
||||
}
|
||||
|
||||
nsAString_Finish(&comment_str);
|
||||
|
||||
if(remove_comment) {
|
||||
nsIDOMNode *nsparent, *tmp;
|
||||
nsAString magic_str;
|
||||
|
||||
static const PRUnichar remove_comment_magicW[] =
|
||||
{'#','!','w','i','n','e', 'r','e','m','o','v','e','!','#',0};
|
||||
|
||||
nsAString_InitDepend(&magic_str, remove_comment_magicW);
|
||||
nsres = nsIDOMComment_SetData(nscomment, &magic_str);
|
||||
nsAString_Finish(&magic_str);
|
||||
if(NS_FAILED(nsres))
|
||||
ERR("SetData failed: %08x\n", nsres);
|
||||
|
||||
nsIDOMComment_GetParentNode(nscomment, &nsparent);
|
||||
if(nsparent) {
|
||||
nsIDOMNode_RemoveChild(nsparent, (nsIDOMNode*)nscomment, &tmp);
|
||||
nsIDOMNode_Release(nsparent);
|
||||
nsIDOMNode_Release(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
nsIDOMComment_Release(nscomment);
|
||||
break;
|
||||
}
|
||||
|
||||
case MUTATION_ENDLOAD:
|
||||
handle_end_load(This);
|
||||
break;
|
||||
|
||||
case MUTATION_SCRIPT: {
|
||||
nsIDOMHTMLScriptElement *nsscript;
|
||||
|
||||
nsres = nsISupports_QueryInterface(This->mutation_queue->nsiface, &IID_nsIDOMHTMLScriptElement,
|
||||
(void**)&nsscript);
|
||||
if(NS_FAILED(nsres)) {
|
||||
ERR("Could not get nsIDOMHTMLScriptElement: %08x\n", nsres);
|
||||
break;
|
||||
}
|
||||
|
||||
doc_insert_script(This->basedoc.window, nsscript);
|
||||
nsIDOMHTMLScriptElement_Release(nsscript);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ERR("invalid type %d\n", This->mutation_queue->type);
|
||||
}
|
||||
|
||||
pop_mutation_queue(This);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
return This->proc(This->doc, This->arg1, This->arg2);
|
||||
}
|
||||
|
||||
static const nsIRunnableVtbl nsRunnableVtbl = {
|
||||
@ -446,6 +408,42 @@ static const nsIRunnableVtbl nsRunnableVtbl = {
|
||||
nsRunnable_Run
|
||||
};
|
||||
|
||||
static void add_script_runner(HTMLDocumentNode *This, runnable_proc_t proc, nsISupports *arg1, nsISupports *arg2)
|
||||
{
|
||||
nsIDOMNSDocument *nsdoc;
|
||||
nsRunnable *runnable;
|
||||
nsresult nsres;
|
||||
|
||||
runnable = heap_alloc_zero(sizeof(*runnable));
|
||||
if(!runnable)
|
||||
return;
|
||||
|
||||
runnable->nsIRunnable_iface.lpVtbl = &nsRunnableVtbl;
|
||||
runnable->ref = 1;
|
||||
|
||||
htmldoc_addref(&This->basedoc);
|
||||
runnable->doc = This;
|
||||
runnable->proc = proc;
|
||||
|
||||
if(arg1)
|
||||
nsISupports_AddRef(arg1);
|
||||
runnable->arg1 = arg1;
|
||||
|
||||
if(arg2)
|
||||
nsISupports_AddRef(arg2);
|
||||
runnable->arg2 = arg2;
|
||||
|
||||
nsres = nsIDOMHTMLDocument_QueryInterface(This->nsdoc, &IID_nsIDOMNSDocument, (void**)&nsdoc);
|
||||
if(NS_SUCCEEDED(nsres)) {
|
||||
nsIDOMNSDocument_WineAddScriptRunner(nsdoc, &runnable->nsIRunnable_iface);
|
||||
nsIDOMNSDocument_Release(nsdoc);
|
||||
}else {
|
||||
ERR("Could not get nsIDOMNSDocument: %08x\n", nsres);
|
||||
}
|
||||
|
||||
nsIRunnable_Release(&runnable->nsIRunnable_iface);
|
||||
}
|
||||
|
||||
static inline HTMLDocumentNode *impl_from_nsIDocumentObserver(nsIDocumentObserver *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, HTMLDocumentNode, nsIDocumentObserver_iface);
|
||||
@ -555,7 +553,7 @@ static void NSAPI nsDocumentObserver_EndLoad(nsIDocumentObserver *iface, nsIDocu
|
||||
return;
|
||||
|
||||
This->content_ready = TRUE;
|
||||
push_mutation_queue(This, MUTATION_ENDLOAD, NULL);
|
||||
add_script_runner(This, run_end_load, NULL, NULL);
|
||||
}
|
||||
|
||||
static void NSAPI nsDocumentObserver_ContentStatesChanged(nsIDocumentObserver *iface, nsIDocument *aDocument,
|
||||
@ -620,7 +618,7 @@ static void NSAPI nsDocumentObserver_BindToDocument(nsIDocumentObserver *iface,
|
||||
if(NS_SUCCEEDED(nsres)) {
|
||||
TRACE("comment node\n");
|
||||
|
||||
push_mutation_queue(This, MUTATION_COMMENT, (nsISupports*)nscomment);
|
||||
add_script_runner(This, run_insert_comment, (nsISupports*)nscomment, NULL);
|
||||
nsIDOMComment_Release(nscomment);
|
||||
}
|
||||
|
||||
@ -628,7 +626,7 @@ static void NSAPI nsDocumentObserver_BindToDocument(nsIDocumentObserver *iface,
|
||||
if(NS_SUCCEEDED(nsres)) {
|
||||
TRACE("iframe node\n");
|
||||
|
||||
push_mutation_queue(This, MUTATION_BINDTOTREE, (nsISupports*)nsiframe);
|
||||
add_script_runner(This, run_bind_to_tree, (nsISupports*)nsiframe, NULL);
|
||||
nsIDOMHTMLIFrameElement_Release(nsiframe);
|
||||
}
|
||||
|
||||
@ -636,7 +634,7 @@ static void NSAPI nsDocumentObserver_BindToDocument(nsIDocumentObserver *iface,
|
||||
if(NS_SUCCEEDED(nsres)) {
|
||||
TRACE("frame node\n");
|
||||
|
||||
push_mutation_queue(This, MUTATION_BINDTOTREE, (nsISupports*)nsframe);
|
||||
add_script_runner(This, run_bind_to_tree, (nsISupports*)nsframe, NULL);
|
||||
nsIDOMHTMLFrameElement_Release(nsframe);
|
||||
}
|
||||
}
|
||||
@ -654,7 +652,7 @@ static void NSAPI nsDocumentObserver_DoneAddingChildren(nsIDocumentObserver *ifa
|
||||
if(NS_SUCCEEDED(nsres)) {
|
||||
TRACE("script node\n");
|
||||
|
||||
push_mutation_queue(This, MUTATION_SCRIPT, (nsISupports*)nsscript);
|
||||
add_script_runner(This, run_insert_script, (nsISupports*)nsscript, NULL);
|
||||
nsIDOMHTMLScriptElement_Release(nsscript);
|
||||
}
|
||||
}
|
||||
@ -694,7 +692,6 @@ void init_mutation(HTMLDocumentNode *doc)
|
||||
nsresult nsres;
|
||||
|
||||
doc->nsIDocumentObserver_iface.lpVtbl = &nsDocumentObserverVtbl;
|
||||
doc->nsIRunnable_iface.lpVtbl = &nsRunnableVtbl;
|
||||
|
||||
nsres = nsIDOMHTMLDocument_QueryInterface(doc->nsdoc, &IID_nsIDOMNSDocument, (void**)&nsdoc);
|
||||
if(NS_FAILED(nsres)) {
|
||||
|
@ -21,7 +21,7 @@ document.write("<script>"
|
||||
|
||||
len = document.getElementsByTagName('script').length;
|
||||
external.todo_wine_ok(len === 2, "script col length = " + len);
|
||||
external.todo_wine_ok(executed, "writen script not executed");
|
||||
ok(executed, "writen script not executed");
|
||||
|
||||
external.reportSuccess();
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user