This is just nodes for now. The tests in the last patch may seem a bit overkill now, but it will be used for all the other prototypes, so they'll only need extra entries in the array/table, making it way simpler and less redundant.
-- v4: mshtml: Don't expose swapNode from NodePrototype. mshtml: Don't expose replaceNode from NodePrototype. mshtml: Don't expose removeNode from NodePrototype. mshtml: Expose ownerDocument from NodePrototype. mshtml/tests: Add initial tests for prototype chain props. mshtml: Enumerate all own builtin props from host object's NextProperty.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Since it's used when filling the props and by getOwnPropertyNames which includes non-enumerable props. Enumeration on jscript side should still filter the props correctly, if needed.
Note that we have to only enumerate those that are found on the actual object, not its prototypes.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 15 +++++++++------ dlls/mshtml/htmlelem.c | 2 +- dlls/mshtml/mshtml_private.h | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 65c54ed8aec..f69f1fe242c 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -52,9 +52,10 @@ typedef struct {
typedef struct { DISPID id; - BSTR name; tid_t tid; + BSTR name; dispex_hook_invoke_t hook; + BOOLEAN on_prototype; SHORT call_vtbl_off; SHORT put_vtbl_off; SHORT get_vtbl_off; @@ -594,8 +595,10 @@ static dispex_data_t *preprocess_dispex_data(dispex_static_data_t *desc, compat_ data->name_table = malloc(data->func_cnt * sizeof(func_info_t*)); for(i=0; i < data->func_cnt; i++) { /* Don't expose properties that are exposed by object's prototype */ - if(find_prototype_member(data, data->funcs[i].id)) + if(find_prototype_member(data, data->funcs[i].id)) { + data->funcs[i].on_prototype = TRUE; continue; + } data->name_table[data->name_cnt++] = data->funcs+i; } qsort(data->name_table, data->name_cnt, sizeof(func_info_t*), func_name_cmp); @@ -2455,7 +2458,7 @@ static HRESULT next_dynamic_id(DispatchEx *dispex, DWORD idx, DISPID *ret_id) return S_OK; }
-HRESULT dispex_next_id(DispatchEx *dispex, DISPID id, DISPID *ret) +HRESULT dispex_next_id(DispatchEx *dispex, DISPID id, BOOL enum_all_own_props, DISPID *ret) { func_info_t *func; HRESULT hres; @@ -2480,7 +2483,7 @@ HRESULT dispex_next_id(DispatchEx *dispex, DISPID id, DISPID *ret) }
while(func < dispex->info->funcs + dispex->info->func_cnt) { - if(func->func_disp_idx == -1) { + if(enum_all_own_props ? (!func->on_prototype) : (func->func_disp_idx == -1)) { *ret = func->id; return S_OK; } @@ -2513,7 +2516,7 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IWineJSDispatchHost *iface, DWORD return E_OUTOFMEMORY; if(This->jsdisp) return IWineJSDispatch_GetNextDispID(This->jsdisp, grfdex, id, pid); - return dispex_next_id(This, id, pid); + return dispex_next_id(This, id, FALSE, pid); }
static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IWineJSDispatchHost *iface, IUnknown **ppunk) @@ -2616,7 +2619,7 @@ static HRESULT WINAPI JSDispatchHost_NextProperty(IWineJSDispatchHost *iface, DI
TRACE("%s (%p)->(%lx)\n", This->info->name, This, id);
- hres = dispex_next_id(This, id, &next); + hres = dispex_next_id(This, id, TRUE, &next); if(hres != S_OK) return hres;
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 0cc41bf41a3..72aeaae816e 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -7513,7 +7513,7 @@ static HRESULT get_attr_dispid_by_relative_idx(HTMLAttributeCollection *This, LO FIXME("filter non-enumerable attributes out\n");
while(1) { - hres = dispex_next_id(&This->elem->node.event_target.dispex, id, &id); + hres = dispex_next_id(&This->elem->node.event_target.dispex, id, FALSE, &id); if(FAILED(hres)) return hres; else if(hres == S_FALSE) diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 591bb3eddd1..11ee0afd3c7 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -631,7 +631,7 @@ HRESULT dispex_prop_put(DispatchEx *dispex, DISPID id, LCID lcid, VARIANT *v, EX IServiceProvider *caller); HRESULT dispex_get_chain_builtin_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID *pid); HRESULT dispex_get_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID *pid); -HRESULT dispex_next_id(DispatchEx *dispex, DISPID id, DISPID *ret); +HRESULT dispex_next_id(DispatchEx *dispex, DISPID id, BOOL enum_all_own_props, DISPID *ret); HRESULT dispex_prop_name(DispatchEx *dispex, DISPID id, BSTR *ret); HRESULT dispex_define_property(DispatchEx *dispex, const WCHAR *name, DWORD flags, VARIANT *v, DISPID *id); HRESULT dispex_index_prop_desc(DispatchEx*,DISPID,struct property_info*);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/documentmode.js | 97 +++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+)
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 0ee20de7a90..a92e3d8fbd6 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3351,6 +3351,54 @@ sync_test("form", function() { ok(form[0] === "test", "form[0] = " + form[0]); });
+function test_own_props(obj, name, props, todos, flaky) { + var v = document.documentMode, prop, expected = {}, enumerated = Object.getOwnPropertyNames(obj).sort(); + + if(flaky) + enumerated = enumerated.filter(function(p) { return flaky.indexOf(p) === -1; }); + if(props) { + for(i = 0; i < props.length; i++) { + prop = props[i]; + if(Array.isArray(prop)) { + if(v < prop[1] || (prop.length > 2 && v > prop[2])) + continue; + prop = prop[0]; + } + expected[prop] |= 1; + } + } + if(todos) { + for(i = 0; i < todos.length; i++) { + prop = todos[i]; + if(Array.isArray(prop)) { + if(v < prop[1] || (prop.length > 2 && v > prop[2])) + continue; + prop = prop[0]; + } + expected[prop] |= 2; /* 2 marks todo */ + } + } + for(i = 0; i < enumerated.length; i++) { + prop = enumerated[i]; + if(!expected.hasOwnProperty(prop)) + ok(false, prop + " is a prop of " + name); + else { + if(expected[prop] & 1) { + todo_wine_if(expected[prop] & 2). + ok(true, prop + " not a prop of " + name); + }else { + todo_wine_if(expected[prop] & 2). + ok(false, prop + " is a prop of " + name); + } + delete expected[prop]; + } + } + for(prop in expected) { + todo_wine_if(expected[prop] & 2). + ok(!(expected[prop] & 1), prop + " not a prop of " + name); + } +} + sync_test("prototypes", function() { var v = document.documentMode; if(v < 9) @@ -3567,3 +3615,52 @@ sync_test("prototypes", function() { check(document.createDocumentFragment(), DocumentFragment.prototype, "fragment"); check(DocumentFragment.prototype, Node.prototype, "fragment prototype"); }); + +sync_test("prototype props", function() { + var v = document.documentMode; + if(v < 9) + return; + + function check(constr, props, todos, flaky) { + var name = Object.prototype.toString.call(constr).slice(8, -1) + ".prototype"; + ok(constr.prototype.constructor === constr, name + "'s constructor not original constructor"); + + props.push("constructor"); + test_own_props(constr.prototype, name, props, todos, flaky); + } + + check(CSSStyleRule, [ "readOnly", "selectorText", "style" ]); + check(CustomEvent, [ "detail", "initCustomEvent" ]); + check(Event, [ + "AT_TARGET", "BUBBLING_PHASE", "CAPTURING_PHASE", "bubbles", "cancelBubble", "cancelable", "currentTarget", + "defaultPrevented", "eventPhase", "initEvent", "isTrusted", "preventDefault", "srcElement", + "stopImmediatePropagation", "stopPropagation", "target", "timeStamp", "type" + ], [ "AT_TARGET", "BUBBLING_PHASE", "CAPTURING_PHASE" ]); + check(HTMLUnknownElement, [ "namedRecordset", "recordset" ]); + check(MessageEvent, [ "data", "initMessageEvent", "origin", ["ports",10], "source" ], [ ["ports",10] ]); + check(MouseEvent, [ + "altKey", "button", "buttons", "clientX", "clientY", "ctrlKey", "fromElement", "getModifierState", + "initMouseEvent", "layerX", "layerY", "metaKey", "offsetX", "offsetY", "pageX", "pageY", "relatedTarget", + "screenX", "screenY", "shiftKey", "toElement", "which", "x", "y" + ]); + check(Node, [ + "ATTRIBUTE_NODE", "CDATA_SECTION_NODE", "COMMENT_NODE", "DOCUMENT_FRAGMENT_NODE", "DOCUMENT_NODE", + "DOCUMENT_POSITION_CONTAINED_BY", "DOCUMENT_POSITION_CONTAINS", "DOCUMENT_POSITION_DISCONNECTED", + "DOCUMENT_POSITION_FOLLOWING", "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", "DOCUMENT_POSITION_PRECEDING", + "DOCUMENT_TYPE_NODE", "ELEMENT_NODE", "ENTITY_NODE", "ENTITY_REFERENCE_NODE", "NOTATION_NODE", + "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "addEventListener", "appendChild", "attributes", "childNodes", "cloneNode", + "compareDocumentPosition", "dispatchEvent", "firstChild", "hasAttributes", "hasChildNodes", "insertBefore", + "isDefaultNamespace", "isEqualNode", "isSameNode", "isSupported", "lastChild", "localName", "lookupNamespaceURI", + "lookupPrefix", "namespaceURI", "nextSibling", "nodeName", "nodeType", "nodeValue", "normalize", "ownerDocument", + "parentNode", "prefix", "previousSibling", "removeChild", "removeEventListener", "replaceChild", "textContent" + ], [ + "ATTRIBUTE_NODE", "CDATA_SECTION_NODE", "COMMENT_NODE", "DOCUMENT_FRAGMENT_NODE", "DOCUMENT_NODE", + "DOCUMENT_POSITION_CONTAINED_BY", "DOCUMENT_POSITION_CONTAINS", "DOCUMENT_POSITION_DISCONNECTED", + "DOCUMENT_POSITION_FOLLOWING", "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", "DOCUMENT_POSITION_PRECEDING", + "DOCUMENT_TYPE_NODE", "ELEMENT_NODE", "ENTITY_NODE", "ENTITY_REFERENCE_NODE", "NOTATION_NODE", + "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "hasAttributes", "normalize", "ownerDocument", "removeNode", + "replaceNode", "swapNode" + ]); + check(StorageEvent, [ "initStorageEvent", "key", "newValue", "oldValue", "storageArea", "url" ]); + check(UIEvent, [ "detail", "initUIEvent", "view" ], null, [ "deviceSessionId" ]); +});
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlnode.c | 4 +++- dlls/mshtml/tests/documentmode.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index 7fad8f22357..ad22ef9dc48 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -1252,8 +1252,10 @@ static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMN
void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode) { - if(mode >= COMPAT_MODE_IE9) + if(mode >= COMPAT_MODE_IE9) { + dispex_info_add_interface(info, IHTMLDOMNode2_tid, NULL); dispex_info_add_interface(info, IHTMLDOMNode3_tid, NULL); + }
EventTarget_init_dispex_info(info, mode); } diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index a92e3d8fbd6..fc28ac80f75 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3658,7 +3658,7 @@ sync_test("prototype props", function() { "DOCUMENT_POSITION_CONTAINED_BY", "DOCUMENT_POSITION_CONTAINS", "DOCUMENT_POSITION_DISCONNECTED", "DOCUMENT_POSITION_FOLLOWING", "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", "DOCUMENT_POSITION_PRECEDING", "DOCUMENT_TYPE_NODE", "ELEMENT_NODE", "ENTITY_NODE", "ENTITY_REFERENCE_NODE", "NOTATION_NODE", - "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "hasAttributes", "normalize", "ownerDocument", "removeNode", + "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "hasAttributes", "normalize", "removeNode", "replaceNode", "swapNode" ]); check(StorageEvent, [ "initStorageEvent", "key", "newValue", "oldValue", "storageArea", "url" ]);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
For some reason it's exposed higher up the chain in various other prototypes, but not the doctype.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmldoc.c | 4 +--- dlls/mshtml/htmlnode.c | 13 ++++++++----- dlls/mshtml/tests/documentmode.js | 27 ++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 70bc028f3a0..e8470c0d4cb 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -316,9 +316,6 @@ static const event_target_vtbl_t DocumentType_event_target_vtbl = {
static const tid_t DocumentType_iface_tids[] = { IDOMDocumentType_tid, - IHTMLDOMNode_tid, - IHTMLDOMNode2_tid, - IHTMLDOMNode3_tid, 0 };
@@ -328,6 +325,7 @@ dispex_static_data_t DocumentType_dispex = { .vtbl = &DocumentType_event_target_vtbl.dispex_vtbl, .disp_tid = DispDOMDocumentType_tid, .iface_tids = DocumentType_iface_tids, + .init_info = HTMLDOMNode_init_dispex_info, };
HRESULT create_doctype_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret) diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index ad22ef9dc48..3b5db6115f4 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -24,6 +24,7 @@ #include "winbase.h" #include "winuser.h" #include "ole2.h" +#include "mshtmdid.h"
#include "wine/debug.h"
@@ -1252,6 +1253,13 @@ static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMN
void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode) { + static const dispex_hook_t ie9_hooks[] = { + {DISPID_IHTMLDOMNODE_REMOVENODE, NULL}, + {DISPID_UNKNOWN} + }; + + dispex_info_add_interface(info, IHTMLDOMNode_tid, mode >= COMPAT_MODE_IE9 ? ie9_hooks : NULL); + if(mode >= COMPAT_MODE_IE9) { dispex_info_add_interface(info, IHTMLDOMNode2_tid, NULL); dispex_info_add_interface(info, IHTMLDOMNode3_tid, NULL); @@ -1295,15 +1303,10 @@ static const dispex_static_data_vtbl_t Node_dispex_vtbl = { .unlink = HTMLDOMNode_unlink };
-static const tid_t HTMLDOMNode_iface_tids[] = { - IHTMLDOMNode_tid, - 0 -}; dispex_static_data_t Node_dispex = { .id = PROT_Node, .vtbl = &Node_dispex_vtbl, .disp_tid = IHTMLDOMNode_tid, - .iface_tids = HTMLDOMNode_iface_tids, .init_info = HTMLDOMNode_init_dispex_info, };
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index fc28ac80f75..546393a6e4a 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -512,6 +512,7 @@ sync_test("elem_props", function() { test_exposed("readyState", v < 11); test_exposed("clientTop", true); test_exposed("title", true); + test_exposed("removeNode", true); test_exposed("querySelectorAll", v >= 8); test_exposed("textContent", v >= 9); test_exposed("prefix", v >= 9); @@ -586,6 +587,28 @@ sync_test("docfrag_props", function() { test_exposed("compareDocumentPosition", v >= 9); });
+sync_test("textnode_props", function() { + var node = document.createTextNode("testNode"); + + function test_exposed(prop, expect) { + if(expect) + ok(prop in node, prop + " not found in text node."); + else + ok(!(prop in node), prop + " found in text node."); + } + + var v = document.documentMode; + + test_exposed("childNodes", true); + test_exposed("nodeName", true); + test_exposed("nodeValue", true); + test_exposed("ownerDocument", true); + test_exposed("removeNode", true); + test_exposed("compareDocumentPosition", v >= 9); + test_exposed("isEqualNode", v >= 9); + test_exposed("prefix", v >= 9); +}); + sync_test("window_props", function() { function test_exposed(prop, expect, is_todo) { var ok_ = is_todo ? todo_wine.ok : ok; @@ -1180,6 +1203,7 @@ sync_test("doctype", function() { }
ok(doctype.name === "html", "doctype.name = " + doctype.name); + ok(!("removeNode" in doctype), "removeNode found in doctype."); });
async_test("iframe_doc_mode", function() { @@ -3631,6 +3655,7 @@ sync_test("prototype props", function() {
check(CSSStyleRule, [ "readOnly", "selectorText", "style" ]); check(CustomEvent, [ "detail", "initCustomEvent" ]); + check(DocumentType, [ "entities", "internalSubset", "name", "notations", "publicId", "systemId" ]); check(Event, [ "AT_TARGET", "BUBBLING_PHASE", "CAPTURING_PHASE", "bubbles", "cancelBubble", "cancelable", "currentTarget", "defaultPrevented", "eventPhase", "initEvent", "isTrusted", "preventDefault", "srcElement", @@ -3658,7 +3683,7 @@ sync_test("prototype props", function() { "DOCUMENT_POSITION_CONTAINED_BY", "DOCUMENT_POSITION_CONTAINS", "DOCUMENT_POSITION_DISCONNECTED", "DOCUMENT_POSITION_FOLLOWING", "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", "DOCUMENT_POSITION_PRECEDING", "DOCUMENT_TYPE_NODE", "ELEMENT_NODE", "ENTITY_NODE", "ENTITY_REFERENCE_NODE", "NOTATION_NODE", - "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "hasAttributes", "normalize", "removeNode", + "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "hasAttributes", "normalize", "replaceNode", "swapNode" ]); check(StorageEvent, [ "initStorageEvent", "key", "newValue", "oldValue", "storageArea", "url" ]);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlnode.c | 1 + dlls/mshtml/tests/documentmode.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index 3b5db6115f4..1b69928418a 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -1255,6 +1255,7 @@ void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode) { static const dispex_hook_t ie9_hooks[] = { {DISPID_IHTMLDOMNODE_REMOVENODE, NULL}, + {DISPID_IHTMLDOMNODE_REPLACENODE, NULL}, {DISPID_UNKNOWN} };
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 546393a6e4a..b23dd200d7d 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -513,6 +513,7 @@ sync_test("elem_props", function() { test_exposed("clientTop", true); test_exposed("title", true); test_exposed("removeNode", true); + test_exposed("replaceNode", true); test_exposed("querySelectorAll", v >= 8); test_exposed("textContent", v >= 9); test_exposed("prefix", v >= 9); @@ -604,6 +605,7 @@ sync_test("textnode_props", function() { test_exposed("nodeValue", true); test_exposed("ownerDocument", true); test_exposed("removeNode", true); + test_exposed("replaceNode", true); test_exposed("compareDocumentPosition", v >= 9); test_exposed("isEqualNode", v >= 9); test_exposed("prefix", v >= 9); @@ -1204,6 +1206,7 @@ sync_test("doctype", function() {
ok(doctype.name === "html", "doctype.name = " + doctype.name); ok(!("removeNode" in doctype), "removeNode found in doctype."); + ok(!("replaceNode" in doctype), "replaceNode found in doctype."); });
async_test("iframe_doc_mode", function() { @@ -3684,7 +3687,7 @@ sync_test("prototype props", function() { "DOCUMENT_POSITION_FOLLOWING", "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", "DOCUMENT_POSITION_PRECEDING", "DOCUMENT_TYPE_NODE", "ELEMENT_NODE", "ENTITY_NODE", "ENTITY_REFERENCE_NODE", "NOTATION_NODE", "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "hasAttributes", "normalize", - "replaceNode", "swapNode" + "swapNode" ]); check(StorageEvent, [ "initStorageEvent", "key", "newValue", "oldValue", "storageArea", "url" ]); check(UIEvent, [ "detail", "initUIEvent", "view" ], null, [ "deviceSessionId" ]);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlnode.c | 1 + dlls/mshtml/tests/documentmode.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index 1b69928418a..7df7b5bdc6a 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -1256,6 +1256,7 @@ void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode) static const dispex_hook_t ie9_hooks[] = { {DISPID_IHTMLDOMNODE_REMOVENODE, NULL}, {DISPID_IHTMLDOMNODE_REPLACENODE, NULL}, + {DISPID_IHTMLDOMNODE_SWAPNODE, NULL}, {DISPID_UNKNOWN} };
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index b23dd200d7d..9f62ca68f1d 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -514,6 +514,7 @@ sync_test("elem_props", function() { test_exposed("title", true); test_exposed("removeNode", true); test_exposed("replaceNode", true); + test_exposed("swapNode", true); test_exposed("querySelectorAll", v >= 8); test_exposed("textContent", v >= 9); test_exposed("prefix", v >= 9); @@ -606,6 +607,7 @@ sync_test("textnode_props", function() { test_exposed("ownerDocument", true); test_exposed("removeNode", true); test_exposed("replaceNode", true); + test_exposed("swapNode", true); test_exposed("compareDocumentPosition", v >= 9); test_exposed("isEqualNode", v >= 9); test_exposed("prefix", v >= 9); @@ -1207,6 +1209,7 @@ sync_test("doctype", function() { ok(doctype.name === "html", "doctype.name = " + doctype.name); ok(!("removeNode" in doctype), "removeNode found in doctype."); ok(!("replaceNode" in doctype), "replaceNode found in doctype."); + ok(!("swapNode" in doctype), "swapNode found in doctype."); });
async_test("iframe_doc_mode", function() { @@ -3686,8 +3689,7 @@ sync_test("prototype props", function() { "DOCUMENT_POSITION_CONTAINED_BY", "DOCUMENT_POSITION_CONTAINS", "DOCUMENT_POSITION_DISCONNECTED", "DOCUMENT_POSITION_FOLLOWING", "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", "DOCUMENT_POSITION_PRECEDING", "DOCUMENT_TYPE_NODE", "ELEMENT_NODE", "ENTITY_NODE", "ENTITY_REFERENCE_NODE", "NOTATION_NODE", - "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "hasAttributes", "normalize", - "swapNode" + "PROCESSING_INSTRUCTION_NODE", "TEXT_NODE", "hasAttributes", "normalize" ]); check(StorageEvent, [ "initStorageEvent", "key", "newValue", "oldValue", "storageArea", "url" ]); check(UIEvent, [ "detail", "initUIEvent", "view" ], null, [ "deviceSessionId" ]);
This merge request was approved by Jacek Caban.