From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 18 +++++++++++------- dlls/jscript/tests/api.js | 1 + dlls/mshtml/tests/es5.js | 5 +++++ 3 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 0e8650f12e5..3b1b4f83267 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -653,8 +653,8 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t This->prototype->props+prop->u.ref, flags, argc, argv, r, caller); case PROP_JSVAL: { if(!is_object_instance(prop->u.val)) { - FIXME("invoke %s\n", debugstr_jsval(prop->u.val)); - return E_FAIL; + FIXME("value %s is not a function\n", debugstr_jsval(prop->u.val)); + return JS_E_FUNCTION_EXPECTED; }
TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val)); @@ -672,12 +672,16 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t return hres;
if(is_object_instance(val)) { - hres = disp_call_value_with_caller(This->ctx, get_object(val), - jsval_disp(jsthis ? jsthis : to_disp(This)), - flags, argc, argv, r, caller); + jsdisp_t *jsfunc = to_jsdisp(get_object(val)); + if(!jsfunc || is_class(jsfunc, JSCLASS_FUNCTION)) + hres = disp_call_value_with_caller(This->ctx, get_object(val), + jsval_disp(jsthis ? jsthis : to_disp(This)), + flags, argc, argv, r, caller); + else + hres = JS_E_INVALID_PROPERTY; }else { - FIXME("invoke %s\n", debugstr_jsval(val)); - hres = E_NOTIMPL; + WARN("value %s is not a function\n", debugstr_jsval(val)); + hres = JS_E_FUNCTION_EXPECTED; }
jsval_release(val); diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index aea412347b9..a82e4756c24 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -2744,6 +2744,7 @@ testException(function() {null.toString();}, "E_OBJECT_EXPECTED"); testException(function() {RegExp.prototype.toString.call(new Object());}, "E_REGEXP_EXPECTED"); testException(function() {/a/.lastIndex();}, "E_NOT_FUNC"); testException(function() {"a".length();}, "E_NOT_FUNC"); +testException(function() {var o = {f: {}}; o.f();}, "E_NOT_FUNC"); testException(function() {((function() { var f = Number.prototype.toString; return (function() { return f(); }); })())();}, "E_NOT_NUM"); testException(function() {((function() { var f = Object.prototype.hasOwnProperty; return (function() { return f("f"); }); })())();}, "E_OBJECT_EXPECTED");
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index f2e025ec864..1225a744de6 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -838,6 +838,11 @@ sync_test("defineProperty", function() { expect_exception(function() { Object.defineProperty(obj, "funcprop", nullDisp); }, JS_E_OBJECT_EXPECTED); + expect_exception(function() { + var o = {}; + Object.defineProperty(o, "f", { get: function() { return 0; } }); + o.f(); + }, JS_E_FUNCTION_EXPECTED); });
sync_test("defineProperties", function() {
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/dispex.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index fd7d571aebd..0be5ba002a7 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1859,7 +1859,8 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IWineJSDispatchHost *iface, REFII
/* Native ignores all cNames > 1, and doesn't even fill them */ if(cNames) - hres = IWineJSDispatchHost_GetDispID(&This->IWineJSDispatchHost_iface, rgszNames[0], 0, rgDispId); + hres = IWineJSDispatchHost_GetDispID(&This->IWineJSDispatchHost_iface, rgszNames[0], + fdexNameCaseInsensitive, rgDispId);
return hres; }
From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 3b1b4f83267..883fd6fc880 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -290,10 +290,8 @@ static HRESULT update_external_prop(jsdisp_t *obj, dispex_prop_t *prop, const st return S_OK; }
-static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) +static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_insens, dispex_prop_t *prop, dispex_prop_t **ret) { - dispex_prop_t *prop; - if(This->builtin_info->lookup_prop) { struct property_info desc; HRESULT hres; @@ -304,17 +302,25 @@ static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_i if(FAILED(hres)) return hres;
- prop = alloc_prop(This, desc.name ? desc.name : name, PROP_DELETED, 0); - if(!prop) + if(prop && desc.name && wcscmp(prop->name, desc.name)) { + prop = lookup_dispex_prop(This, string_hash(desc.name), desc.name, case_insens); + if(prop && prop->type != PROP_EXTERN && prop->type != PROP_DELETED && prop->type != PROP_PROTREF) { + *ret = prop; + return S_OK; + } + } + if(!prop && !(prop = alloc_prop(This, desc.name ? desc.name : name, PROP_DELETED, 0))) return E_OUTOFMEMORY;
hres = update_external_prop(This, prop, &desc); *ret = prop; return hres; + }else if(prop && prop->type == PROP_EXTERN) { + prop->type = PROP_DELETED; } }
- *ret = NULL; + *ret = prop; return S_OK; }
@@ -326,7 +332,7 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name,
if(!prop) prop = lookup_dispex_prop(This, hash, name, case_insens); - if(prop && prop->type != PROP_DELETED) { + if(prop && prop->type != PROP_DELETED && prop->type != PROP_EXTERN) { *ret = prop; return S_OK; } @@ -362,10 +368,7 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, return S_OK; }
- hres = find_external_prop(This, name, case_insens, ret); - if(hres == S_OK && !*ret) - *ret = prop; - return hres; + return find_external_prop(This, name, case_insens, prop, ret); }
static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens,
From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 37 +++++++++++++++++++------ dlls/jscript/jscript.h | 1 + dlls/jscript/jsdisp.idl | 1 + dlls/mshtml/dispex.c | 59 +++++++++++++++++++++++++--------------- dlls/mshtml/htmlwindow.c | 8 ++++++ 5 files changed, 76 insertions(+), 30 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 883fd6fc880..da9594a5e6e 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2209,7 +2209,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IWineJSDispatch *iface, DISPID id, LCI return leave_script(This->ctx, hres); }
-static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) +static HRESULT delete_prop(jsdisp_t *obj, dispex_prop_t *prop, BOOL *ret) { if(prop->type == PROP_PROTREF || prop->type == PROP_DELETED) { *ret = TRUE; @@ -2223,13 +2223,26 @@ static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret)
*ret = TRUE;
- if(prop->type == PROP_JSVAL) + switch(prop->type) { + case PROP_JSVAL: jsval_release(prop->u.val); - if(prop->type == PROP_ACCESSOR) { + break; + case PROP_ACCESSOR: if(prop->u.accessor.getter) jsdisp_release(prop->u.accessor.getter); if(prop->u.accessor.setter) jsdisp_release(prop->u.accessor.setter); + break; + case PROP_EXTERN: + if(obj->builtin_info->prop_delete) { + HRESULT hres; + hres = obj->builtin_info->prop_delete(obj, prop->u.id); + if(FAILED(hres)) + return hres; + } + break; + default: + break; } prop->type = PROP_DELETED; return S_OK; @@ -2255,7 +2268,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IWineJSDispatch *iface, BSTR return S_OK; }
- return delete_prop(prop, &b); + return delete_prop(This, prop, &b); }
static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IWineJSDispatch *iface, DISPID id) @@ -2272,7 +2285,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IWineJSDispatch *iface, DI return DISP_E_MEMBERNOTFOUND; }
- return delete_prop(prop, &b); + return delete_prop(This, prop, &b); }
static HRESULT WINAPI DispatchEx_GetMemberProperties(IWineJSDispatch *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) @@ -2951,7 +2964,7 @@ HRESULT jsdisp_delete_idx(jsdisp_t *obj, DWORD idx) if(FAILED(hres) || !prop) return hres;
- hres = delete_prop(prop, &b); + hres = delete_prop(obj, prop, &b); if(FAILED(hres)) return hres; return b ? S_OK : JS_E_INVALID_ACTION; @@ -2969,7 +2982,7 @@ HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret)
prop = get_prop(jsdisp, id); if(prop) - hres = delete_prop(prop, ret); + hres = delete_prop(jsdisp, prop, ret); else hres = DISP_E_MEMBERNOTFOUND;
@@ -3045,7 +3058,7 @@ HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL
hres = find_prop_name(jsdisp, string_hash(ptr), ptr, FALSE, NULL, &prop); if(prop) { - hres = delete_prop(prop, ret); + hres = delete_prop(jsdisp, prop, ret); }else { *ret = TRUE; hres = S_OK; @@ -3409,6 +3422,13 @@ static HRESULT HostObject_next_prop(jsdisp_t *jsdisp, unsigned id, struct proper return IWineJSDispatchHost_NextProperty(This->host_iface, id, desc); }
+static HRESULT HostObject_prop_delete(jsdisp_t *jsdisp, unsigned id) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + + return IWineJSDispatchHost_DeleteProperty(This->host_iface, id); +} + static HRESULT HostObject_to_string(jsdisp_t *jsdisp, jsstr_t **ret) { HostObject *This = HostObject_from_jsdisp(jsdisp); @@ -3432,6 +3452,7 @@ static const builtin_info_t HostObject_info = { .prop_get = HostObject_prop_get, .prop_put = HostObject_prop_put, .next_prop = HostObject_next_prop, + .prop_delete = HostObject_prop_delete, .to_string = HostObject_to_string, };
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 456f00171ed..3642bf171c8 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -190,6 +190,7 @@ typedef struct { HRESULT (*next_prop)(jsdisp_t*,unsigned,struct property_info*); HRESULT (*prop_get)(jsdisp_t*,unsigned,jsval_t*); HRESULT (*prop_put)(jsdisp_t*,unsigned,jsval_t); + HRESULT (*prop_delete)(jsdisp_t*,unsigned); HRESULT (*to_string)(jsdisp_t*,jsstr_t**); HRESULT (*gc_traverse)(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*); } builtin_info_t; diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index f01ea95ce48..4030a0110a3 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -59,6 +59,7 @@ interface IWineJSDispatchHost : IDispatchEx HRESULT NextProperty(DISPID id, struct property_info *desc); HRESULT GetProperty(DISPID id, LCID lcid, VARIANT *r, EXCEPINFO *ei, IServiceProvider *caller); HRESULT SetProperty(DISPID id, LCID lcid, VARIANT *v, EXCEPINFO *ei, IServiceProvider *caller); + HRESULT DeleteProperty(DISPID id); HRESULT CallFunction(DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); HRESULT ToString(BSTR *str); } diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 0be5ba002a7..93dfe95c760 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2097,6 +2097,32 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IWineJSDispatchHost *iface, DISPID id, } }
+static HRESULT dispex_prop_delete(DispatchEx *dispex, DISPID id) +{ + if(is_custom_dispid(id) && dispex->info->desc->vtbl->delete) + return dispex->info->desc->vtbl->delete(dispex, id); + + if(dispex_compat_mode(dispex) < COMPAT_MODE_IE8) { + /* Not implemented by IE */ + return E_NOTIMPL; + } + + if(is_dynamic_dispid(id)) { + DWORD idx = id - DISPID_DYNPROP_0; + dynamic_prop_t *prop; + + if(!get_dynamic_data(dispex) || idx >= dispex->dynamic_data->prop_cnt) + return S_OK; + + prop = dispex->dynamic_data->props + idx; + VariantClear(&prop->var); + prop->flags |= DYNPROP_DELETED; + return S_OK; + } + + return S_OK; +} + static HRESULT WINAPI DispatchEx_DeleteMemberByName(IWineJSDispatchHost *iface, BSTR name, DWORD grfdex) { DispatchEx *This = impl_from_IWineJSDispatchHost(iface); @@ -2133,28 +2159,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IWineJSDispatchHost *iface return E_OUTOFMEMORY; if(This->jsdisp) return IWineJSDispatch_DeleteMemberByDispID(This->jsdisp, id); - if(is_custom_dispid(id) && This->info->desc->vtbl->delete) - return This->info->desc->vtbl->delete(This, id); - - if(dispex_compat_mode(This) < COMPAT_MODE_IE8) { - /* Not implemented by IE */ - return E_NOTIMPL; - } - - if(is_dynamic_dispid(id)) { - DWORD idx = id - DISPID_DYNPROP_0; - dynamic_prop_t *prop; - - if(!get_dynamic_data(This) || idx >= This->dynamic_data->prop_cnt) - return S_OK; - - prop = This->dynamic_data->props + idx; - VariantClear(&prop->var); - prop->flags |= DYNPROP_DELETED; - return S_OK; - } - - return S_OK; + return dispex_prop_delete(This, id); }
static HRESULT WINAPI DispatchEx_GetMemberProperties(IWineJSDispatchHost *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) @@ -2427,6 +2432,15 @@ static HRESULT WINAPI JSDispatchHost_SetProperty(IWineJSDispatchHost *iface, DIS return dispex_prop_put(This, id, lcid, v, ei, caller); }
+static HRESULT WINAPI JSDispatchHost_DeleteProperty(IWineJSDispatchHost *iface, DISPID id) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + + TRACE("%s (%p)->(%lx)\n", This->info->desc->name, This, id); + + return dispex_prop_delete(This, id); +} + static HRESULT WINAPI JSDispatchHost_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { @@ -2474,6 +2488,7 @@ static IWineJSDispatchHostVtbl JSDispatchHostVtbl = { JSDispatchHost_NextProperty, JSDispatchHost_GetProperty, JSDispatchHost_SetProperty, + JSDispatchHost_DeleteProperty, JSDispatchHost_CallFunction, JSDispatchHost_ToString, }; diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index b936a9a844a..41bef9c7fcf 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3485,6 +3485,13 @@ static HRESULT WINAPI WindowDispEx_SetProperty(IWineJSDispatchHost *iface, DISPI id, lcid, v, ei, caller); }
+static HRESULT WINAPI WindowDispEx_DeleteProperty(IWineJSDispatchHost *iface, DISPID id) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_DeleteProperty(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id); +} + static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { @@ -3522,6 +3529,7 @@ static const IWineJSDispatchHostVtbl WindowDispExVtbl = { WindowDispEx_NextProperty, WindowDispEx_GetProperty, WindowDispEx_SetProperty, + WindowDispEx_DeleteProperty, WindowDispEx_CallFunction, WindowDispEx_ToString, };
From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 27 ++++++++++++++++++++++++--- dlls/jscript/jscript.h | 1 + dlls/jscript/jsdisp.idl | 3 +++ dlls/mshtml/dispex.c | 28 ++++++++++++++++++++++++---- dlls/mshtml/htmlwindow.c | 8 ++++++++ 5 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index da9594a5e6e..ec256c8643c 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -3303,14 +3303,26 @@ HRESULT jsdisp_change_prototype(jsdisp_t *obj, jsdisp_t *proto) return S_OK; }
+static void set_prop_flags(jsdisp_t *obj, dispex_prop_t *prop, UINT32 flags) +{ + if(prop->type == PROP_EXTERN && obj->builtin_info->prop_config) { + HRESULT hres = obj->builtin_info->prop_config(obj, prop->u.id, flags); + if(hres != S_OK) + return; + } + prop->flags = (prop->flags & ~PROPF_PUBLIC_MASK) | flags; +} + void jsdisp_freeze(jsdisp_t *obj, BOOL seal) { unsigned int i;
+ fill_props(obj); for(i = 0; i < obj->prop_cnt; i++) { + unsigned int mask = PROPF_CONFIGURABLE; if(!seal && obj->props[i].type == PROP_JSVAL) - obj->props[i].flags &= ~PROPF_WRITABLE; - obj->props[i].flags &= ~PROPF_CONFIGURABLE; + mask |= PROPF_WRITABLE; + set_prop_flags(obj, &obj->props[i], obj->props[i].flags & PROPF_PUBLIC_MASK & ~mask); }
obj->extensible = FALSE; @@ -3322,9 +3334,10 @@ BOOL jsdisp_is_frozen(jsdisp_t *obj, BOOL sealed)
if(obj->extensible) return FALSE; + fill_props(obj);
for(i = 0; i < obj->prop_cnt; i++) { - if(obj->props[i].type == PROP_JSVAL) { + if(obj->props[i].type == PROP_JSVAL || obj->props[i].type == PROP_EXTERN) { if(!sealed && (obj->props[i].flags & PROPF_WRITABLE)) return FALSE; }else if(obj->props[i].type != PROP_ACCESSOR) @@ -3429,6 +3442,13 @@ static HRESULT HostObject_prop_delete(jsdisp_t *jsdisp, unsigned id) return IWineJSDispatchHost_DeleteProperty(This->host_iface, id); }
+static HRESULT HostObject_prop_config(jsdisp_t *jsdisp, unsigned id, unsigned flags) +{ + HostObject *This = HostObject_from_jsdisp(jsdisp); + + return IWineJSDispatchHost_ConfigureProperty(This->host_iface, id, flags); +} + static HRESULT HostObject_to_string(jsdisp_t *jsdisp, jsstr_t **ret) { HostObject *This = HostObject_from_jsdisp(jsdisp); @@ -3453,6 +3473,7 @@ static const builtin_info_t HostObject_info = { .prop_put = HostObject_prop_put, .next_prop = HostObject_next_prop, .prop_delete = HostObject_prop_delete, + .prop_config = HostObject_prop_config, .to_string = HostObject_to_string, };
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 3642bf171c8..48738ca82f4 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -191,6 +191,7 @@ typedef struct { HRESULT (*prop_get)(jsdisp_t*,unsigned,jsval_t*); HRESULT (*prop_put)(jsdisp_t*,unsigned,jsval_t); HRESULT (*prop_delete)(jsdisp_t*,unsigned); + HRESULT (*prop_config)(jsdisp_t*,unsigned,unsigned); HRESULT (*to_string)(jsdisp_t*,jsstr_t**); HRESULT (*gc_traverse)(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*); } builtin_info_t; diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index 4030a0110a3..a2b8762b2c0 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -34,6 +34,8 @@ const unsigned int PROPF_ENUMERABLE = 0x0400; const unsigned int PROPF_WRITABLE = 0x0800; const unsigned int PROPF_CONFIGURABLE = 0x1000;
+const unsigned int PROPF_PUBLIC_MASK = PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE; + interface IWineJSDispatchHost;
[ @@ -60,6 +62,7 @@ interface IWineJSDispatchHost : IDispatchEx HRESULT GetProperty(DISPID id, LCID lcid, VARIANT *r, EXCEPINFO *ei, IServiceProvider *caller); HRESULT SetProperty(DISPID id, LCID lcid, VARIANT *v, EXCEPINFO *ei, IServiceProvider *caller); HRESULT DeleteProperty(DISPID id); + HRESULT ConfigureProperty(DISPID id, UINT32 flags); HRESULT CallFunction(DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); HRESULT ToString(BSTR *str); } diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 93dfe95c760..2e4cf244a87 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -680,7 +680,7 @@ static HRESULT alloc_dynamic_prop(DispatchEx *This, const WCHAR *name, dynamic_p return E_OUTOFMEMORY;
VariantInit(&prop->var); - prop->flags = 0; + prop->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; data->prop_cnt++; *ret = prop; return S_OK; @@ -2354,11 +2354,13 @@ static HRESULT get_host_property_descriptor(DispatchEx *This, DISPID id, struct } break; } - case DISPEXPROP_DYNAMIC: - desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; - desc->name = This->dynamic_data->props[id - DISPID_DYNPROP_0].name; + case DISPEXPROP_DYNAMIC: { + dynamic_prop_t *prop = &This->dynamic_data->props[id - DISPID_DYNPROP_0]; + desc->flags = prop->flags & PROPF_PUBLIC_MASK; + desc->name = prop->name; desc->func_iid = 0; break; + } case DISPEXPROP_CUSTOM: return This->info->desc->vtbl->get_prop_desc(This, id, desc); } @@ -2441,6 +2443,23 @@ static HRESULT WINAPI JSDispatchHost_DeleteProperty(IWineJSDispatchHost *iface, return dispex_prop_delete(This, id); }
+static HRESULT WINAPI JSDispatchHost_ConfigureProperty(IWineJSDispatchHost *iface, DISPID id, UINT32 flags) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + + TRACE("%s (%p)->(%lx %x)\n", This->info->desc->name, This, id, flags); + + if(is_dynamic_dispid(id)) { + DWORD idx = id - DISPID_DYNPROP_0; + if(This->dynamic_data && idx < This->dynamic_data->prop_cnt) { + dynamic_prop_t *prop = &This->dynamic_data->props[idx]; + prop->flags = (prop->flags & ~PROPF_PUBLIC_MASK) | flags; + } + } + + return S_OK; +} + static HRESULT WINAPI JSDispatchHost_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { @@ -2489,6 +2508,7 @@ static IWineJSDispatchHostVtbl JSDispatchHostVtbl = { JSDispatchHost_GetProperty, JSDispatchHost_SetProperty, JSDispatchHost_DeleteProperty, + JSDispatchHost_ConfigureProperty, JSDispatchHost_CallFunction, JSDispatchHost_ToString, }; diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 41bef9c7fcf..c40d3fe889b 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3492,6 +3492,13 @@ static HRESULT WINAPI WindowDispEx_DeleteProperty(IWineJSDispatchHost *iface, DI return IWineJSDispatchHost_DeleteProperty(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id); }
+static HRESULT WINAPI WindowDispEx_ConfigureProperty(IWineJSDispatchHost *iface, DISPID id, UINT32 flags) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_ConfigureProperty(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id, flags); +} + static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { @@ -3530,6 +3537,7 @@ static const IWineJSDispatchHostVtbl WindowDispExVtbl = { WindowDispEx_GetProperty, WindowDispEx_SetProperty, WindowDispEx_DeleteProperty, + WindowDispEx_ConfigureProperty, WindowDispEx_CallFunction, WindowDispEx_ToString, };
From: Jacek Caban jacek@codeweavers.com
--- dlls/jscript/dispex.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index ec256c8643c..3859f4c9a30 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -429,16 +429,27 @@ static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, DWORD create_ if(SUCCEEDED(hres) && (!prop || prop->type == PROP_DELETED)) { TRACE("creating prop %s flags %lx\n", debugstr_w(name), create_flags);
- if(prop) { - prop->type = PROP_JSVAL; - prop->flags = create_flags; - prop->u.val = jsval_undefined(); - }else { - prop = alloc_prop(This, name, PROP_JSVAL, create_flags); + if(!prop) { + prop = alloc_prop(This, name, PROP_DELETED, 0); if(!prop) return E_OUTOFMEMORY; }
+ if(This->builtin_info->lookup_prop) { + struct property_info desc; + hres = This->builtin_info->lookup_prop(This, name, fdexNameEnsure, &desc); + if(hres == S_OK) { + hres = update_external_prop(This, prop, &desc); + if(FAILED(hres)) + return hres; + *ret = prop; + return S_OK; + } + } + + hres = S_OK; + prop->type = PROP_JSVAL; + prop->flags = create_flags; prop->u.val = jsval_undefined(); }
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/htmlform.c | 27 +-------------------------- dlls/mshtml/tests/documentmode.js | 2 +- 2 files changed, 2 insertions(+), 27 deletions(-)
diff --git a/dlls/mshtml/htmlform.c b/dlls/mshtml/htmlform.c index b9ed7eabe51..a6a4bc0bce9 100644 --- a/dlls/mshtml/htmlform.c +++ b/dlls/mshtml/htmlform.c @@ -846,31 +846,6 @@ static HRESULT HTMLFormElement_get_dispid(DispatchEx *dispex, const WCHAR *name, return hres; }
-static HRESULT HTMLFormElement_dispex_get_name(DispatchEx *dispex, DISPID id, BSTR *name) -{ - HTMLFormElement *This = impl_from_DispatchEx(dispex); - DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; - nsIDOMHTMLCollection *elements; - nsresult nsres; - UINT32 len = 0; - WCHAR buf[11]; - - nsres = nsIDOMHTMLFormElement_GetElements(This->nsform, &elements); - if(NS_FAILED(nsres)) - return map_nsresult(nsres); - - nsres = nsIDOMHTMLCollection_GetLength(elements, &len); - nsIDOMHTMLCollection_Release(elements); - if(NS_FAILED(nsres)) - return map_nsresult(nsres); - - 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 HTMLFormElement_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -920,7 +895,7 @@ static const event_target_vtbl_t HTMLFormElement_event_target_vtbl = { .traverse = HTMLFormElement_traverse, .unlink = HTMLFormElement_unlink, .get_dispid = HTMLFormElement_get_dispid, - .get_name = HTMLFormElement_dispex_get_name, + .get_prop_desc = dispex_index_prop_desc, .invoke = HTMLFormElement_invoke }, HTMLELEMENT_EVENT_TARGET_VTBL_ENTRIES, diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 8302c7504b7..76598cadb77 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -149,7 +149,7 @@ sync_test("builtin_toString", function() { [ "figure", "" ], [ "font", "Font", -1 ], [ "footer", "" ], - [ "form", "Form", -1 ], + [ "form", "Form" ], [ "frame", "Frame", -1 ], [ "frameset", "FrameSet", -1 ], [ "h1", "Heading", -1 ],
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/dispex.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 2e4cf244a87..6bbc34b516e 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1678,13 +1678,6 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) } }
-compat_mode_t dispex_compat_mode(DispatchEx *dispex) -{ - return dispex->info != dispex->info->desc->delayed_init_info - ? dispex->info->compat_mode - : dispex->info->desc->vtbl->get_compat_mode(dispex); -} - HRESULT dispex_to_string(DispatchEx *dispex, BSTR *ret) { static const WCHAR prefix[8] = L"[object "; @@ -1741,13 +1734,23 @@ static dispex_data_t *ensure_dispex_info(DispatchEx *dispex, dispex_static_data_
static BOOL ensure_real_info(DispatchEx *dispex) { + compat_mode_t compat_mode; + if(dispex->info != dispex->info->desc->delayed_init_info) return TRUE;
- dispex->info = ensure_dispex_info(dispex, dispex->info->desc, dispex_compat_mode(dispex), NULL); + compat_mode = dispex->info->desc->vtbl->get_compat_mode(dispex); + dispex->info = ensure_dispex_info(dispex, dispex->info->desc, compat_mode, NULL); return dispex->info != NULL; }
+compat_mode_t dispex_compat_mode(DispatchEx *dispex) +{ + if(!ensure_real_info(dispex)) + return COMPAT_MODE_NONE; + return dispex->info->compat_mode; +} + static inline DispatchEx *impl_from_IWineJSDispatchHost(IWineJSDispatchHost *iface) { return CONTAINING_RECORD(iface, DispatchEx, IWineJSDispatchHost_iface);
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/dispex.c | 5 ++-- dlls/mshtml/htmldoc.c | 31 +++++++++++-------- dlls/mshtml/htmlwindow.c | 2 +- dlls/mshtml/mshtml_private.h | 2 +- dlls/mshtml/tests/documentmode.js | 4 +-- dlls/mshtml/tests/es5.js | 49 ++++++++++++++++++++++++++----- dlls/mshtml/tests/events.c | 1 - 7 files changed, 65 insertions(+), 29 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 6bbc34b516e..d9d7b35526f 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1734,13 +1734,14 @@ static dispex_data_t *ensure_dispex_info(DispatchEx *dispex, dispex_static_data_
static BOOL ensure_real_info(DispatchEx *dispex) { + HTMLInnerWindow *script_global = NULL; compat_mode_t compat_mode;
if(dispex->info != dispex->info->desc->delayed_init_info) return TRUE;
- compat_mode = dispex->info->desc->vtbl->get_compat_mode(dispex); - dispex->info = ensure_dispex_info(dispex, dispex->info->desc, compat_mode, NULL); + compat_mode = dispex->info->desc->vtbl->get_compat_mode(dispex, &script_global); + dispex->info = ensure_dispex_info(dispex, dispex->info->desc, compat_mode, script_global); return dispex->info != NULL; }
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 6fe1516a720..0eb2bc3bcda 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -5364,17 +5364,6 @@ static void HTMLDocumentNode_destructor(DispatchEx *dispex) HTMLDOMNode_destructor(&This->node.event_target.dispex); }
-static HRESULT HTMLDocumentNode_get_name(DispatchEx *dispex, DISPID id, BSTR *name) -{ - HTMLDocumentNode *This = impl_from_DispatchEx(dispex); - DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; - - if(!This->dom_document || idx >= This->elem_vars_cnt) - return DISP_E_MEMBERNOTFOUND; - - return (*name = SysAllocString(This->elem_vars[idx])) ? S_OK : E_OUTOFMEMORY; -} - static HRESULT HTMLDocumentNode_get_dispid(DispatchEx *dispex, const WCHAR *name, DWORD grfdex, DISPID *dispid) { HTMLDocumentNode *This = impl_from_DispatchEx(dispex); @@ -5531,12 +5520,28 @@ static HRESULT HTMLDocumentNode_next_dispid(DispatchEx *dispex, DISPID id, DISPI return S_OK; }
-static compat_mode_t HTMLDocumentNode_get_compat_mode(DispatchEx *dispex) +static HRESULT HTMLDocumentNode_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_info *desc) +{ + HTMLDocumentNode *This = impl_from_DispatchEx(dispex); + DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN; + + if(!This->dom_document || idx >= This->elem_vars_cnt) + return DISP_E_MEMBERNOTFOUND; + + desc->name = This->elem_vars[idx]; + desc->id = id; + desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; + desc->func_iid = 0; + return S_OK; +} + +static compat_mode_t HTMLDocumentNode_get_compat_mode(DispatchEx *dispex, HTMLInnerWindow **script_global) { HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
TRACE("(%p) returning %u\n", This, This->document_mode);
+ *script_global = This->script_global; return lock_document_mode(This); }
@@ -5628,9 +5633,9 @@ static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = { .destructor = HTMLDocumentNode_destructor, .traverse = HTMLDocumentNode_traverse, .unlink = HTMLDocumentNode_unlink, - .get_name = HTMLDocumentNode_get_name, .get_dispid = HTMLDocumentNode_get_dispid, .find_dispid = HTMLDocumentNode_find_dispid, + .get_prop_desc = HTMLDocumentNode_get_prop_desc, .invoke = HTMLDocumentNode_invoke, .disp_invoke = HTMLDocumentNode_disp_invoke, .next_dispid = HTMLDocumentNode_next_dispid, diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index c40d3fe889b..ceac07e4dd3 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3946,7 +3946,7 @@ static HRESULT HTMLWindow_next_dispid(DispatchEx *dispex, DISPID id, DISPID *pid return S_OK; }
-static compat_mode_t HTMLWindow_get_compat_mode(DispatchEx *dispex) +static compat_mode_t HTMLWindow_get_compat_mode(DispatchEx *dispex, HTMLInnerWindow **script_global) { HTMLInnerWindow *This = impl_from_DispatchEx(dispex); return lock_document_mode(This->doc); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 4e6a79108bb..04c51fb2503 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -398,7 +398,7 @@ typedef struct { HRESULT (*disp_invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
/* Used by objects that want to delay their compat mode initialization until actually needed */ - compat_mode_t (*get_compat_mode)(DispatchEx*); + compat_mode_t (*get_compat_mode)(DispatchEx*,HTMLInnerWindow**);
/* Used by objects that want to populate some dynamic props on initialization */ HRESULT (*populate_props)(DispatchEx*); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 76598cadb77..5fada630a51 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -296,7 +296,7 @@ sync_test("builtin_toString", function() { if(clientRects) test("clientRect", clientRects[0], "ClientRect", 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); + if(v >= 11 /* todo_wine */) test("document", document, v < 11 ? "Document" : "HTMLDocument"); test("elements", document.getElementsByTagName("body"), "HTMLCollection", null, true); test("history", window.history, "History"); test("implementation", document.implementation, "DOMImplementation"); @@ -379,7 +379,6 @@ sync_test("builtin_obj", function() { }catch(ex) { e = ex.number; } - todo_wine_if(v >= 9). ok(e === (v < 9 ? 0xa0005 : 0x0ffff) - 0x80000000, "[f.call(Object, 'div')] e = " + e);
e = 0; @@ -388,7 +387,6 @@ sync_test("builtin_obj", function() { }catch(ex) { e = ex.number; } - todo_wine_if(v >= 9). ok(e === (v < 9 ? 0xa0005 : 0x0ffff) - 0x80000000, "[f.call(null, 'div')] e = " + e);
var elem1 = f.call(document, "div"); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 1225a744de6..ddffea263a6 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -41,6 +41,15 @@ var JS_E_ARRAYBUFFER_EXPECTED = 0x800a15e4;
var tests = [];
+function check_enum(o, name) { + var ret = 0; + for(var iter in o) { + if(iter == name) ret++; + } + ok(ret < 2, name + " enumerated " + ret + " times"); + return ret != 0; +} + sync_test("script vars", function() { function foo() { } foo.prototype.foo = 13; @@ -2637,14 +2646,6 @@ sync_test("screen", function() { o.prop2 = 3; ok(!("prop2" in o), "o.prop2 = " + o.prop2);
- function check_enum(o, name) { - var ret = 0; - for(var iter in o) { - if(iter == name) ret++; - } - ok(ret < 2, name + " enumerated " + ret + " times"); - return ret != 0; - } ok(check_enum(o, "width"), "width not enumerated"); ok(check_enum(o, "height"), "height not enumerated"); ok(check_enum(o, "prop"), "prop not enumerated"); @@ -2692,3 +2693,35 @@ async_test("script_global", function() { iframe.src = "about:blank"; document.body.appendChild(iframe); }); + +sync_test("form_as_prop", function() { + document.body.innerHTML = '<form id="testid" name="testname"></form>'; + var form = document.body.firstChild; + var o = Object.create(document); + + ok(document.testid === form, "document.testid = " + document.testid); + ok(o.testid === form, "o.testid = " + o.testid); + ok(document.hasOwnProperty("testid"), 'document.hasOwnProperty("testid") = ' + document.hasOwnProperty("testid")); + ok(!o.hasOwnProperty("testid"), 'o.hasOwnProperty("testid") = ' + o.hasOwnProperty("testid")); + test_own_data_prop_desc(document, "testid", true, true, true); + + ok(document.testname === form, "document.testname = " + document.testname); + ok(o.testname === form, "o.testname = " + o.testname); + ok(document.hasOwnProperty("testname"), 'document.hasOwnProperty("testname") = ' + document.hasOwnProperty("testname")); + ok(!o.hasOwnProperty("testname"), 'o.hasOwnProperty("testname") = ' + o.hasOwnProperty("testname")); + test_own_data_prop_desc(document, "testname", true, true, true); + todo_wine. + ok(!check_enum(document, "testid"), "testid enumerated in document"); + ok(check_enum(document, "testname"), "testid not enumerated in document"); + todo_wine. + ok(!check_enum(o, "testid"), "testid enumerated in o"); + ok(check_enum(o, "testname"), "testid not enumerated in o"); + + document.body.innerHTML = ''; + ok(!("testid" in o), "testid is in o"); + ok(!("testname" in o), "testname is in o"); + ok(!("testid" in document), "testid is in document"); + ok(!("testname" in document), "testname is in document"); + ok(!document.hasOwnProperty("testid"), 'document.hasOwnProperty("testid") = ' + document.hasOwnProperty("testid")); + ok(!document.hasOwnProperty("testname"), 'document.hasOwnProperty("testname") = ' + document.hasOwnProperty("testname")); +}); diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 9760d6bcb9a..6b48fcda226 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -4239,7 +4239,6 @@ static void test_doc_obj(IHTMLDocument2 *doc) /* jscript prop on prototype chain */ bstr = SysAllocString(L"hasOwnProperty"); hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &has_own_prop_id); - todo_wine_if(document_mode >= 9) ok(hres == (document_mode < 9 ? DISP_E_UNKNOWNNAME : S_OK), "GetIDsOfNames(hasOwnProperty) returned: %08lx\n", hres); SysFreeString(bstr);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147341
Your paranoid android.
=== w1064v1507 (64 bit report) ===
mshtml: script.c:1223: Test failed: L"/index.html?dom.js:document_lastModified: lastModified too far from navigationStart: 3086"
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000011F00E8, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032