This adds support for mshtml host object accessor to jscript, with necessary fixes along the way.
For the last patch I decided to go with flags (i.e. PROPF_METHOD) instead of introducing a type field, which makes it simpler, less fields to track off and less changes.
-- v2: jscript|mshtml: Add support for host object accessor props. mshtml: Move the hook invocations inside of the builtin_prop* helpers. mshtml: Fix builtin style translation in removeAttribute for IE9+ modes. mshtml: Move lookup_dispid and get_dispid calls out of get_builtin_id. mshtml: Don't make hidden props enumerable.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
So it matches dispex_next_id.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.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 20f924230fe..638c75edfe1 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2521,7 +2521,8 @@ static HRESULT get_host_property_descriptor(DispatchEx *This, DISPID id, struct desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; desc->name = func->name; if(func->func_disp_idx < 0) { - desc->flags |= PROPF_ENUMERABLE; + if(func->func_disp_idx == -1) + desc->flags |= PROPF_ENUMERABLE; desc->func_iid = 0; }else { desc->func_iid = func->tid;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
They're not really "builtins" (from the type info) and we need actual builtins for style attr checks.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 638c75edfe1..292ff8fa165 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1323,17 +1323,7 @@ static HRESULT get_builtin_func(dispex_data_t *data, DISPID id, func_info_t **re
static HRESULT get_builtin_id(DispatchEx *This, const WCHAR *name, DWORD grfdex, DISPID *ret) { - int min, max, n, c; - HRESULT hres; - - if(This->info->vtbl->lookup_dispid) { - hres = This->info->vtbl->lookup_dispid(This, name, grfdex, ret); - if(hres != DISP_E_UNKNOWNNAME) - return hres; - } - - min = 0; - max = This->info->name_cnt-1; + int min = 0, max = This->info->name_cnt - 1, n, c;
while(min <= max) { n = (min+max)/2; @@ -1353,12 +1343,6 @@ static HRESULT get_builtin_id(DispatchEx *This, const WCHAR *name, DWORD grfdex, min = n+1; }
- if(This->info->vtbl->get_dispid) { - hres = This->info->vtbl->get_dispid(This, name, grfdex, ret); - if(hres != DISP_E_UNKNOWNNAME) - return hres; - } - return DISP_E_UNKNOWNNAME; }
@@ -2059,10 +2043,22 @@ HRESULT dispex_get_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID dynamic_prop_t *dprop = NULL; HRESULT hres;
+ if(dispex->info->vtbl->lookup_dispid) { + hres = dispex->info->vtbl->lookup_dispid(dispex, name, flags, pid); + if(hres != DISP_E_UNKNOWNNAME) + return hres; + } + hres = get_builtin_id(dispex, name, flags, pid); if(hres != DISP_E_UNKNOWNNAME) return hres;
+ if(dispex->info->vtbl->get_dispid) { + hres = dispex->info->vtbl->get_dispid(dispex, name, flags, pid); + if(hres != DISP_E_UNKNOWNNAME) + return hres; + } + hres = get_dynamic_prop(dispex, name, flags & ~fdexNameEnsure, &dprop); if(FAILED(hres)) { if(dispex->info->vtbl->find_dispid) {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Because we're supposed to translate styles here to what Gecko expects via the style table, we don't actually need to look up the *real* prototypes on the object (what it has currently in js code), but rather just the builtin list of style props of the object, which must include all the styles supported. So we look into the entire builtin prototype chain.
remove_attribute also only deals with builtin dispids, so it makes no sense to use it on the output of GetDispID in IE9+ modes. Legacy modes do remove all props though, added tests to confirm this.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 30 ++++++++++++++++++++++++------ dlls/mshtml/htmlstyle.c | 7 +++++-- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/documentmode.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 292ff8fa165..7cd74476492 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1321,19 +1321,19 @@ static HRESULT get_builtin_func(dispex_data_t *data, DISPID id, func_info_t **re return DISP_E_MEMBERNOTFOUND; }
-static HRESULT get_builtin_id(DispatchEx *This, const WCHAR *name, DWORD grfdex, DISPID *ret) +static HRESULT get_builtin_id(const dispex_data_t *info, const WCHAR *name, DWORD grfdex, DISPID *ret) { - int min = 0, max = This->info->name_cnt - 1, n, c; + int min = 0, max = info->name_cnt - 1, n, c;
while(min <= max) { n = (min+max)/2;
- c = wcsicmp(This->info->name_table[n]->name, name); + c = wcsicmp(info->name_table[n]->name, name); if(!c) { - if((grfdex & fdexNameCaseSensitive) && wcscmp(This->info->name_table[n]->name, name)) + if((grfdex & fdexNameCaseSensitive) && wcscmp(info->name_table[n]->name, name)) break;
- *ret = This->info->name_table[n]->id; + *ret = info->name_table[n]->id; return S_OK; }
@@ -1346,6 +1346,24 @@ static HRESULT get_builtin_id(DispatchEx *This, const WCHAR *name, DWORD grfdex, return DISP_E_UNKNOWNNAME; }
+HRESULT dispex_get_chain_builtin_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID *pid) +{ + compat_mode_t compat_mode = dispex->info->compat_mode; + const dispex_data_t *info = dispex->info; + HRESULT hres; + + assert(compat_mode >= COMPAT_MODE_IE9); + + for(;;) { + hres = get_builtin_id(info, name, flags, pid); + if(hres != DISP_E_UNKNOWNNAME) + return hres; + if(!info->desc->prototype_id) + return DISP_E_UNKNOWNNAME; + info = object_descriptors[info->desc->prototype_id]->prototype_info[compat_mode - COMPAT_MODE_IE9]; + } +} + HRESULT change_type(VARIANT *dst, VARIANT *src, VARTYPE vt, IServiceProvider *caller) { V_VT(dst) = VT_EMPTY; @@ -2049,7 +2067,7 @@ HRESULT dispex_get_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID return hres; }
- hres = get_builtin_id(dispex, name, flags, pid); + hres = get_builtin_id(dispex->info, name, flags, pid); if(hres != DISP_E_UNKNOWNNAME) return hres;
diff --git a/dlls/mshtml/htmlstyle.c b/dlls/mshtml/htmlstyle.c index 33655698d43..92dd9f853be 100644 --- a/dlls/mshtml/htmlstyle.c +++ b/dlls/mshtml/htmlstyle.c @@ -2936,12 +2936,15 @@ static HRESULT WINAPI HTMLStyle_removeAttribute(IHTMLStyle *iface, BSTR strAttri
style_entry = lookup_style_tbl(&This->css_style, strAttributeName); if(!style_entry) { + DWORD fdex = (lFlags & 1) ? fdexNameCaseSensitive : fdexNameCaseInsensitive; compat_mode_t compat_mode = dispex_compat_mode(&This->css_style.dispex); DISPID dispid; unsigned i;
- hres = dispex_get_id(&This->css_style.dispex, strAttributeName, - (lFlags & 1) ? fdexNameCaseSensitive : fdexNameCaseInsensitive, &dispid); + if(compat_mode < COMPAT_MODE_IE9) + hres = IWineJSDispatchHost_GetDispID(&This->css_style.dispex.IWineJSDispatchHost_iface, strAttributeName, fdex, &dispid); + else + hres = dispex_get_chain_builtin_id(&This->css_style.dispex, strAttributeName, fdex, &dispid); if(hres != S_OK) { *pfSuccess = VARIANT_FALSE; return S_OK; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index b190e7c4dc8..b006202befd 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -629,6 +629,7 @@ HRESULT dispex_prop_get(DispatchEx *dispex, DISPID id, LCID lcid, VARIANT *r, EX IServiceProvider *caller); HRESULT dispex_prop_put(DispatchEx *dispex, DISPID id, LCID lcid, VARIANT *v, EXCEPINFO *ei, 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_prop_name(DispatchEx *dispex, DISPID id, BSTR *ret); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 071f76c11f0..306d65e5768 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -2596,6 +2596,36 @@ sync_test("builtins_diffs", function() { } });
+sync_test("style attribute", function() { + var r, v = document.documentMode, s = document.createElement("div").style; + + s.setAttribute("background-color", "black"); + s.foobar = "white"; + + r = s.getAttribute("background-color"); + ok(r === "black", "background-color = " + r); + r = s.foobar; + ok(r === "white", "foobar prop = " + r); + + r = s.removeAttribute("background-color"); + ok(r === true, "removeAttribute(background-color) returned " + r); + r = s.removeAttribute("border"); + ok(r === false, "removeAttribute(border) returned " + r); + r = s.removeAttribute("foobar"); + ok(r === (v < 9 ? true : false), "removeAttribute(foobar) returned " + r); + r = s.removeAttribute("barfoo"); + ok(r === false, "removeAttribute(barfoo) returned " + r); + + r = s.getAttribute("background-color"); + ok(r === "", "background-color after remove = " + r); + if(v < 9) + ok(!("foobar" in s), "foobar in style after remove"); + else { + r = s.foobar; + ok(r === "white", "foobar prop after remove = " + r); + } +}); + sync_test("nullDisp", function() { var v = document.documentMode, nullDisp = external.nullDisp, r;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 7cd74476492..35f4be50ea8 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1402,11 +1402,17 @@ HRESULT change_type(VARIANT *dst, VARIANT *src, VARTYPE vt, IServiceProvider *ca return VariantChangeType(dst, src, 0, vt); }
-static HRESULT builtin_propget(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res) +static HRESULT builtin_propget(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { IUnknown *iface; HRESULT hres;
+ if(func->hook) { + hres = func->hook(This, DISPATCH_PROPERTYGET, dp, res, ei, caller); + if(hres != S_FALSE) + return hres; + } + if(dp && dp->cArgs) { FIXME("cArgs %d\n", dp->cArgs); return E_NOTIMPL; @@ -1442,12 +1448,18 @@ static HRESULT builtin_propget(DispatchEx *This, func_info_t *func, DISPPARAMS * return S_OK; }
-static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, IServiceProvider *caller) +static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, EXCEPINFO *ei, IServiceProvider *caller) { VARIANT *v, tmpv; IUnknown *iface; HRESULT hres;
+ if(func->hook) { + hres = func->hook(This, DISPATCH_PROPERTYPUT, dp, NULL, ei, caller); + if(hres != S_FALSE) + return hres; + } + if(dp->cArgs != 1 || (dp->cNamedArgs == 1 && *dp->rgdispidNamedArgs != DISPID_PROPERTYPUT) || dp->cNamedArgs > 1) { FIXME("invalid args\n"); @@ -1699,28 +1711,27 @@ static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD if(func->func_disp_idx >= 0) return invoke_builtin_function(This, func, flags, dp, res, ei, caller);
- if(func->hook) { - hres = func->hook(This, flags, dp, res, ei, caller); - if(hres != S_FALSE) - return hres; - } - switch(flags) { case DISPATCH_PROPERTYPUT: if(res) V_VT(res) = VT_EMPTY; - hres = builtin_propput(This, func, dp, caller); + hres = builtin_propput(This, func, dp, ei, caller); break; case DISPATCH_PROPERTYGET: - hres = builtin_propget(This, func, dp, res); + hres = builtin_propget(This, func, dp, res, ei, caller); break; default: if(!func->get_vtbl_off) { + if(func->hook) { + hres = func->hook(This, flags, dp, res, ei, caller); + if(hres != S_FALSE) + return hres; + } hres = typeinfo_invoke(This, func, flags, dp, res, ei); }else { VARIANT v;
- hres = builtin_propget(This, func, NULL, &v); + hres = builtin_propget(This, func, NULL, &v, ei, caller); if(FAILED(hres)) return hres;
@@ -1811,7 +1822,7 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) *success = VARIANT_TRUE;
V_VT(&var) = VT_EMPTY; - hres = builtin_propput(This, func, &dp, NULL); + hres = builtin_propput(This, func, &dp, NULL, NULL); if(FAILED(hres)) { VARIANT *ref; hres = dispex_get_dprop_ref(This, func->name, FALSE, &ref);
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 | 7 ++--- dlls/jscript/jsdisp.idl | 7 +++-- 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 | 30 +++++++++++++++++++- 10 files changed, 120 insertions(+), 50 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 3d3d0f8a6c9..e9207c231d8 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -76,12 +76,9 @@ typedef struct jsdisp_t jsdisp_t; extern HINSTANCE jscript_hinstance ; HRESULT get_dispatch_typeinfo(ITypeInfo**);
-#define PROPF_ARGMASK 0x00ff -#define PROPF_METHOD 0x0100 -#define PROPF_CONSTR 0x0200 - #define PROPF_ALL (PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE)
+#define PROPF_ARGMASK 0x000000ff #define PROPF_VERSION_MASK 0x01ff0000 #define PROPF_VERSION_SHIFT 16 #define PROPF_HTML (SCRIPTLANGUAGEVERSION_HTML << PROPF_VERSION_SHIFT) @@ -281,7 +278,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 bae00d40a3d..051f819e817 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -27,9 +27,12 @@ struct property_info UINT32 flags; const WCHAR *name; UINT32 index; - UINT32 func_iid; + UINT32 iid; };
+const unsigned int PROPF_METHOD = 0x0100; +const unsigned int PROPF_CONSTR = 0x0200; + const unsigned int PROPF_ENUMERABLE = 0x0400; const unsigned int PROPF_WRITABLE = 0x0800; const unsigned int PROPF_CONFIGURABLE = 0x1000; @@ -65,7 +68,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 35f4be50ea8..9d69f413d44 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; }
@@ -2526,7 +2522,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; }
@@ -2543,14 +2539,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; } @@ -2558,7 +2562,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: @@ -2645,19 +2649,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..18b106e2a82 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2661,6 +2661,20 @@ 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")); + + var desc = Object.getOwnPropertyDescriptor(Screen.prototype, "width"); + ok(!("value" in desc), "width prop: value is in desc"); + ok(!("writable" in desc), "width prop: writable is in desc"); + ok(desc.enumerable === true, "width prop: enumerable = " + desc.enumerable); + ok(desc.configurable === true, "width prop: configurable = " + desc.configurable); + ok(Object.getPrototypeOf(desc.get) === Function.prototype, "width prop: get not a function: " + desc.get); + ok("set" in desc, "width prop: set is not in desc"); + ok(desc.set === undefined, "width prop: set not undefined: " + desc.set); + ok(desc.get.call(o) === o.width, "width prop: get.call() not same as o.width: " + desc.get.call(o) + ", expected " + o.width); + o.prop2 = 3; ok(!("prop2" in o), "o.prop2 = " + o.prop2);
@@ -2672,7 +2686,7 @@ sync_test("screen", function() { });
sync_test("builtin_func", function() { - var o = document.implementation; + var o = document.implementation, r; var f = o.hasFeature;
ok(f instanceof Function, "f is not an instance of Function"); @@ -2681,6 +2695,20 @@ sync_test("builtin_func", function() { ok(f.length === 0, "f.length = " + f.length); ok(f.call(o, "test", 1) === false, 'f.call(o, "test", 1) = ' + f.call(o, "test", 1)); ok("" + f === "\nfunction hasFeature() {\n [native code]\n}\n", "f = " + f); + + o = document.body; + var desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Object.getPrototypeOf(o)), "innerHTML"); + ok(!("value" in desc), "innerHTML prop: value is in desc"); + ok(!("writable" in desc), "innerHTML prop: writable is in desc"); + ok(desc.enumerable === true, "innerHTML prop: enumerable = " + desc.enumerable); + ok(desc.configurable === true, "innerHTML prop: configurable = " + desc.configurable); + ok(Object.getPrototypeOf(desc.get) === Function.prototype, "innerHTML prop: get not a function: " + desc.get); + ok(Object.getPrototypeOf(desc.set) === Function.prototype, "innerHTML prop: set not a function: " + desc.set); + r = desc.set.call(o, '<div id="winetest"></div>'); + ok(r === undefined, "innerHTML prop: setter returned " + r); + r = desc.get.call(o); + ok(r === '<div id="winetest"></div>', "innerHTML prop: getter returned " + r); + ok(r === o.innerHTML, "innerHTML prop: getter not same as o.innerHTML: " + r + ", expected " + o.innerHTML); });
async_test("script_global", function() {
This merge request was approved by Jacek Caban.