From: Gabriel Ivăncescu gabrielopcode@gmail.com
Based on a patch by Jacek Caban.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 40 +++++++++++++++++++------- dlls/jscript/function.c | 12 ++++---- dlls/jscript/jscript.h | 2 +- dlls/jscript/jsdisp.idl | 4 +-- dlls/mshtml/dispex.c | 60 ++++++++++++++++++++++++++------------- dlls/mshtml/htmldoc.c | 2 +- dlls/mshtml/htmlstorage.c | 2 +- dlls/mshtml/htmlwindow.c | 8 +++--- dlls/mshtml/pluginhost.c | 2 +- dlls/mshtml/tests/es5.js | 4 +++ 10 files changed, 91 insertions(+), 45 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index a99f09776e2..91fa2c00cf4 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -270,23 +270,41 @@ static dispex_prop_t *lookup_dispex_prop(jsdisp_t *obj, unsigned hash, const WCH
static HRESULT update_external_prop(jsdisp_t *obj, dispex_prop_t *prop, const struct property_info *desc) { - if(desc->func_iid) { + HRESULT hres; + + if(!desc->iid) { + prop->type = PROP_EXTERN; + prop->u.id = desc->id; + }else if(desc->flags & PROPF_METHOD) { jsdisp_t *func; - HRESULT hres;
- hres = create_host_function(obj->ctx, desc, &func); + hres = create_host_function(obj->ctx, desc, DISPATCH_METHOD, &func); if(FAILED(hres)) return hres;
prop->type = PROP_JSVAL; - prop->flags = desc->flags; prop->u.val = jsval_obj(func); - return S_OK; + }else { + jsdisp_t *getter, *setter = NULL; + + hres = create_host_function(obj->ctx, desc, DISPATCH_PROPERTYGET, &getter); + if(FAILED(hres)) + return hres; + + if(desc->flags & PROPF_WRITABLE) { + hres = create_host_function(obj->ctx, desc, DISPATCH_PROPERTYPUT, &setter); + if(FAILED(hres)) { + jsdisp_release(getter); + return hres; + } + } + + prop->type = PROP_ACCESSOR; + prop->u.accessor.getter = getter; + prop->u.accessor.setter = setter; }
- prop->type = PROP_EXTERN; - prop->flags = desc->flags; - prop->u.id = desc->id; + prop->flags = desc->flags & PROPF_ALL; return S_OK; }
@@ -469,13 +487,14 @@ HRESULT jsdisp_index_lookup(jsdisp_t *obj, const WCHAR *name, unsigned length, s } if(*ptr) return DISP_E_UNKNOWNNAME; + desc->id = idx; desc->flags = PROPF_ENUMERABLE; if(obj->builtin_info->prop_put) desc->flags |= PROPF_WRITABLE; desc->name = NULL; desc->index = idx; - desc->func_iid = 0; + desc->iid = 0; return S_OK; }
@@ -483,13 +502,14 @@ HRESULT jsdisp_next_index(jsdisp_t *obj, unsigned length, unsigned id, struct pr { if(id + 1 == length) return S_FALSE; + desc->id = id + 1; desc->flags = PROPF_ENUMERABLE; if(obj->builtin_info->prop_put) desc->flags |= PROPF_WRITABLE; desc->name = NULL; desc->index = desc->id; - desc->func_iid = 0; + desc->iid = 0; return S_OK; }
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 11be56dd809..5330bbae21f 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -68,6 +68,7 @@ typedef struct { const WCHAR *name; UINT32 id; UINT32 iid; + UINT32 flags; } HostFunction;
typedef struct { @@ -1022,8 +1023,8 @@ static HRESULT HostFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsva
if(SUCCEEDED(hres)) { V_VT(&retv) = VT_EMPTY; - hres = IWineJSDispatchHost_CallFunction(obj, function->id, function->iid, &dp, r ? &retv : NULL, &ei, - &ctx->jscaller->IServiceProvider_iface); + hres = IWineJSDispatchHost_CallFunction(obj, function->id, function->iid, function->flags, &dp, + r ? &retv : NULL, &ei, &ctx->jscaller->IServiceProvider_iface); if(hres == DISP_E_EXCEPTION) handle_dispatch_exception(ctx, &ei); if(SUCCEEDED(hres) && r) { @@ -1068,7 +1069,7 @@ static const function_vtbl_t HostFunctionVtbl = { HostFunction_gc_traverse };
-HRESULT create_host_function(script_ctx_t *ctx, const struct property_info *desc, jsdisp_t **ret) +HRESULT create_host_function(script_ctx_t *ctx, const struct property_info *desc, DWORD flags, jsdisp_t **ret) { HostFunction *function; HRESULT hres; @@ -1083,7 +1084,8 @@ HRESULT create_host_function(script_ctx_t *ctx, const struct property_info *desc
function->name = desc->name; function->id = desc->id; - function->iid = desc->func_iid; + function->iid = desc->iid; + function->flags = flags; *ret = &function->function.dispex; return S_OK; } @@ -1104,7 +1106,7 @@ static HRESULT HostConstructor_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, { HostConstructor *constr = (HostConstructor*)jsdisp; HRESULT hres = IWineJSDispatchHost_LookupProperty(constr->host_iface, name, flags, desc); - assert(hres != S_OK || desc->func_iid); /* external properties are not allowed */ + assert(hres != S_OK || (desc->flags & PROPF_METHOD)); /* external properties are not allowed */ return hres; }
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index a8285a8f468..aa9e9a9f383 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -277,7 +277,7 @@ HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const WCHAR*,cons jsdisp_t*,jsdisp_t**); HRESULT create_builtin_constructor(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD, jsdisp_t*,jsdisp_t**); -HRESULT create_host_function(script_ctx_t*,const struct property_info*,jsdisp_t**); +HRESULT create_host_function(script_ctx_t*,const struct property_info*,DWORD,jsdisp_t**); HRESULT Function_invoke(jsdisp_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*);
HRESULT Function_value(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*); diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index d31dd221eec..98d6ee20466 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -27,7 +27,7 @@ struct property_info UINT32 flags; const WCHAR *name; UINT32 index; - UINT32 func_iid; + UINT32 iid; };
const unsigned int PROPF_ARGMASK = 0x00ff; @@ -69,7 +69,7 @@ interface IWineJSDispatchHost : IDispatchEx 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 CallFunction(DISPID id, UINT32 iid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); HRESULT Construct(LCID lcid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); HRESULT GetOuterDispatch(IWineJSDispatchHost **ret); HRESULT ToString(BSTR *str); diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index c67631a6d14..7b6a8862dc5 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -285,10 +285,6 @@ static void add_func_info(dispex_data_t *data, tid_t tid, const FUNCDESC *desc, BSTR name; HRESULT hres;
- /* FIXME: Expose non-function properties from prototypes too (requires support for accessor properties). */ - if(data->is_prototype && !(desc->invkind & DISPATCH_METHOD)) - return; - if(name_override) name = SysAllocString(name_override); else if(desc->wFuncFlags & FUNCFLAG_FRESTRICTED) @@ -1054,7 +1050,7 @@ static HRESULT function_apply(func_disp_t *func, DISPPARAMS *dp, LCID lcid, VARI } }
- hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, ¶ms, res, ei, caller); + hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, DISPATCH_METHOD, ¶ms, res, ei, caller);
fail: while(argc--) @@ -1081,7 +1077,7 @@ static HRESULT function_call(func_disp_t *func, DISPPARAMS *dp, LCID lcid, VARIA if(FAILED(hres)) return CTL_E_ILLEGALFUNCTIONCALL;
- hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, ¶ms, res, ei, caller); + hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, DISPATCH_METHOD, ¶ms, res, ei, caller); IWineJSDispatchHost_Release(this_iface); return (hres == E_UNEXPECTED) ? CTL_E_ILLEGALFUNCTIONCALL : hres; } @@ -1158,7 +1154,7 @@ static HRESULT function_get_prop_desc(DispatchEx *dispex, DISPID id, struct prop desc->id = id; desc->flags = 0; desc->name = function_props[idx].name; - desc->func_iid = 0; + desc->iid = 0; return S_OK; }
@@ -2527,7 +2523,7 @@ HRESULT dispex_index_prop_desc(DispatchEx *dispex, DISPID id, struct property_in desc->flags |= PROPF_ENUMERABLE; desc->name = NULL; desc->index = id - MSHTML_DISPID_CUSTOM_MIN; - desc->func_iid = 0; + desc->iid = 0; return S_OK; }
@@ -2544,14 +2540,22 @@ static HRESULT get_host_property_descriptor(DispatchEx *This, DISPID id, struct hres = get_builtin_func(This->info, id, &func); if(FAILED(hres)) return hres; - desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; + desc->flags = PROPF_CONFIGURABLE; desc->name = func->name; - if(func->func_disp_idx < 0) { - if(func->func_disp_idx == -1) - desc->flags |= PROPF_ENUMERABLE; - desc->func_iid = 0; + if(func->func_disp_idx >= 0) { + desc->iid = func->tid; + desc->flags |= PROPF_METHOD | PROPF_WRITABLE; }else { - desc->func_iid = func->tid; + if(func->func_disp_idx == -1) + desc->flags |= PROPF_ENUMERABLE; + if(This->info->is_prototype) { + desc->iid = func->tid; + if(func->put_vtbl_off) + desc->flags |= PROPF_WRITABLE; + }else { + desc->flags |= PROPF_WRITABLE; + desc->iid = 0; + } } break; } @@ -2559,7 +2563,7 @@ static HRESULT get_host_property_descriptor(DispatchEx *This, DISPID id, struct 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; + desc->iid = 0; break; } case DISPEXPROP_CUSTOM: @@ -2646,19 +2650,35 @@ static HRESULT WINAPI JSDispatchHost_ConfigureProperty(IWineJSDispatchHost *ifac return S_OK; }
-static HRESULT WINAPI JSDispatchHost_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, - EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT WINAPI JSDispatchHost_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DWORD flags, + DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { DispatchEx *This = impl_from_IWineJSDispatchHost(iface); func_info_t *func; HRESULT hres;
- TRACE("%s (%p)->(%lx %x %p %p %p %p)\n", This->info->name, This, id, iid, dp, ret, ei, caller); + TRACE("%s (%p)->(%lx %x %lx %p %p %p %p)\n", This->info->name, This, id, iid, flags, dp, ret, ei, caller);
hres = get_builtin_func(This->info, id, &func); - if(FAILED(hres) || func->tid != iid || func->func_disp_idx < 0) + if(FAILED(hres) || func->tid != iid) return E_UNEXPECTED; - return call_builtin_function(This, func, dp, ret, ei, caller); + + switch(flags) { + case DISPATCH_METHOD: + assert(func->func_disp_idx >= 0); + return call_builtin_function(This, func, dp, ret, ei, caller); + case DISPATCH_PROPERTYGET: + assert(func->get_vtbl_off); + return builtin_propget(This, func, dp, ret, ei, caller); + case DISPATCH_PROPERTYPUT: + assert(func->put_vtbl_off); + if(ret) + V_VT(ret) = VT_EMPTY; + return builtin_propput(This, func, dp, ei, caller); + default: + assert(0); + return E_FAIL; + } }
static HRESULT WINAPI JSDispatchHost_Construct(IWineJSDispatchHost *iface, LCID lcid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 260264642b2..70bc028f3a0 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -5530,7 +5530,7 @@ static HRESULT HTMLDocumentNode_get_prop_desc(DispatchEx *dispex, DISPID id, str desc->name = This->elem_vars[idx]; desc->id = id; desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; - desc->func_iid = 0; + desc->iid = 0; return S_OK; }
diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 2ce8b951c20..8fb5679089a 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -1274,7 +1274,7 @@ static HRESULT HTMLStorage_get_prop_desc(DispatchEx *dispex, DISPID id, struct p desc->name = This->props[id - MSHTML_DISPID_CUSTOM_MIN]; desc->id = id; desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; - desc->func_iid = 0; + desc->iid = 0; return S_OK; }
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index ccb593724d4..a4039ce08bc 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3473,13 +3473,13 @@ static HRESULT WINAPI WindowDispEx_ConfigureProperty(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) +static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DWORD flags, DISPPARAMS *dp, + VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
return IWineJSDispatchHost_CallFunction(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, - id, iid, dp, ret, ei, caller); + id, iid, flags, dp, ret, ei, caller); }
static HRESULT WINAPI WindowDispEx_Construct(IWineJSDispatchHost *iface, LCID lcid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, @@ -3981,7 +3981,7 @@ HRESULT HTMLWindow_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_ desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; if(prop->type == GLOBAL_DISPEXVAR) desc->flags |= PROPF_ENUMERABLE; - desc->func_iid = 0; + desc->iid = 0; return S_OK; }
diff --git a/dlls/mshtml/pluginhost.c b/dlls/mshtml/pluginhost.c index 5479e25b0b8..c4a580ea4eb 100644 --- a/dlls/mshtml/pluginhost.c +++ b/dlls/mshtml/pluginhost.c @@ -835,7 +835,7 @@ HRESULT HTMLPluginContainer_get_prop_desc(DispatchEx *dispex, DISPID id, struct desc->id = id; desc->flags = 0; desc->name = plugin_container->props[id - MSHTML_DISPID_CUSTOM_MIN]->name; - desc->func_iid = 0; + desc->iid = 0; return S_OK; }
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 7496ea4c395..edbed64698e 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2661,6 +2661,10 @@ sync_test("screen", function() { ok(Object.isFrozen(o) === false, "Object.isFrozen(o) = " + Object.isFrozen(o)); ok(Object.isSealed(o) === true, "Object.isSealed(o) = " + Object.isSealed(o));
+ ok(!o.hasOwnProperty("width"), 'o.hasOwnProperty("width") = ' + o.hasOwnProperty("width")); + ok(Screen.prototype.hasOwnProperty("width"), + 'Screen.prototype.hasOwnProperty("width") = ' + Screen.prototype.hasOwnProperty("width")); + o.prop2 = 3; ok(!("prop2" in o), "o.prop2 = " + o.prop2);