Alexandre Julliard pushed to branch master at wine / wine
Commits: a76b5021 by Jacek Caban at 2024-07-24T20:14:45+02:00 mshtml: Use dispex_get_id in JSDispatchHost_LookupProperty.
- - - - - 0ca77e91 by Jacek Caban at 2024-07-24T20:14:47+02:00 mshtml: Introduce get_prop_desc call.
And use it in HTMLRectCollection instead of get_name.
- - - - - 7c2b85a6 by Jacek Caban at 2024-07-24T20:14:49+02:00 mshtml: Use host object script bindings for HTMLRectCollection.
- - - - - a0319211 by Jacek Caban at 2024-07-24T20:14:49+02:00 jscript: Make sure to use the right name for a prototype reference in find_prop_name_prot.
It may have a different name for case insensitive searches.
- - - - - 99189c31 by Jacek Caban at 2024-07-24T20:14:50+02:00 jscript: Fixup prototype references as part of lookup.
Instead of using fix_protref_prot.
- - - - - 262ad357 by Jacek Caban at 2024-07-24T20:14:51+02:00 jscript: Use a dedicated jsclass_t entry for host objects.
To avoid falling into JSCLASS_OBJECT special-case in disp_call_value_with_caller.
- - - - -
8 changed files:
- dlls/jscript/dispex.c - dlls/jscript/jscript.h - dlls/jscript/object.c - dlls/mshtml/dispex.c - dlls/mshtml/htmlelem.c - dlls/mshtml/mshtml_private.h - dlls/mshtml/tests/documentmode.js - dlls/mshtml/tests/dom.js
Changes:
===================================== dlls/jscript/dispex.c ===================================== @@ -318,13 +318,14 @@ static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_i return S_OK; }
-static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) +static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, + dispex_prop_t *prop, dispex_prop_t **ret) { const builtin_prop_t *builtin; - dispex_prop_t *prop; HRESULT hres;
- prop = lookup_dispex_prop(This, hash, name, case_insens); + if(!prop) + prop = lookup_dispex_prop(This, hash, name, case_insens); if(prop && prop->type != PROP_DELETED) { *ret = prop; return S_OK; @@ -367,43 +368,52 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, return hres; }
-static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) +static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, + dispex_prop_t *own_prop, dispex_prop_t **ret) { - dispex_prop_t *prop, *del=NULL; + dispex_prop_t *prot_prop = NULL; HRESULT hres;
- hres = find_prop_name(This, hash, name, case_insens, &prop); + hres = find_prop_name(This, hash, name, case_insens, own_prop, &own_prop); if(FAILED(hres)) return hres; - if(prop && prop->type==PROP_DELETED) { - del = prop; - } else if(prop) { - fix_protref_prop(This, prop); - *ret = prop; - return S_OK; + if(own_prop) { + if(own_prop->type == PROP_PROTREF) { + prot_prop = &This->prototype->props[own_prop->u.ref]; + }else if(own_prop->type != PROP_DELETED) { + *ret = own_prop; + return S_OK; + } }
if(This->prototype) { - hres = find_prop_name_prot(This->prototype, hash, name, case_insens, &prop); + hres = find_prop_name_prot(This->prototype, hash, name, case_insens, prot_prop, &prot_prop); if(FAILED(hres)) return hres; - if(prop && prop->type != PROP_DELETED) { - if(del) { - del->type = PROP_PROTREF; - del->u.ref = prop - This->prototype->props; - prop = del; + if(prot_prop && prot_prop->type != PROP_DELETED) { + if(own_prop && case_insens && wcscmp(prot_prop->name, own_prop->name)) { + hres = find_prop_name(This, prot_prop->hash, prot_prop->name, FALSE, NULL, &own_prop); + if(FAILED(hres)) + return hres; + if(own_prop && own_prop->type != PROP_DELETED) { + *ret = own_prop; + return S_OK; + } + } + if(own_prop) { + own_prop->type = PROP_PROTREF; + own_prop->u.ref = prot_prop - This->prototype->props; }else { - prop = alloc_protref(This, prop->name, prop - This->prototype->props); - if(!prop) + own_prop = alloc_protref(This, prot_prop->name, prot_prop - This->prototype->props); + if(!own_prop) return E_OUTOFMEMORY; } - - *ret = prop; - return S_OK; + }else if(own_prop) { + own_prop->type = PROP_DELETED; } }
- *ret = del; + *ret = own_prop; return S_OK; }
@@ -412,7 +422,7 @@ static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, DWORD create_ dispex_prop_t *prop; HRESULT hres;
- hres = find_prop_name_prot(This, string_hash(name), name, case_insens, &prop); + hres = find_prop_name_prot(This, string_hash(name), name, case_insens, NULL, &prop); if(SUCCEEDED(hres) && (!prop || prop->type == PROP_DELETED)) { TRACE("creating prop %s flags %lx\n", debugstr_w(name), create_flags);
@@ -742,7 +752,7 @@ static HRESULT fill_protrefs(jsdisp_t *This) return hres;
for(iter = This->prototype->props; iter < This->prototype->props+This->prototype->prop_cnt; iter++) { - hres = find_prop_name(This, iter->hash, iter->name, FALSE, &prop); + hres = find_prop_name(This, iter->hash, iter->name, FALSE, NULL, &prop); if(FAILED(hres)) return hres; if(!prop || prop->type==PROP_DELETED) { @@ -2230,7 +2240,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IWineJSDispatch *iface, BSTR if(grfdex & ~(fdexNameCaseSensitive|fdexNameCaseInsensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK)) FIXME("Unsupported grfdex %lx\n", grfdex);
- hres = find_prop_name(This, string_hash(bstrName), bstrName, grfdex & fdexNameCaseInsensitive, &prop); + hres = find_prop_name(This, string_hash(bstrName), bstrName, grfdex & fdexNameCaseInsensitive, NULL, &prop); if(FAILED(hres)) return hres; if(!prop) { @@ -2420,7 +2430,7 @@ HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const built dispex_prop_t *prop; HRESULT hres;
- hres = find_prop_name_prot(constr, string_hash(L"prototype"), L"prototype", FALSE, &prop); + hres = find_prop_name_prot(constr, string_hash(L"prototype"), L"prototype", FALSE, NULL, &prop); if(SUCCEEDED(hres) && prop && prop->type!=PROP_DELETED) { jsval_t val;
@@ -2461,7 +2471,7 @@ HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID * hres = ensure_prop_name(jsdisp, name, PROPF_ENUMERABLE | PROPF_CONFIGURABLE | PROPF_WRITABLE, flags & fdexNameCaseInsensitive, &prop); else - hres = find_prop_name_prot(jsdisp, string_hash(name), name, flags & fdexNameCaseInsensitive, &prop); + hres = find_prop_name_prot(jsdisp, string_hash(name), name, flags & fdexNameCaseInsensitive, NULL, &prop); if(FAILED(hres)) return hres;
@@ -2522,7 +2532,7 @@ HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned dispex_prop_t *prop; HRESULT hres;
- hres = find_prop_name_prot(disp, string_hash(name), name, FALSE, &prop); + hres = find_prop_name_prot(disp, string_hash(name), name, FALSE, NULL, &prop); if(FAILED(hres)) return hres;
@@ -2752,7 +2762,7 @@ HRESULT jsdisp_propput(jsdisp_t *obj, const WCHAR *name, DWORD flags, BOOL throw if(obj->extensible) hres = ensure_prop_name(obj, name, flags, FALSE, &prop); else - hres = find_prop_name(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name(obj, string_hash(name), name, FALSE, NULL, &prop); if(FAILED(hres)) return hres; if(!prop || (prop->type == PROP_DELETED && !obj->extensible)) @@ -2853,7 +2863,7 @@ HRESULT jsdisp_propget_name(jsdisp_t *obj, const WCHAR *name, jsval_t *val) dispex_prop_t *prop; HRESULT hres;
- hres = find_prop_name_prot(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name_prot(obj, string_hash(name), name, FALSE, NULL, &prop); if(FAILED(hres)) return hres;
@@ -2873,7 +2883,7 @@ HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r)
swprintf(name, ARRAY_SIZE(name), L"%d", idx);
- hres = find_prop_name_prot(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name_prot(obj, string_hash(name), name, FALSE, NULL, &prop); if(FAILED(hres)) return hres;
@@ -2930,7 +2940,7 @@ HRESULT jsdisp_delete_idx(jsdisp_t *obj, DWORD idx)
swprintf(buf, ARRAY_SIZE(buf), L"%d", idx);
- hres = find_prop_name(obj, string_hash(buf), buf, FALSE, &prop); + hres = find_prop_name(obj, string_hash(buf), buf, FALSE, NULL, &prop); if(FAILED(hres) || !prop) return hres;
@@ -3026,7 +3036,7 @@ HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL return E_OUTOFMEMORY; }
- hres = find_prop_name(jsdisp, string_hash(ptr), ptr, FALSE, &prop); + hres = find_prop_name(jsdisp, string_hash(ptr), ptr, FALSE, NULL, &prop); if(prop) { hres = delete_prop(prop, ret); }else { @@ -3073,7 +3083,7 @@ HRESULT jsdisp_get_own_property(jsdisp_t *obj, const WCHAR *name, BOOL flags_onl dispex_prop_t *prop; HRESULT hres;
- hres = find_prop_name(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name(obj, string_hash(name), name, FALSE, NULL, &prop); if(FAILED(hres)) return hres;
@@ -3117,7 +3127,7 @@ HRESULT jsdisp_define_property(jsdisp_t *obj, const WCHAR *name, property_desc_t dispex_prop_t *prop; HRESULT hres;
- hres = find_prop_name(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name(obj, string_hash(name), name, FALSE, NULL, &prop); if(FAILED(hres)) return hres;
@@ -3408,7 +3418,7 @@ static HRESULT HostObject_to_string(jsdisp_t *jsdisp, jsstr_t **ret) }
static const builtin_info_t HostObject_info = { - .class = JSCLASS_OBJECT, + .class = JSCLASS_HOST, .addref = HostObject_addref, .release = HostObject_release, .lookup_prop = HostObject_lookup_prop,
===================================== dlls/jscript/jscript.h ===================================== @@ -119,6 +119,7 @@ typedef enum { JSCLASS_MAP, JSCLASS_SET, JSCLASS_WEAKMAP, + JSCLASS_HOST, } jsclass_t;
jsdisp_t *iface_to_jsdisp(IDispatch*);
===================================== dlls/jscript/object.c ===================================== @@ -55,7 +55,8 @@ static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns L"[object Object]", L"[object Object]", L"[object Object]", - L"[object Object]" + L"[object Object]", + NULL };
TRACE("\n");
===================================== dlls/mshtml/dispex.c ===================================== @@ -2169,6 +2169,20 @@ HRESULT dispex_prop_name(DispatchEx *dispex, DISPID id, BSTR *ret) HRESULT hres;
if(is_custom_dispid(id)) { + if(dispex->info->desc->vtbl->get_prop_desc) { + struct property_info desc; + WCHAR buf[12]; + + hres = dispex->info->desc->vtbl->get_prop_desc(dispex, id, &desc); + if(FAILED(hres)) + return hres; + if(!desc.name) { + swprintf(buf, ARRAYSIZE(buf), L"%u", desc.index); + desc.name = buf; + } + *ret = SysAllocString(desc.name); + return *ret ? S_OK : E_OUTOFMEMORY; + } if(dispex->info->desc->vtbl->get_name) return dispex->info->desc->vtbl->get_name(dispex, id, ret); return DISP_E_MEMBERNOTFOUND; @@ -2299,33 +2313,67 @@ static HRESULT WINAPI JSDispatchHost_GetJSDispatch(IWineJSDispatchHost *iface, I return S_OK; }
+HRESULT dispex_index_prop_desc(DispatchEx *dispex, DISPID id, struct property_info *desc) +{ + desc->id = id; + desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; + if(dispex->info->desc->vtbl->next_dispid) + desc->flags |= PROPF_ENUMERABLE; + desc->name = NULL; + desc->index = id - MSHTML_DISPID_CUSTOM_MIN; + desc->func_iid = 0; + return S_OK; +} + +static HRESULT get_host_property_descriptor(DispatchEx *This, DISPID id, struct property_info *desc) +{ + HRESULT hres; + + desc->id = id; + + switch(get_dispid_type(id)) { + case DISPEXPROP_BUILTIN: { + func_info_t *func; + + hres = get_builtin_func(This->info, id, &func); + if(FAILED(hres)) + return hres; + desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; + desc->name = func->name; + if(func->func_disp_idx < 0) { + desc->flags |= PROPF_ENUMERABLE; + desc->func_iid = 0; + }else { + desc->func_iid = func->tid; + } + break; + } + case DISPEXPROP_DYNAMIC: + desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; + desc->name = This->dynamic_data->props[id - DISPID_DYNPROP_0].name; + desc->func_iid = 0; + break; + case DISPEXPROP_CUSTOM: + return This->info->desc->vtbl->get_prop_desc(This, id, desc); + } + + return S_OK; +} + static HRESULT WINAPI JSDispatchHost_LookupProperty(IWineJSDispatchHost *iface, const WCHAR *name, DWORD flags, struct property_info *desc) { DispatchEx *This = impl_from_IWineJSDispatchHost(iface); - func_info_t *func; DISPID id; HRESULT hres;
TRACE("%s (%p)->(%s)\n", This->info->desc->name, This, debugstr_w(name));
- hres = get_builtin_id(This, name, flags, &id); + hres = dispex_get_id(This, name, flags, &id); if(FAILED(hres)) return hres;
- hres = get_builtin_func(This->info, id, &func); - if(FAILED(hres)) - return hres; - desc->id = id; - desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; - if(func->func_disp_idx < 0) { - desc->flags |= PROPF_ENUMERABLE; - desc->func_iid = 0; - }else { - desc->func_iid = func->tid; - } - desc->name = func->name; - return S_OK; + return get_host_property_descriptor(This, id, desc); }
static HRESULT WINAPI JSDispatchHost_NextProperty(IWineJSDispatchHost *iface, DISPID id, struct property_info *desc)
===================================== dlls/mshtml/htmlelem.c ===================================== @@ -1073,21 +1073,6 @@ static HRESULT HTMLRectCollection_get_dispid(DispatchEx *dispex, const WCHAR *na return S_OK; }
-static HRESULT HTMLRectCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name) -{ - HTMLRectCollection *This = HTMLRectCollection_from_DispatchEx(dispex); - DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; - UINT32 len = 0; - WCHAR buf[11]; - - nsIDOMClientRectList_GetLength(This->rect_list, &len); - if(idx >= len) - return DISP_E_MEMBERNOTFOUND; - - len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); - return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY; -} - static HRESULT HTMLRectCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -1132,7 +1117,7 @@ static const dispex_static_data_vtbl_t HTMLRectCollection_dispex_vtbl = { .traverse = HTMLRectCollection_traverse, .unlink = HTMLRectCollection_unlink, .get_dispid = HTMLRectCollection_get_dispid, - .get_name = HTMLRectCollection_get_name, + .get_prop_desc = dispex_index_prop_desc, .invoke = HTMLRectCollection_invoke, }; static const tid_t HTMLRectCollection_iface_tids[] = { @@ -3053,7 +3038,7 @@ static HRESULT WINAPI HTMLElement2_getClientRects(IHTMLElement2 *iface, IHTMLRec
rects->IHTMLRectCollection_iface.lpVtbl = &HTMLRectCollectionVtbl; rects->rect_list = rect_list; - init_dispatch(&rects->dispex, &HTMLRectCollection_dispex, NULL, + init_dispatch(&rects->dispex, &HTMLRectCollection_dispex, This->node.doc->script_global, dispex_compat_mode(&This->node.event_target.dispex));
*pRectCol = &rects->IHTMLRectCollection_iface;
===================================== dlls/mshtml/mshtml_private.h ===================================== @@ -392,6 +392,7 @@ typedef struct { HRESULT (*invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); HRESULT (*delete)(DispatchEx*,DISPID); HRESULT (*next_dispid)(DispatchEx*,DISPID,DISPID*); + HRESULT (*get_prop_desc)(DispatchEx*,DISPID,struct property_info*);
/* Similar to invoke, but allows overriding all dispids */ HRESULT (*disp_invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); @@ -515,6 +516,7 @@ HRESULT dispex_prop_put(DispatchEx *dispex, DISPID id, LCID lcid, VARIANT *v, EX 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_prop_name(DispatchEx *dispex, DISPID id, BSTR *ret); +HRESULT dispex_index_prop_desc(DispatchEx*,DISPID,struct property_info*);
typedef enum { DISPEXPROP_CUSTOM,
===================================== dlls/mshtml/tests/documentmode.js ===================================== @@ -294,7 +294,7 @@ sync_test("builtin_toString", function() { if(false /* todo_wine */) test("attributes", e.attributes, "NamedNodeMap"); test("childNodes", document.body.childNodes, "NodeList", null, true); if(clientRects) test("clientRect", clientRects[0], "ClientRect", null, true); - if(clientRects) test("clientRects", clientRects, "ClientRectList", null, true); + if(clientRects) test("clientRects", clientRects, "ClientRectList"); if(currentStyle) test("currentStyle", currentStyle, "MSCurrentStyleCSSProperties", null, true); if(v >= 11 /* todo_wine */) test("document", document, v < 11 ? "Document" : "HTMLDocument", null, true); test("elements", document.getElementsByTagName("body"), "HTMLCollection", null, true);
===================================== dlls/mshtml/tests/dom.js ===================================== @@ -331,6 +331,18 @@ sync_test("rects", function() { ok(rects.length === 1, "rect.length = " + rects.length); ok(rects[0].top === rect.top, "rects[0].top = " + rects[0].top + " rect.top = " + rect.top); ok(rects[0].bottom === rect.bottom, "rects[0].bottom = " + rects[0].bottom + " rect.bottom = " + rect.bottom); + + ok("" + rects[0] === "[object ClientRect]", "rects[0] = " + rects[0]); + ok(rects.hasOwnProperty("0"), 'rects.hasOwnProperty("0") = ' + rects.hasOwnProperty("0")); + todo_wine. + ok(rects.hasOwnProperty("1"), 'rects.hasOwnProperty("1") = ' + rects.hasOwnProperty("1")); + var desc = Object.getOwnPropertyDescriptor(rects, "0"); + ok(desc.writable === true, "writable = " + desc.writable); + todo_wine. + ok(desc.enumerable === true, "enumerable = " + desc.enumerable); + ok(desc.configurable === true, "configurable = " + desc.configurable); + ok("" + desc.value === "[object ClientRect]", "desc.value = " + desc.value); + ok(rect.height === rect.bottom - rect.top, "rect.height = " + rect.height + " rect.bottom = " + rect.bottom + " rect.top = " + rect.top); ok(rect.width === rect.right - rect.left, "rect.width = " + rect.width + " rect.right = " + rect.right + " rect.left = " + rect.left);
View it on GitLab: https://gitlab.winehq.org/wine/wine/-/compare/1d3515481436c867b5321106345022...