Commit 8de5187d authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

mshtml: Do not enumerate internal dynamic props.

Props allocated with dispex_get_dprop_ref or dispex_get_dynid are purely internal to our implementation and must not be enumerated. Note that in case of window, the props themselves become enumerable, but the dynamic props must still be hidden, since it's the custom prop that refers to it that must be enumerated (i.e. the DISPID must match with the custom prop, not the underlying dynamic prop backing it, which would violate the former DISPID obtained for the respective name). Signed-off-by: 's avatarGabriel Ivăncescu <gabrielopcode@gmail.com>
parent 03c4a231
......@@ -85,6 +85,7 @@ typedef struct {
} dynamic_prop_t;
#define DYNPROP_DELETED 0x01
#define DYNPROP_HIDDEN 0x02
typedef struct {
DispatchEx dispex;
......@@ -702,6 +703,8 @@ HRESULT dispex_get_dprop_ref(DispatchEx *This, const WCHAR *name, BOOL alloc, VA
if(FAILED(hres))
return hres;
if(alloc)
prop->flags |= DYNPROP_HIDDEN;
*ret = &prop->var;
return S_OK;
}
......@@ -715,6 +718,7 @@ HRESULT dispex_get_dynid(DispatchEx *This, const WCHAR *name, DISPID *id)
if(FAILED(hres))
return hres;
prop->flags |= DYNPROP_HIDDEN;
*id = DISPID_DYNPROP_0 + (prop - This->dynamic_data->props);
return S_OK;
}
......@@ -1860,7 +1864,8 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BS
static HRESULT next_dynamic_id(DispatchEx *dispex, DWORD idx, DISPID *ret_id)
{
while(idx < dispex->dynamic_data->prop_cnt && dispex->dynamic_data->props[idx].flags & DYNPROP_DELETED)
while(idx < dispex->dynamic_data->prop_cnt &&
(dispex->dynamic_data->props[idx].flags & (DYNPROP_DELETED | DYNPROP_HIDDEN)))
idx++;
if(idx == dispex->dynamic_data->prop_cnt) {
......
......@@ -3874,6 +3874,20 @@ static HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD
return hres;
}
static HRESULT HTMLWindow_next_dispid(DispatchEx *dispex, DISPID id, DISPID *pid)
{
DWORD idx = (id == DISPID_STARTENUM) ? 0 : id - MSHTML_DISPID_CUSTOM_MIN + 1;
HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
while(idx < This->global_prop_cnt && This->global_props[idx].type != GLOBAL_DISPEXVAR)
idx++;
if(idx >= This->global_prop_cnt)
return S_FALSE;
*pid = idx + MSHTML_DISPID_CUSTOM_MIN;
return S_OK;
}
static compat_mode_t HTMLWindow_get_compat_mode(DispatchEx *dispex)
{
HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
......@@ -3971,7 +3985,7 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = {
HTMLWindow_get_name,
HTMLWindow_invoke,
NULL,
NULL,
HTMLWindow_next_dispid,
HTMLWindow_get_compat_mode,
NULL
},
......
......@@ -635,6 +635,8 @@ sync_test("JS objs", function() {
});
sync_test("for..in", function() {
var v = document.documentMode, found = 0, r;
function ctor() {}
ctor.prototype.test2 = true;
......@@ -642,7 +644,7 @@ sync_test("for..in", function() {
obj.test1 = true;
i = 0;
for(var r in obj) {
for(r in obj) {
ctor.prototype.test3 = true;
arr[r] = true;
i++;
......@@ -652,10 +654,22 @@ sync_test("for..in", function() {
ok(arr["test1"] === true, "arr[test1] !== true");
ok(arr["test2"] === true, "arr[test2] !== true");
ok(arr["test3"] === true, "arr[test3] !== true");
for(r in document)
if(r === "ondragstart")
found++;
ok(found === 1, "ondragstart enumerated " + found + " times in document");
document.ondragstart = "";
found = 0;
for(r in document)
if(r === "ondragstart")
found++;
ok(found === 1, "ondragstart enumerated " + found + " times in document after set to empty string");
});
sync_test("elem_by_id", function() {
document.body.innerHTML = '<form id="testid" name="testname"></form>';
var found;
var id_elem = document.getElementById("testid");
ok(id_elem.tagName === "FORM", "id_elem.tagName = " + id_elem.tagName);
......@@ -665,6 +679,32 @@ sync_test("elem_by_id", function() {
ok(id_elem === name_elem, "id_elem != id_elem");
else
ok(name_elem === null, "name_elem != null");
id_elem = window.testid;
ok(id_elem.tagName === "FORM", "window.testid = " + id_elem);
name_elem = document.testname;
ok(name_elem.tagName === "FORM", "document.testname = " + name_elem);
for(id_elem in window)
ok(id_elem !== "testid" && id_elem != "testname", id_elem + " was enumerated in window");
window.testid = 137;
found = false;
for(id_elem in window) {
ok(id_elem != "testname", id_elem + " was enumerated in window after set to 137");
if(id_elem === "testid")
found = true;
}
ok(found, "testid was not enumerated in window after set to 137");
found = false;
for(id_elem in document) {
ok(id_elem !== "testid", "testid was enumerated in document");
if(id_elem === "testname")
found = true;
}
todo_wine.
ok(found, "testname was not enumerated in document");
});
sync_test("doc_mode", function() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment