Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlselect.c | 46 +++++++++++++++++++++++++++++++++++++++- dlls/mshtml/tests/dom.c | 22 ++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index 7869a8e..b2c10f7 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -590,14 +590,58 @@ static const IHTMLOptionElementFactoryVtbl HTMLOptionElementFactoryVtbl = { HTMLOptionElementFactory_create };
+static inline HTMLOptionElementFactory *HTMLOptionElementFactory_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, HTMLOptionElementFactory, dispex); +} + +static HRESULT HTMLOptionElementFactory_value(DispatchEx *dispex, LCID lcid, + WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, + IServiceProvider *caller) +{ + HTMLOptionElementFactory *This = HTMLOptionElementFactory_from_DispatchEx(dispex); + unsigned int i, argc = params->cArgs - params->cNamedArgs; + IHTMLOptionElement *opt; + VARIANT empty, *arg[4]; + HRESULT hres; + + if(flags != DISPATCH_CONSTRUCT) { + FIXME("flags %x not supported\n", flags); + return E_NOTIMPL; + } + + V_VT(res) = VT_NULL; + V_VT(&empty) = VT_EMPTY; + + for(i = 0; i < ARRAY_SIZE(arg); i++) + arg[i] = argc > i ? ¶ms->rgvarg[params->cArgs - 1 - i] : ∅ + + hres = IHTMLOptionElementFactory_create(&This->IHTMLOptionElementFactory_iface, + *arg[0], *arg[1], *arg[2], *arg[3], &opt); + if(FAILED(hres)) + return hres; + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch*)opt; + + return S_OK; +} + static const tid_t HTMLOptionElementFactory_iface_tids[] = { IHTMLOptionElementFactory_tid, 0 };
+static const dispex_static_data_vtbl_t HTMLOptionElementFactory_dispex_vtbl = { + HTMLOptionElementFactory_value, + NULL, + NULL, + NULL +}; + static dispex_static_data_t HTMLOptionElementFactory_dispex = { L"Function", - NULL, + &HTMLOptionElementFactory_dispex_vtbl, IHTMLOptionElementFactory_tid, HTMLOptionElementFactory_iface_tids, HTMLElement_init_dispex_info diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index ea5b210..0c065a2 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -2190,10 +2190,12 @@ static void _set_object_name(unsigned line, IHTMLElement *elem, const WCHAR *nam static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *doc, const WCHAR *txt, const WCHAR *val) { + VARIANT text, value, empty, option_var, args[2]; + DISPPARAMS dp = { args, NULL, 2, 0 }; IHTMLOptionElementFactory *factory; IHTMLOptionElement *option; IHTMLWindow2 *window; - VARIANT text, value, empty; + IDispatch *disp; HRESULT hres;
hres = IHTMLDocument2_get_parentWindow(doc, &window); @@ -2211,6 +2213,24 @@ static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *do V_BSTR(&value) = SysAllocString(val); V_VT(&empty) = VT_EMPTY;
+ hres = IHTMLOptionElementFactory_QueryInterface(factory, &IID_IDispatch, (void**)&disp); + ok_(__FILE__,line)(hres == S_OK, "Could not get IDispatch: %08x\n", hres); + + args[1] = text; + args[0] = value; + hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, 0, DISPATCH_CONSTRUCT, &dp, &option_var, NULL, NULL); + IDispatch_Release(disp); + ok_(__FILE__,line)(hres == S_OK, "Invoke(DISPID_VALUE) returned: %08x\n", hres); + ok_(__FILE__,line)(V_VT(&option_var) == VT_DISPATCH, "VT(option_var) = %d\n", V_VT(&option_var)); + hres = IDispatch_QueryInterface(V_DISPATCH(&option_var), &IID_IHTMLOptionElement, (void**)&option); + ok_(__FILE__,line)(hres == S_OK, "Could not get IHTMLOptionElement: %08x\n", hres); + VariantClear(&option_var); + + _test_option_text(line, option, txt); + _test_option_value(line, option, val); + _test_option_selected(line, option, VARIANT_FALSE); + IHTMLOptionElement_Release(option); + hres = IHTMLOptionElementFactory_create(factory, text, value, empty, empty, &option); ok_(__FILE__,line) (hres == S_OK, "create failed: %08x\n", hres);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlstylesheet.c | 73 +++++++++++++++++++++++++++++++++++- dlls/mshtml/tests/dom.js | 3 ++ 2 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/htmlstylesheet.c b/dlls/mshtml/htmlstylesheet.c index c31c780..d82a089 100644 --- a/dlls/mshtml/htmlstylesheet.c +++ b/dlls/mshtml/htmlstylesheet.c @@ -576,13 +576,84 @@ static const IHTMLStyleSheetsCollectionVtbl HTMLStyleSheetsCollectionVtbl = { HTMLStyleSheetsCollection_item };
+static inline HTMLStyleSheetsCollection *HTMLStyleSheetsCollection_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, HTMLStyleSheetsCollection, dispex); +} + +static HRESULT HTMLStyleSheetsCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid) +{ + HTMLStyleSheetsCollection *This = HTMLStyleSheetsCollection_from_DispatchEx(dispex); + UINT32 len = 0; + DWORD idx = 0; + WCHAR *ptr; + + for(ptr = name; *ptr && is_digit(*ptr); ptr++) + idx = idx*10 + (*ptr-'0'); + if(*ptr) + return DISP_E_UNKNOWNNAME; + + nsIDOMStyleSheetList_GetLength(This->nslist, &len); + if(idx >= len) + return DISP_E_UNKNOWNNAME; + + *dispid = MSHTML_DISPID_CUSTOM_MIN + idx; + TRACE("ret %x\n", *dispid); + return S_OK; +} + +static HRESULT HTMLStyleSheetsCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLStyleSheetsCollection *This = HTMLStyleSheetsCollection_from_DispatchEx(dispex); + + TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller); + + switch(flags) { + case DISPATCH_PROPERTYGET: { + nsIDOMStyleSheet *nsstylesheet; + IHTMLStyleSheet *stylesheet; + nsresult nsres; + HRESULT hres; + + nsres = nsIDOMStyleSheetList_Item(This->nslist, id - MSHTML_DISPID_CUSTOM_MIN, &nsstylesheet); + if(NS_FAILED(nsres)) + return DISP_E_MEMBERNOTFOUND; + if(!nsstylesheet) { + V_VT(res) = VT_EMPTY; + return S_OK; + } + + hres = create_style_sheet(nsstylesheet, dispex_compat_mode(&This->dispex), &stylesheet); + nsIDOMStyleSheet_Release(nsstylesheet); + if(FAILED(hres)) + return hres; + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch*)stylesheet; + break; + } + + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static const dispex_static_data_vtbl_t HTMLStyleSheetsCollection_dispex_vtbl = { + NULL, + HTMLStyleSheetsCollection_get_dispid, + HTMLStyleSheetsCollection_invoke +}; static const tid_t HTMLStyleSheetsCollection_iface_tids[] = { IHTMLStyleSheetsCollection_tid, 0 }; static dispex_static_data_t HTMLStyleSheetsCollection_dispex = { L"StyleSheetList", - NULL, + &HTMLStyleSheetsCollection_dispex_vtbl, DispHTMLStyleSheetsCollection_tid, HTMLStyleSheetsCollection_iface_tids }; diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index e2be697..ed5f72c 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -405,6 +405,9 @@ sync_test("stylesheets", function() { ok(typeof(stylesheet.rules.item(0)) === "object", "typeof(stylesheet.rules.item(0)) = " + typeof(stylesheet.rules.item(0)));
+ stylesheet = document.styleSheets[0]; + ok(stylesheet.rules.length === 1, "document.styleSheets[0].rules.length = " + stylesheet.rules.length); + try { stylesheet.rules.item(1); ok(false, "expected exception");
Signed-off-by: Jacek Caban jacek@codeweavers.com
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=103320
Your paranoid android.
=== w8adm (32 bit report) ===
mshtml: events.c:1089: Test failed: unexpected call img_onerror events: Timeout
=== w8adm (32 bit report) ===
mshtml: htmldoc.c:3084: Test failed: Incorrect error code: -2146697211 htmldoc.c:3089: Test failed: Page address: L"http://test.winehq.org/tests/winehq_snapshot/" htmldoc.c:5861: Test failed: expected OnChanged_1012 htmldoc.c:5862: Test failed: expected Exec_HTTPEQUIV htmldoc.c:5864: Test failed: expected Exec_SETTITLE htmldoc.c:5905: Test failed: expected FireNavigateComplete2
=== w10pro64_zh_CN (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
=== w7u_el (32 bit report) ===
mshtml: script.c:624: Test failed: L"/index.html?es5.js:date_now: unexpected Date.now() result 1638543412437 expected 1638543412500"
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlstylesheet.c | 73 ++++++++++++++++++++++++++++++- dlls/mshtml/tests/documentmode.js | 2 +- 2 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlstylesheet.c b/dlls/mshtml/htmlstylesheet.c index d82a089..3d9b7bb 100644 --- a/dlls/mshtml/htmlstylesheet.c +++ b/dlls/mshtml/htmlstylesheet.c @@ -375,13 +375,84 @@ static const IHTMLStyleSheetRulesCollectionVtbl HTMLStyleSheetRulesCollectionVtb HTMLStyleSheetRulesCollection_item };
+static inline HTMLStyleSheetRulesCollection *HTMLStyleSheetRulesCollection_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, HTMLStyleSheetRulesCollection, dispex); +} + +static HRESULT HTMLStyleSheetRulesCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid) +{ + HTMLStyleSheetRulesCollection *This = HTMLStyleSheetRulesCollection_from_DispatchEx(dispex); + UINT32 len = 0; + DWORD idx = 0; + WCHAR *ptr; + + for(ptr = name; *ptr && is_digit(*ptr); ptr++) + idx = idx*10 + (*ptr-'0'); + if(*ptr) + return DISP_E_UNKNOWNNAME; + + nsIDOMCSSRuleList_GetLength(This->nslist, &len); + if(idx >= len) + return DISP_E_UNKNOWNNAME; + + *dispid = MSHTML_DISPID_CUSTOM_MIN + idx; + TRACE("ret %x\n", *dispid); + return S_OK; +} + +static HRESULT HTMLStyleSheetRulesCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLStyleSheetRulesCollection *This = HTMLStyleSheetRulesCollection_from_DispatchEx(dispex); + + TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller); + + switch(flags) { + case DISPATCH_PROPERTYGET: { + IHTMLStyleSheetRule *stylesheetrule; + nsIDOMCSSRule *nsstylesheetrule; + nsresult nsres; + HRESULT hres; + + nsres = nsIDOMCSSRuleList_Item(This->nslist, id - MSHTML_DISPID_CUSTOM_MIN, &nsstylesheetrule); + if(NS_FAILED(nsres)) + return DISP_E_MEMBERNOTFOUND; + if(!nsstylesheetrule) { + V_VT(res) = VT_EMPTY; + return S_OK; + } + + hres = create_style_sheet_rule(nsstylesheetrule, dispex_compat_mode(&This->dispex), &stylesheetrule); + nsIDOMCSSRule_Release(nsstylesheetrule); + if(FAILED(hres)) + return hres; + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch*)stylesheetrule; + break; + } + + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static const dispex_static_data_vtbl_t HTMLStyleSheetRulesCollection_dispex_vtbl = { + NULL, + HTMLStyleSheetRulesCollection_get_dispid, + HTMLStyleSheetRulesCollection_invoke +}; static const tid_t HTMLStyleSheetRulesCollection_iface_tids[] = { IHTMLStyleSheetRulesCollection_tid, 0 }; static dispex_static_data_t HTMLStyleSheetRulesCollection_dispex = { L"MSCSSRuleList", - NULL, + &HTMLStyleSheetRulesCollection_dispex_vtbl, DispHTMLStyleSheetRulesCollection_tid, HTMLStyleSheetRulesCollection_iface_tids }; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 2564186..6555e8b 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -226,7 +226,7 @@ sync_test("builtin_toString", function() { test("sessionStorage", window.sessionStorage, "Storage"); test("style", document.body.style, "MSStyleCSSProperties"); test("styleSheet", sheet, "CSSStyleSheet"); - test("styleSheetRule", sheet.rules.item(0), "CSSStyleRule"); + test("styleSheetRule", sheet.rules[0], "CSSStyleRule"); test("styleSheetRules", sheet.rules, "MSCSSRuleList"); test("styleSheets", document.styleSheets, "StyleSheetList"); test("textNode", document.createTextNode("testNode"), "Text", v < 9 ? "testNode" : null);
Signed-off-by: Jacek Caban jacek@codeweavers.com
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=103321
Your paranoid android.
=== w8adm (32 bit report) ===
mshtml: events.c:1089: Test failed: unexpected call img_onerror events: Timeout
=== w8adm (32 bit report) ===
mshtml: htmldoc.c:3084: Test failed: Incorrect error code: -2146697211 htmldoc.c:3089: Test failed: Page address: L"http://test.winehq.org/tests/winehq_snapshot/" htmldoc.c:5861: Test failed: expected OnChanged_1012 htmldoc.c:5862: Test failed: expected Exec_HTTPEQUIV htmldoc.c:5864: Test failed: expected Exec_SETTITLE htmldoc.c:5905: Test failed: expected FireNavigateComplete2
=== w1064_tsign (32 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
=== w10pro64_he (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
This fixes a discrepancy between builtins called via a function dispatch object and others.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 37 ++++++++++++++++++++----------- dlls/mshtml/htmlelem.c | 7 +++--- dlls/mshtml/htmlevent.c | 10 ++++----- dlls/mshtml/mshtml_private.h | 6 +++-- dlls/mshtml/tests/documentmode.js | 14 +++++++++++- dlls/mshtml/xmlhttprequest.c | 5 ++--- 6 files changed, 50 insertions(+), 29 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 9f56a56..4ba00f8 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -49,7 +49,7 @@ typedef struct { VARIANT default_value; } func_arg_info_t;
-typedef struct { +struct func_info_t { DISPID id; BSTR name; tid_t tid; @@ -63,7 +63,7 @@ typedef struct { VARTYPE prop_vt; VARTYPE *arg_types; func_arg_info_t *arg_info; -} func_info_t; +};
struct dispex_data_t { dispex_static_data_t *desc; @@ -837,6 +837,11 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR case DISPATCH_METHOD: if(!This->obj) return E_UNEXPECTED; + if(This->info->hook) { + hres = This->info->hook(This->obj, This->info, lcid, flags, params, res, ei, caller); + if(hres != S_FALSE) + break; + } hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei); break; case DISPATCH_PROPERTYGET: { @@ -1163,13 +1168,17 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * return hres; }
-static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller) +HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, + EXCEPINFO *ei, IServiceProvider *caller) { VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres; unsigned i, nconv = 0; IUnknown *iface; HRESULT hres;
+ if(!func->call_vtbl_off) + return typeinfo_invoke(This, func, flags, dp, res, ei); + if(dp->cNamedArgs) { FIXME("Named arguments not supported\n"); return E_NOTIMPL; @@ -1265,8 +1274,8 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP return V_ERROR(&vhres); }
-static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, - EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT function_invoke(DispatchEx *This, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { HRESULT hres;
@@ -1296,10 +1305,12 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, } }
- if(func->call_vtbl_off) - hres = invoke_builtin_function(This, func, dp, res, caller); - else - hres = typeinfo_invoke(This, func, flags, dp, res, ei); + if(func->hook) { + hres = func->hook(This, func, lcid, flags, dp, res, ei, caller); + if(hres != S_FALSE) + break; + } + hres = invoke_builtin_function(This, func, flags, dp, res, ei, caller); break; case DISPATCH_PROPERTYGET: { func_obj_entry_t *entry; @@ -1364,15 +1375,15 @@ static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD if(FAILED(hres)) return hres;
+ if(func->func_disp_idx != -1) + return function_invoke(This, func, lcid, flags, dp, res, ei, caller); + if(func->hook) { - hres = func->hook(This, lcid, flags, dp, res, ei, caller); + hres = func->hook(This, func, lcid, flags, dp, res, ei, caller); if(hres != S_FALSE) return hres; }
- if(func->func_disp_idx != -1) - return function_invoke(This, func, flags, dp, res, ei, caller); - switch(flags) { case DISPATCH_PROPERTYPUT: if(res) diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index a205728..5b14550 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6643,8 +6643,8 @@ static IHTMLEventObj *HTMLElement_set_current_event(DispatchEx *dispex, IHTMLEve return default_set_current_event(This->node.doc->window, event); }
-static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, - VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, func_info_t *func, LCID lcid, WORD flags, + DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { VARIANT args[2]; HRESULT hres; @@ -6667,8 +6667,7 @@ static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, LCID lcid, WO return hres; args[1] = dp->rgvarg[dp->cArgs - 1];
- hres = IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IHTMLELEMENT6_IE9_SETATTRIBUTE, - lcid, flags, &new_dp, res, ei, caller); + hres = invoke_builtin_function(dispex, func, flags, &new_dp, res, ei, caller); VariantClear(&args[0]); return hres; } diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 3f545bb..653aed3 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -3314,7 +3314,7 @@ static HRESULT WINAPI EventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent * return dispatch_event_object(This, event, DISPATCH_STANDARD, result); }
-static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, LCID lcid, WORD flags, +static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { /* If only two arguments were given, implicitly set capture to false */ @@ -3328,14 +3328,13 @@ static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, LCID lcid,
TRACE("implicit capture\n");
- return IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IEVENTTARGET_ADDEVENTLISTENER, - lcid, flags, &new_dp, res, ei, caller); + return invoke_builtin_function(dispex, func, flags, &new_dp, res, ei, caller); }
return S_FALSE; /* fallback to default */ }
-static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, LCID lcid, WORD flags, +static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { /* If only two arguments were given, implicitly set capture to false */ @@ -3349,8 +3348,7 @@ static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, LCID lc
TRACE("implicit capture\n");
- return IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, - lcid, flags, &new_dp, res, ei, caller); + return invoke_builtin_function(dispex, func, flags, &new_dp, res, ei, caller); }
return S_FALSE; /* fallback to default */ diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 6978ed7..e18db4b 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -312,6 +312,7 @@ extern const compat_mode_info_t compat_mode_info[COMPAT_MODE_CNT] DECLSPEC_HIDDE
typedef struct dispex_data_t dispex_data_t; typedef struct dispex_dynamic_data_t dispex_dynamic_data_t; +typedef struct func_info_t func_info_t;
#define MSHTML_DISPID_CUSTOM_MIN 0x60000000 #define MSHTML_DISPID_CUSTOM_MAX 0x6fffffff @@ -337,8 +338,8 @@ typedef struct { dispex_data_t *delayed_init_info; } dispex_static_data_t;
-typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*, - EXCEPINFO*,IServiceProvider*); +typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,func_info_t*,LCID,WORD,DISPPARAMS*, + VARIANT*,EXCEPINFO*,IServiceProvider*);
typedef struct { DISPID dispid; @@ -387,6 +388,7 @@ BOOL dispex_query_interface(DispatchEx*,REFIID,void**) DECLSPEC_HIDDEN; HRESULT change_type(VARIANT*,VARIANT*,VARTYPE,IServiceProvider*) DECLSPEC_HIDDEN; HRESULT dispex_get_dprop_ref(DispatchEx*,const WCHAR*,BOOL,VARIANT**) DECLSPEC_HIDDEN; HRESULT get_dispids(tid_t,DWORD*,DISPID**) DECLSPEC_HIDDEN; +HRESULT invoke_builtin_function(DispatchEx*,func_info_t*,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*) DECLSPEC_HIDDEN; HRESULT remove_attribute(DispatchEx*,DISPID,VARIANT_BOOL*) DECLSPEC_HIDDEN; HRESULT dispex_get_dynid(DispatchEx*,const WCHAR*,DISPID*) DECLSPEC_HIDDEN; void dispex_traverse(DispatchEx*,nsCycleCollectionTraversalCallback*) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 6555e8b..2af5fae 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1166,6 +1166,18 @@ sync_test("elem_attr", function() { r = elem.removeAttribute("testattr"); ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom valueOf returned " + r); ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom valueOf = " + elem.testattr); + + var func = elem.setAttribute; + try { + func("testattr", arr); + todo_wine_if(v >= 9). + ok(v < 9, "expected exception setting testattr via func"); + }catch(ex) { + ok(v >= 9, "did not expect exception setting testattr via func"); + elem.setAttribute("testattr", arr); + } + r = elem.getAttribute("testattr"); + ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute (as func) = " + r); delete arr.valueOf; delete arr.toString;
@@ -1177,7 +1189,7 @@ sync_test("elem_attr", function() { ok(r === (v < 9 ? true : undefined), "id removeAttribute returned " + r); ok(elem.id === "", "removed id = " + elem.id);
- var func = function() { }; + func = function() { }; elem.onclick = func; ok(elem.onclick === func, "onclick = " + elem.onclick); r = elem.getAttribute("onclick"); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 56e18d0..f28d9c3 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -475,7 +475,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface) return S_OK; }
-static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, LCID lcid, WORD flags, +static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { /* If only two arguments were given, implicitly set async to false */ @@ -491,8 +491,7 @@ static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, LCID lcid, WORD
TRACE("implicit async\n");
- return IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IHTMLXMLHTTPREQUEST_OPEN, - lcid, flags, &new_dp, res, ei, caller); + return invoke_builtin_function(dispex, func, flags, &new_dp, res, ei, caller); }
return S_FALSE; /* fallback to default */
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
This fixes a discrepancy between builtins called via a function dispatch object and others.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/mshtml/dispex.c | 37 ++++++++++++++++++++----------- dlls/mshtml/htmlelem.c | 7 +++--- dlls/mshtml/htmlevent.c | 10 ++++----- dlls/mshtml/mshtml_private.h | 6 +++-- dlls/mshtml/tests/documentmode.js | 14 +++++++++++- dlls/mshtml/xmlhttprequest.c | 5 ++--- 6 files changed, 50 insertions(+), 29 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 9f56a56..4ba00f8 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -49,7 +49,7 @@ typedef struct { VARIANT default_value; } func_arg_info_t;
-typedef struct { +struct func_info_t { DISPID id; BSTR name; tid_t tid; @@ -63,7 +63,7 @@ typedef struct { VARTYPE prop_vt; VARTYPE *arg_types; func_arg_info_t *arg_info; -} func_info_t; +};
This could be kept local to dispex.c.
struct dispex_data_t { dispex_static_data_t *desc; @@ -837,6 +837,11 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR case DISPATCH_METHOD: if(!This->obj) return E_UNEXPECTED;
if(This->info->hook) {
hres = This->info->hook(This->obj, This->info, lcid, flags, params, res, ei, caller);
if(hres != S_FALSE)
break;
} hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei); break;
I think you could simply change typeinfo_invoke to function_invoke() here.
case DISPATCH_PROPERTYGET: {
@@ -1163,13 +1168,17 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * return hres; }
-static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller) +HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
EXCEPINFO *ei, IServiceProvider *caller)
{ VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres; unsigned i, nconv = 0; IUnknown *iface; HRESULT hres;
if(!func->call_vtbl_off)
return typeinfo_invoke(This, func, flags, dp, res, ei);
if(dp->cNamedArgs) { FIXME("Named arguments not supported\n"); return E_NOTIMPL;
@@ -1265,8 +1274,8 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP return V_ERROR(&vhres); }
-static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
EXCEPINFO *ei, IServiceProvider *caller)
+static HRESULT function_invoke(DispatchEx *This, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp,
{ HRESULT hres;VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
@@ -1296,10 +1305,12 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, } }
if(func->call_vtbl_off)
hres = invoke_builtin_function(This, func, dp, res, caller);
else
hres = typeinfo_invoke(This, func, flags, dp, res, ei);
if(func->hook) {
hres = func->hook(This, func, lcid, flags, dp, res, ei, caller);
if(hres != S_FALSE)
break;
}
hres = invoke_builtin_function(This, func, flags, dp, res, ei, caller);
This seems to be a good place to call the hook, but could you just keep typeinfo_invoke call here and don't expose invoke_builtin_function?
Thanks,
Jacek
Hi Jacek,
Thanks for the review.
On 03/12/2021 16:35, Jacek Caban wrote:
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
This fixes a discrepancy between builtins called via a function dispatch object and others.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/mshtml/dispex.c | 37 ++++++++++++++++++++----------- dlls/mshtml/htmlelem.c | 7 +++--- dlls/mshtml/htmlevent.c | 10 ++++----- dlls/mshtml/mshtml_private.h | 6 +++-- dlls/mshtml/tests/documentmode.js | 14 +++++++++++- dlls/mshtml/xmlhttprequest.c | 5 ++--- 6 files changed, 50 insertions(+), 29 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 9f56a56..4ba00f8 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -49,7 +49,7 @@ typedef struct { VARIANT default_value; } func_arg_info_t; -typedef struct { +struct func_info_t { DISPID id; BSTR name; tid_t tid; @@ -63,7 +63,7 @@ typedef struct { VARTYPE prop_vt; VARTYPE *arg_types; func_arg_info_t *arg_info; -} func_info_t; +};
This could be kept local to dispex.c.
How are hooks supposed to call it then? It's opaque outside of dispex.c and just forwarded in hooks where necessary. Should I change the argument in hooks to void* then?
struct dispex_data_t { dispex_static_data_t *desc; @@ -837,6 +837,11 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR case DISPATCH_METHOD: if(!This->obj) return E_UNEXPECTED; + if(This->info->hook) { + hres = This->info->hook(This->obj, This->info, lcid, flags, params, res, ei, caller); + if(hres != S_FALSE) + break; + } hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei); break;
I think you could simply change typeinfo_invoke to function_invoke() here.
We have some named argument tests that will fail if that is used, because it will attempt to use invoke_builtin_function which doesn't have them implemented (yes, I know it's a workaround but...).
Of course if I use only typeinfo_invoke in function_invoke then this issue disappears, but then what's the point of invoke_builtin_function?
case DISPATCH_PROPERTYGET: { @@ -1163,13 +1168,17 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * return hres; } -static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller) +HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, + EXCEPINFO *ei, IServiceProvider *caller) { VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres; unsigned i, nconv = 0; IUnknown *iface; HRESULT hres; + if(!func->call_vtbl_off) + return typeinfo_invoke(This, func, flags, dp, res, ei);
if(dp->cNamedArgs) { FIXME("Named arguments not supported\n"); return E_NOTIMPL; @@ -1265,8 +1274,8 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP return V_ERROR(&vhres); } -static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, - EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT function_invoke(DispatchEx *This, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { HRESULT hres; @@ -1296,10 +1305,12 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, } } - if(func->call_vtbl_off) - hres = invoke_builtin_function(This, func, dp, res, caller); - else - hres = typeinfo_invoke(This, func, flags, dp, res, ei); + if(func->hook) { + hres = func->hook(This, func, lcid, flags, dp, res, ei, caller); + if(hres != S_FALSE) + break; + } + hres = invoke_builtin_function(This, func, flags, dp, res, ei, caller);
This seems to be a good place to call the hook, but could you just keep typeinfo_invoke call here and don't expose invoke_builtin_function?
But I need to expose it for hooks so they can forward to it. It's either that or I expose typeinfo_invoke. Keep in mind that, for hooks, the Dispatch object itself may not exist at all, we can't use it to look up the function, that's incorrect.
That's not the case right now, no, but it will be when I'll either implement function.apply/call (for all modes) or the proxy jscript implementation, in further patches.
Here's a future example:
f = elem.setAttribute; f.call(some_other_obj, "a", blah);
The hook needs to run on some_other_obj and stringify blah appropriately before calling the builtin function on some_other_obj. In fact, we won't have a DispatchEx at all, just a generic IDispatch with "some_other_obj".
Thanks, Gabriel
On 12/3/21 7:21 PM, Gabriel Ivăncescu wrote:
Hi Jacek,
Thanks for the review.
On 03/12/2021 16:35, Jacek Caban wrote:
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
This fixes a discrepancy between builtins called via a function dispatch object and others.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/mshtml/dispex.c | 37 ++++++++++++++++++++----------- dlls/mshtml/htmlelem.c | 7 +++--- dlls/mshtml/htmlevent.c | 10 ++++----- dlls/mshtml/mshtml_private.h | 6 +++-- dlls/mshtml/tests/documentmode.js | 14 +++++++++++- dlls/mshtml/xmlhttprequest.c | 5 ++--- 6 files changed, 50 insertions(+), 29 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 9f56a56..4ba00f8 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -49,7 +49,7 @@ typedef struct { VARIANT default_value; } func_arg_info_t; -typedef struct { +struct func_info_t { DISPID id; BSTR name; tid_t tid; @@ -63,7 +63,7 @@ typedef struct { VARTYPE prop_vt; VARTYPE *arg_types; func_arg_info_t *arg_info; -} func_info_t; +};
This could be kept local to dispex.c.
How are hooks supposed to call it then? It's opaque outside of dispex.c and just forwarded in hooks where necessary. Should I change the argument in hooks to void* then?
I see, the problematic case is when we call builtin, but the original property was overwritten. Still, I don't think it's the right to call the hook directly in function_value().
case DISPATCH_PROPERTYGET: { @@ -1163,13 +1168,17 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * return hres; } -static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller) +HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, + EXCEPINFO *ei, IServiceProvider *caller) { VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres; unsigned i, nconv = 0; IUnknown *iface; HRESULT hres; + if(!func->call_vtbl_off) + return typeinfo_invoke(This, func, flags, dp, res, ei);
if(dp->cNamedArgs) { FIXME("Named arguments not supported\n"); return E_NOTIMPL; @@ -1265,8 +1274,8 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP return V_ERROR(&vhres); } -static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, - EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT function_invoke(DispatchEx *This, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { HRESULT hres; @@ -1296,10 +1305,12 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, } } - if(func->call_vtbl_off) - hres = invoke_builtin_function(This, func, dp, res, caller); - else - hres = typeinfo_invoke(This, func, flags, dp, res, ei); + if(func->hook) { + hres = func->hook(This, func, lcid, flags, dp, res, ei, caller); + if(hres != S_FALSE) + break; + } + hres = invoke_builtin_function(This, func, flags, dp, res, ei, caller);
This seems to be a good place to call the hook, but could you just keep typeinfo_invoke call here and don't expose invoke_builtin_function?
But I need to expose it for hooks so they can forward to it. It's either that or I expose typeinfo_invoke. Keep in mind that, for hooks, the Dispatch object itself may not exist at all, we can't use it to look up the function, that's incorrect.
That's not the case right now, no, but it will be when I'll either implement function.apply/call (for all modes) or the proxy jscript implementation, in further patches.
Here's a future example:
f = elem.setAttribute; f.call(some_other_obj, "a", blah);
The hook needs to run on some_other_obj and stringify blah appropriately before calling the builtin function on some_other_obj. In fact, we won't have a DispatchEx at all, just a generic IDispatch with "some_other_obj".
I hoped that the result of your 'proxy' patches will be that those functions will be true JavaScript objects. It means that MSHTML's function objects will not be relevant in ES5 mode. Why do you still need them?
Thanks,
Jacek
On 03/12/2021 21:19, Jacek Caban wrote:
On 12/3/21 7:21 PM, Gabriel Ivăncescu wrote:
Hi Jacek,
Thanks for the review.
On 03/12/2021 16:35, Jacek Caban wrote:
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
This fixes a discrepancy between builtins called via a function dispatch object and others.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/mshtml/dispex.c | 37 ++++++++++++++++++++----------- dlls/mshtml/htmlelem.c | 7 +++--- dlls/mshtml/htmlevent.c | 10 ++++----- dlls/mshtml/mshtml_private.h | 6 +++-- dlls/mshtml/tests/documentmode.js | 14 +++++++++++- dlls/mshtml/xmlhttprequest.c | 5 ++--- 6 files changed, 50 insertions(+), 29 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 9f56a56..4ba00f8 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -49,7 +49,7 @@ typedef struct { VARIANT default_value; } func_arg_info_t; -typedef struct { +struct func_info_t { DISPID id; BSTR name; tid_t tid; @@ -63,7 +63,7 @@ typedef struct { VARTYPE prop_vt; VARTYPE *arg_types; func_arg_info_t *arg_info; -} func_info_t; +};
This could be kept local to dispex.c.
How are hooks supposed to call it then? It's opaque outside of dispex.c and just forwarded in hooks where necessary. Should I change the argument in hooks to void* then?
I see, the problematic case is when we call builtin, but the original property was overwritten. Still, I don't think it's the right to call the hook directly in function_value().
Why not? In fact, the hook *should* be called everytime before invoke_builtin_function (or typeinfo_invoke) except when it's called from the hook itself. It makes sense, since the hook is supposed to override *all* calls to the builtin in any other case.
Maybe I can use a helper function instead? Which calls the hook at the top and then invoke_builtin_function or typeinfo_invoke.
Tbh I feel like implementing named args for invoke_builtin_function just to get rid of this workaround, but I've no idea how difficult it would be.
case DISPATCH_PROPERTYGET: { @@ -1163,13 +1168,17 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * return hres; } -static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller) +HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, + EXCEPINFO *ei, IServiceProvider *caller) { VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres; unsigned i, nconv = 0; IUnknown *iface; HRESULT hres; + if(!func->call_vtbl_off) + return typeinfo_invoke(This, func, flags, dp, res, ei);
if(dp->cNamedArgs) { FIXME("Named arguments not supported\n"); return E_NOTIMPL; @@ -1265,8 +1274,8 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP return V_ERROR(&vhres); } -static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, - EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT function_invoke(DispatchEx *This, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { HRESULT hres; @@ -1296,10 +1305,12 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, } } - if(func->call_vtbl_off) - hres = invoke_builtin_function(This, func, dp, res, caller); - else - hres = typeinfo_invoke(This, func, flags, dp, res, ei); + if(func->hook) { + hres = func->hook(This, func, lcid, flags, dp, res, ei, caller); + if(hres != S_FALSE) + break; + } + hres = invoke_builtin_function(This, func, flags, dp, res, ei, caller);
This seems to be a good place to call the hook, but could you just keep typeinfo_invoke call here and don't expose invoke_builtin_function?
But I need to expose it for hooks so they can forward to it. It's either that or I expose typeinfo_invoke. Keep in mind that, for hooks, the Dispatch object itself may not exist at all, we can't use it to look up the function, that's incorrect.
That's not the case right now, no, but it will be when I'll either implement function.apply/call (for all modes) or the proxy jscript implementation, in further patches.
Here's a future example:
f = elem.setAttribute; f.call(some_other_obj, "a", blah);
The hook needs to run on some_other_obj and stringify blah appropriately before calling the builtin function on some_other_obj. In fact, we won't have a DispatchEx at all, just a generic IDispatch with "some_other_obj".
I hoped that the result of your 'proxy' patches will be that those functions will be true JavaScript objects. It means that MSHTML's function objects will not be relevant in ES5 mode. Why do you still need them?
Yes, that's true, but I need a way to encapsulate a builtin function (including its hook) into a jscript function. Currently, I create a ProxyFunction that holds the func_info opaque pointer and an internal interface pointer that it uses to call into mshtml.
mshtml then uses this entry point to call the hook first, passing it the func_info and the 'this' dispatch object, and if no hook reverts back to invoke_builtin_function. Of course the hook also has to use invoke_builtin_function at some point, after massaging the args.
Either way, the point is that the hook *has* to be called on an arbitrary object, not the original dispatch it's from, so that's why I'm passing func_info_t to it, which is needed to be forwarded into invoke_builtin_function (or another wrapper).
On 12/4/21 12:20 AM, Gabriel Ivăncescu wrote:
On 03/12/2021 21:19, Jacek Caban wrote:
On 12/3/21 7:21 PM, Gabriel Ivăncescu wrote:
Hi Jacek,
Thanks for the review.
On 03/12/2021 16:35, Jacek Caban wrote:
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
This fixes a discrepancy between builtins called via a function dispatch object and others.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/mshtml/dispex.c | 37 ++++++++++++++++++++----------- dlls/mshtml/htmlelem.c | 7 +++--- dlls/mshtml/htmlevent.c | 10 ++++----- dlls/mshtml/mshtml_private.h | 6 +++-- dlls/mshtml/tests/documentmode.js | 14 +++++++++++- dlls/mshtml/xmlhttprequest.c | 5 ++--- 6 files changed, 50 insertions(+), 29 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 9f56a56..4ba00f8 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -49,7 +49,7 @@ typedef struct { VARIANT default_value; } func_arg_info_t; -typedef struct { +struct func_info_t { DISPID id; BSTR name; tid_t tid; @@ -63,7 +63,7 @@ typedef struct { VARTYPE prop_vt; VARTYPE *arg_types; func_arg_info_t *arg_info; -} func_info_t; +};
This could be kept local to dispex.c.
How are hooks supposed to call it then? It's opaque outside of dispex.c and just forwarded in hooks where necessary. Should I change the argument in hooks to void* then?
I see, the problematic case is when we call builtin, but the original property was overwritten. Still, I don't think it's the right to call the hook directly in function_value().
Why not? In fact, the hook *should* be called everytime before invoke_builtin_function (or typeinfo_invoke) except when it's called from the hook itself. It makes sense, since the hook is supposed to override *all* calls to the builtin in any other case.
Maybe I can use a helper function instead? Which calls the hook at the top and then invoke_builtin_function or typeinfo_invoke.
Tbh I feel like implementing named args for invoke_builtin_function just to get rid of this workaround, but I've no idea how difficult it would be.
I agree that the hook should be called somehow, but I don't agree that copy&paste is the right way to do it. Structuring code to workaround named arguments shortcomings also does not sound convincing.
case DISPATCH_PROPERTYGET: { @@ -1163,13 +1168,17 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * return hres; } -static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller) +HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, + EXCEPINFO *ei, IServiceProvider *caller) { VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres; unsigned i, nconv = 0; IUnknown *iface; HRESULT hres; + if(!func->call_vtbl_off) + return typeinfo_invoke(This, func, flags, dp, res, ei);
if(dp->cNamedArgs) { FIXME("Named arguments not supported\n"); return E_NOTIMPL; @@ -1265,8 +1274,8 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP return V_ERROR(&vhres); } -static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, - EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT function_invoke(DispatchEx *This, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { HRESULT hres; @@ -1296,10 +1305,12 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, } } - if(func->call_vtbl_off) - hres = invoke_builtin_function(This, func, dp, res, caller); - else - hres = typeinfo_invoke(This, func, flags, dp, res, ei); + if(func->hook) { + hres = func->hook(This, func, lcid, flags, dp, res, ei, caller); + if(hres != S_FALSE) + break; + } + hres = invoke_builtin_function(This, func, flags, dp, res, ei, caller);
This seems to be a good place to call the hook, but could you just keep typeinfo_invoke call here and don't expose invoke_builtin_function?
But I need to expose it for hooks so they can forward to it. It's either that or I expose typeinfo_invoke. Keep in mind that, for hooks, the Dispatch object itself may not exist at all, we can't use it to look up the function, that's incorrect.
That's not the case right now, no, but it will be when I'll either implement function.apply/call (for all modes) or the proxy jscript implementation, in further patches.
Here's a future example:
f = elem.setAttribute; f.call(some_other_obj, "a", blah);
The hook needs to run on some_other_obj and stringify blah appropriately before calling the builtin function on some_other_obj. In fact, we won't have a DispatchEx at all, just a generic IDispatch with "some_other_obj".
I hoped that the result of your 'proxy' patches will be that those functions will be true JavaScript objects. It means that MSHTML's function objects will not be relevant in ES5 mode. Why do you still need them? >
Yes, that's true, but I need a way to encapsulate a builtin function (including its hook) into a jscript function. Currently, I create a ProxyFunction that holds the func_info opaque pointer and an internal interface pointer that it uses to call into mshtml.
mshtml then uses this entry point to call the hook first, passing it the func_info and the 'this' dispatch object, and if no hook reverts back to invoke_builtin_function. Of course the hook also has to use invoke_builtin_function at some point, after massaging the args.
Either way, the point is that the hook *has* to be called on an arbitrary object, not the original dispatch it's from, so that's why I'm passing func_info_t to it, which is needed to be forwarded into invoke_builtin_function (or another wrapper).
I don't think we need that internal interface pointer. Did you consider something similar to storing a builtin function as (IID,DISPID) like I suggested earlier? This would not need any object representing functions on MSHTML side.
Jacek
On 04/12/2021 17:45, Jacek Caban wrote:
On 12/4/21 12:20 AM, Gabriel Ivăncescu wrote:
On 03/12/2021 21:19, Jacek Caban wrote:
On 12/3/21 7:21 PM, Gabriel Ivăncescu wrote:
Hi Jacek,
Thanks for the review.
On 03/12/2021 16:35, Jacek Caban wrote:
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
This fixes a discrepancy between builtins called via a function dispatch object and others.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/mshtml/dispex.c | 37 ++++++++++++++++++++----------- dlls/mshtml/htmlelem.c | 7 +++--- dlls/mshtml/htmlevent.c | 10 ++++----- dlls/mshtml/mshtml_private.h | 6 +++-- dlls/mshtml/tests/documentmode.js | 14 +++++++++++- dlls/mshtml/xmlhttprequest.c | 5 ++--- 6 files changed, 50 insertions(+), 29 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 9f56a56..4ba00f8 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -49,7 +49,7 @@ typedef struct { VARIANT default_value; } func_arg_info_t; -typedef struct { +struct func_info_t { DISPID id; BSTR name; tid_t tid; @@ -63,7 +63,7 @@ typedef struct { VARTYPE prop_vt; VARTYPE *arg_types; func_arg_info_t *arg_info; -} func_info_t; +};
This could be kept local to dispex.c.
How are hooks supposed to call it then? It's opaque outside of dispex.c and just forwarded in hooks where necessary. Should I change the argument in hooks to void* then?
I see, the problematic case is when we call builtin, but the original property was overwritten. Still, I don't think it's the right to call the hook directly in function_value().
Why not? In fact, the hook *should* be called everytime before invoke_builtin_function (or typeinfo_invoke) except when it's called from the hook itself. It makes sense, since the hook is supposed to override *all* calls to the builtin in any other case.
Maybe I can use a helper function instead? Which calls the hook at the top and then invoke_builtin_function or typeinfo_invoke.
Tbh I feel like implementing named args for invoke_builtin_function just to get rid of this workaround, but I've no idea how difficult it would be.
I agree that the hook should be called somehow, but I don't agree that copy&paste is the right way to do it. Structuring code to workaround named arguments shortcomings also does not sound convincing.
Oh I agree about that. My plan was to consolidate all of this into a single function (e.g. invoke_builtin_function), which does everything:
1) it calls the hook first, if any. 2) then, if it has no vtbl_off, it forwards to typeinfo_invoke. 3) otherwise, it does the things invoke_builtin_function does now.
The problem is that we have an existing test (line 1976 in script.c) that uses named args on a function dispatch object, so it will fail (that's because it has a vtbl_off, but now it calls typeinfo_invoke always). That said, it's really just DISPID_THIS, so I guess it shouldn't be too hard to handle it.
Worst case, I'll just add a FIXME if we have named args and fallback to typeinfo_invoke.
case DISPATCH_PROPERTYGET: { @@ -1163,13 +1168,17 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * return hres; } -static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller) +HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, + EXCEPINFO *ei, IServiceProvider *caller) { VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres; unsigned i, nconv = 0; IUnknown *iface; HRESULT hres; + if(!func->call_vtbl_off) + return typeinfo_invoke(This, func, flags, dp, res, ei);
if(dp->cNamedArgs) { FIXME("Named arguments not supported\n"); return E_NOTIMPL; @@ -1265,8 +1274,8 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP return V_ERROR(&vhres); } -static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, - EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT function_invoke(DispatchEx *This, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { HRESULT hres; @@ -1296,10 +1305,12 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, } } - if(func->call_vtbl_off) - hres = invoke_builtin_function(This, func, dp, res, caller); - else - hres = typeinfo_invoke(This, func, flags, dp, res, ei); + if(func->hook) { + hres = func->hook(This, func, lcid, flags, dp, res, ei, caller); + if(hres != S_FALSE) + break; + } + hres = invoke_builtin_function(This, func, flags, dp, res, ei, caller);
This seems to be a good place to call the hook, but could you just keep typeinfo_invoke call here and don't expose invoke_builtin_function?
But I need to expose it for hooks so they can forward to it. It's either that or I expose typeinfo_invoke. Keep in mind that, for hooks, the Dispatch object itself may not exist at all, we can't use it to look up the function, that's incorrect.
That's not the case right now, no, but it will be when I'll either implement function.apply/call (for all modes) or the proxy jscript implementation, in further patches.
Here's a future example:
f = elem.setAttribute; f.call(some_other_obj, "a", blah);
The hook needs to run on some_other_obj and stringify blah appropriately before calling the builtin function on some_other_obj. In fact, we won't have a DispatchEx at all, just a generic IDispatch with "some_other_obj".
I hoped that the result of your 'proxy' patches will be that those functions will be true JavaScript objects. It means that MSHTML's function objects will not be relevant in ES5 mode. Why do you still need them? >
Yes, that's true, but I need a way to encapsulate a builtin function (including its hook) into a jscript function. Currently, I create a ProxyFunction that holds the func_info opaque pointer and an internal interface pointer that it uses to call into mshtml.
mshtml then uses this entry point to call the hook first, passing it the func_info and the 'this' dispatch object, and if no hook reverts back to invoke_builtin_function. Of course the hook also has to use invoke_builtin_function at some point, after massaging the args.
Either way, the point is that the hook *has* to be called on an arbitrary object, not the original dispatch it's from, so that's why I'm passing func_info_t to it, which is needed to be forwarded into invoke_builtin_function (or another wrapper).
I don't think we need that internal interface pointer. Did you consider something similar to storing a builtin function as (IID,DISPID) like I suggested earlier? This would not need any object representing functions on MSHTML side.
Yes, I had it that way, but I had to change it to handle hooks. I don't actually use any object though, so it's not a problem. I just give the func_info_t as an opaque pointer to jscript, and a function pointer so that it knows what to call (in ProxyFunction_call) and pass it there.
The function pointer points to a function in mshtml that simply does the necessary things (typically, just invokes invoke_builtin_function, or for accessors, builtin_propget/put and the hooks). No actual object is used, but I still need the hooks patch of course.
On 12/5/21 5:54 PM, Gabriel Ivăncescu wrote:
>
This seems to be a good place to call the hook, but could you just keep typeinfo_invoke call here and don't expose invoke_builtin_function?
But I need to expose it for hooks so they can forward to it. It's either that or I expose typeinfo_invoke. Keep in mind that, for hooks, the Dispatch object itself may not exist at all, we can't use it to look up the function, that's incorrect.
That's not the case right now, no, but it will be when I'll either implement function.apply/call (for all modes) or the proxy jscript implementation, in further patches.
Here's a future example:
f = elem.setAttribute; f.call(some_other_obj, "a", blah);
The hook needs to run on some_other_obj and stringify blah appropriately before calling the builtin function on some_other_obj. In fact, we won't have a DispatchEx at all, just a generic IDispatch with "some_other_obj".
I hoped that the result of your 'proxy' patches will be that those functions will be true JavaScript objects. It means that MSHTML's function objects will not be relevant in ES5 mode. Why do you still need them? >
Yes, that's true, but I need a way to encapsulate a builtin function (including its hook) into a jscript function. Currently, I create a ProxyFunction that holds the func_info opaque pointer and an internal interface pointer that it uses to call into mshtml.
mshtml then uses this entry point to call the hook first, passing it the func_info and the 'this' dispatch object, and if no hook reverts back to invoke_builtin_function. Of course the hook also has to use invoke_builtin_function at some point, after massaging the args.
Either way, the point is that the hook *has* to be called on an arbitrary object, not the original dispatch it's from, so that's why I'm passing func_info_t to it, which is needed to be forwarded into invoke_builtin_function (or another wrapper).
I don't think we need that internal interface pointer. Did you consider something similar to storing a builtin function as (IID,DISPID) like I suggested earlier? This would not need any object representing functions on MSHTML side.
Yes, I had it that way, but I had to change it to handle hooks. I don't actually use any object though, so it's not a problem. I just give the func_info_t as an opaque pointer to jscript, and a function pointer so that it knows what to call (in ProxyFunction_call) and pass it there.
The function pointer points to a function in mshtml that simply does the necessary things (typically, just invokes invoke_builtin_function, or for accessors, builtin_propget/put and the hooks). No actual object is used, but I still need the hooks patch of course.
I still don't see why you need that. IID is enough to make sure that we're trying to call the function on the right object type. Once we know that the object type is right, DISPID already uniquely identifies func_info_t, which MSHTML may get as needed when the function is called.
Thanks,
Jacek
On 06/12/2021 16:48, Jacek Caban wrote:
On 12/5/21 5:54 PM, Gabriel Ivăncescu wrote:
>> > > > This seems to be a good place to call the hook, but could you > just keep typeinfo_invoke call here and don't expose > invoke_builtin_function? > >
But I need to expose it for hooks so they can forward to it. It's either that or I expose typeinfo_invoke. Keep in mind that, for hooks, the Dispatch object itself may not exist at all, we can't use it to look up the function, that's incorrect.
That's not the case right now, no, but it will be when I'll either implement function.apply/call (for all modes) or the proxy jscript implementation, in further patches.
Here's a future example:
f = elem.setAttribute; f.call(some_other_obj, "a", blah);
The hook needs to run on some_other_obj and stringify blah appropriately before calling the builtin function on some_other_obj. In fact, we won't have a DispatchEx at all, just a generic IDispatch with "some_other_obj".
I hoped that the result of your 'proxy' patches will be that those functions will be true JavaScript objects. It means that MSHTML's function objects will not be relevant in ES5 mode. Why do you still need them? >
Yes, that's true, but I need a way to encapsulate a builtin function (including its hook) into a jscript function. Currently, I create a ProxyFunction that holds the func_info opaque pointer and an internal interface pointer that it uses to call into mshtml.
mshtml then uses this entry point to call the hook first, passing it the func_info and the 'this' dispatch object, and if no hook reverts back to invoke_builtin_function. Of course the hook also has to use invoke_builtin_function at some point, after massaging the args.
Either way, the point is that the hook *has* to be called on an arbitrary object, not the original dispatch it's from, so that's why I'm passing func_info_t to it, which is needed to be forwarded into invoke_builtin_function (or another wrapper).
I don't think we need that internal interface pointer. Did you consider something similar to storing a builtin function as (IID,DISPID) like I suggested earlier? This would not need any object representing functions on MSHTML side.
Yes, I had it that way, but I had to change it to handle hooks. I don't actually use any object though, so it's not a problem. I just give the func_info_t as an opaque pointer to jscript, and a function pointer so that it knows what to call (in ProxyFunction_call) and pass it there.
The function pointer points to a function in mshtml that simply does the necessary things (typically, just invokes invoke_builtin_function, or for accessors, builtin_propget/put and the hooks). No actual object is used, but I still need the hooks patch of course.
I still don't see why you need that. IID is enough to make sure that we're trying to call the function on the right object type. Once we know that the object type is right, DISPID already uniquely identifies func_info_t, which MSHTML may get as needed when the function is called.
Well it's simpler to pass an opaque pointer that includes all the information rather than store two separate pieces and then have to look it up. The lookup would have to be done on mshtml side anyway (since it has func_info_t and hooks), so there's no advantage.
On 12/6/21 4:40 PM, Gabriel Ivăncescu wrote:
On 06/12/2021 16:48, Jacek Caban wrote:
On 12/5/21 5:54 PM, Gabriel Ivăncescu wrote:
>>> >> >> >> This seems to be a good place to call the hook, but could you >> just keep typeinfo_invoke call here and don't expose >> invoke_builtin_function? >> >> > > But I need to expose it for hooks so they can forward to it. > It's either that or I expose typeinfo_invoke. Keep in mind that, > for hooks, the Dispatch object itself may not exist at all, we > can't use it to look up the function, that's incorrect. > > That's not the case right now, no, but it will be when I'll > either implement function.apply/call (for all modes) or the > proxy jscript implementation, in further patches. > > Here's a future example: > > f = elem.setAttribute; > f.call(some_other_obj, "a", blah); > > The hook needs to run on some_other_obj and stringify blah > appropriately before calling the builtin function on > some_other_obj. In fact, we won't have a DispatchEx at all, just > a generic IDispatch with "some_other_obj".
I hoped that the result of your 'proxy' patches will be that those functions will be true JavaScript objects. It means that MSHTML's function objects will not be relevant in ES5 mode. Why do you still need them? >
Yes, that's true, but I need a way to encapsulate a builtin function (including its hook) into a jscript function. Currently, I create a ProxyFunction that holds the func_info opaque pointer and an internal interface pointer that it uses to call into mshtml.
mshtml then uses this entry point to call the hook first, passing it the func_info and the 'this' dispatch object, and if no hook reverts back to invoke_builtin_function. Of course the hook also has to use invoke_builtin_function at some point, after massaging the args.
Either way, the point is that the hook *has* to be called on an arbitrary object, not the original dispatch it's from, so that's why I'm passing func_info_t to it, which is needed to be forwarded into invoke_builtin_function (or another wrapper).
I don't think we need that internal interface pointer. Did you consider something similar to storing a builtin function as (IID,DISPID) like I suggested earlier? This would not need any object representing functions on MSHTML side.
Yes, I had it that way, but I had to change it to handle hooks. I don't actually use any object though, so it's not a problem. I just give the func_info_t as an opaque pointer to jscript, and a function pointer so that it knows what to call (in ProxyFunction_call) and pass it there.
The function pointer points to a function in mshtml that simply does the necessary things (typically, just invokes invoke_builtin_function, or for accessors, builtin_propget/put and the hooks). No actual object is used, but I still need the hooks patch of course.
I still don't see why you need that. IID is enough to make sure that we're trying to call the function on the right object type. Once we know that the object type is right, DISPID already uniquely identifies func_info_t, which MSHTML may get as needed when the function is called.
Well it's simpler to pass an opaque pointer that includes all the information rather than store two separate pieces and then have to look it up. The lookup would have to be done on mshtml side anyway (since it has func_info_t and hooks), so there's no advantage.
As long as you need a function object in mshtml, even if you don't call it an actual object, I don't see how it's simpler.
Also note that (at least currently, prototypes support may change it, but likely not) func_info_t, separated object types will use separated function infos. For example div element's function info for setAttribute is not the same as body element's. It happens to work if you use the other one, but that's now how it's meant to be used.
Jacek
On 07/12/2021 14:28, Jacek Caban wrote:
On 12/6/21 4:40 PM, Gabriel Ivăncescu wrote:
On 06/12/2021 16:48, Jacek Caban wrote:
On 12/5/21 5:54 PM, Gabriel Ivăncescu wrote:
>>>> >>> >>> >>> This seems to be a good place to call the hook, but could you >>> just keep typeinfo_invoke call here and don't expose >>> invoke_builtin_function? >>> >>> >> >> But I need to expose it for hooks so they can forward to it. >> It's either that or I expose typeinfo_invoke. Keep in mind that, >> for hooks, the Dispatch object itself may not exist at all, we >> can't use it to look up the function, that's incorrect. >> >> That's not the case right now, no, but it will be when I'll >> either implement function.apply/call (for all modes) or the >> proxy jscript implementation, in further patches. >> >> Here's a future example: >> >> f = elem.setAttribute; >> f.call(some_other_obj, "a", blah); >> >> The hook needs to run on some_other_obj and stringify blah >> appropriately before calling the builtin function on >> some_other_obj. In fact, we won't have a DispatchEx at all, just >> a generic IDispatch with "some_other_obj". > > > I hoped that the result of your 'proxy' patches will be that > those functions will be true JavaScript objects. It means that > MSHTML's function objects will not be relevant in ES5 mode. Why > do you still need them? > >
Yes, that's true, but I need a way to encapsulate a builtin function (including its hook) into a jscript function. Currently, I create a ProxyFunction that holds the func_info opaque pointer and an internal interface pointer that it uses to call into mshtml.
mshtml then uses this entry point to call the hook first, passing it the func_info and the 'this' dispatch object, and if no hook reverts back to invoke_builtin_function. Of course the hook also has to use invoke_builtin_function at some point, after massaging the args.
Either way, the point is that the hook *has* to be called on an arbitrary object, not the original dispatch it's from, so that's why I'm passing func_info_t to it, which is needed to be forwarded into invoke_builtin_function (or another wrapper).
I don't think we need that internal interface pointer. Did you consider something similar to storing a builtin function as (IID,DISPID) like I suggested earlier? This would not need any object representing functions on MSHTML side.
Yes, I had it that way, but I had to change it to handle hooks. I don't actually use any object though, so it's not a problem. I just give the func_info_t as an opaque pointer to jscript, and a function pointer so that it knows what to call (in ProxyFunction_call) and pass it there.
The function pointer points to a function in mshtml that simply does the necessary things (typically, just invokes invoke_builtin_function, or for accessors, builtin_propget/put and the hooks). No actual object is used, but I still need the hooks patch of course.
I still don't see why you need that. IID is enough to make sure that we're trying to call the function on the right object type. Once we know that the object type is right, DISPID already uniquely identifies func_info_t, which MSHTML may get as needed when the function is called.
Well it's simpler to pass an opaque pointer that includes all the information rather than store two separate pieces and then have to look it up. The lookup would have to be done on mshtml side anyway (since it has func_info_t and hooks), so there's no advantage.
As long as you need a function object in mshtml, even if you don't call it an actual object, I don't see how it's simpler.
I don't really use an object at all. Here's a rough sketch of how it is:
On mshtml side:
static HRESULT proxy_func_invoke(IDispatch *this_obj, void *func_info, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { func_info_t *func = func_info; return invoke_builtin_function(this_obj, func, DISPATCH_METHOD, dp, res, ei, caller); }
then in the proxy interface, we have a method that returns...
1) Address of proxy_func_invoke 2) The func_info_t
...back to jscript. Jscript uses it when creating a ProxyFunction and stores it inside, then during ProxyFunction_call:
ProxyFunction_call(...): { ... function->func.invoke(this_disp, function->func.info, ...); ... }
Where 'invoke' is the function pointer from mshtml (that points to proxy_func_invoke) and 'info' is the func_into_t from mshtml. jscript doesn't have to know anything about them.
The catch is that, of course, I need the *same* underlying mechanism as invoking a function object without proxies, so that's why I'm sending it now. It doesn't mean I actually use the function object, though, but since the function object needs the same mechanism more or less (and invoke_builtin_function fixed to call hooks and do everything on arbitrary "this" dispatches), it's an opportunity to fix it as well.
Of course, I also have to do this for accessors (which can be retrieved with getOwnPropertyDescriptor), but it's the same idea, nothing special.
Also note that (at least currently, prototypes support may change it, but likely not) func_info_t, separated object types will use separated function infos. For example div element's function info for setAttribute is not the same as body element's. It happens to work if you use the other one, but that's now how it's meant to be used.
Isn't that technically correct? Imagine, for a hypothetical example, that body element's setAttribute has a quirk on native, where div element's does not; i.e. it does not have the stringifying hook, where all other elements do. In this case, doing something like:
document.body.setAttribute.call(divElem, "attr", obj);
Needs to *not* stringify the obj value, because we are using body's setAttribute (which has the quirk) rather than divElem's, so in fact using func_info_t is more correct than IID/DIPSID pair, which would look it up on divElem and use the wrong setAttribute with the wrong hook.
This is of course, not a problem in practice, also because setAttribute is part of the prototype, so it's the same thing that's called.
That said there's some special cases (for example, style's prototype having a separate setAttribute, not using the element prototype chain), so I believe should we encounter such quirks in the future, it's still more correct anyway.
On 12/7/21 4:32 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 14:28, Jacek Caban wrote:
On 12/6/21 4:40 PM, Gabriel Ivăncescu wrote:
On 06/12/2021 16:48, Jacek Caban wrote:
On 12/5/21 5:54 PM, Gabriel Ivăncescu wrote:
>>>>> >>>> >>>> >>>> This seems to be a good place to call the hook, but could you >>>> just keep typeinfo_invoke call here and don't expose >>>> invoke_builtin_function? >>>> >>>> >>> >>> But I need to expose it for hooks so they can forward to it. >>> It's either that or I expose typeinfo_invoke. Keep in mind >>> that, for hooks, the Dispatch object itself may not exist at >>> all, we can't use it to look up the function, that's incorrect. >>> >>> That's not the case right now, no, but it will be when I'll >>> either implement function.apply/call (for all modes) or the >>> proxy jscript implementation, in further patches. >>> >>> Here's a future example: >>> >>> f = elem.setAttribute; >>> f.call(some_other_obj, "a", blah); >>> >>> The hook needs to run on some_other_obj and stringify blah >>> appropriately before calling the builtin function on >>> some_other_obj. In fact, we won't have a DispatchEx at all, >>> just a generic IDispatch with "some_other_obj". >> >> >> I hoped that the result of your 'proxy' patches will be that >> those functions will be true JavaScript objects. It means that >> MSHTML's function objects will not be relevant in ES5 mode. Why >> do you still need them? >> > > > Yes, that's true, but I need a way to encapsulate a builtin > function (including its hook) into a jscript function. > Currently, I create a ProxyFunction that holds the func_info > opaque pointer and an internal interface pointer that it uses to > call into mshtml. > > mshtml then uses this entry point to call the hook first, > passing it the func_info and the 'this' dispatch object, and if > no hook reverts back to invoke_builtin_function. Of course the > hook also has to use invoke_builtin_function at some point, > after massaging the args. > > Either way, the point is that the hook *has* to be called on an > arbitrary object, not the original dispatch it's from, so that's > why I'm passing func_info_t to it, which is needed to be > forwarded into invoke_builtin_function (or another wrapper).
I don't think we need that internal interface pointer. Did you consider something similar to storing a builtin function as (IID,DISPID) like I suggested earlier? This would not need any object representing functions on MSHTML side.
Yes, I had it that way, but I had to change it to handle hooks. I don't actually use any object though, so it's not a problem. I just give the func_info_t as an opaque pointer to jscript, and a function pointer so that it knows what to call (in ProxyFunction_call) and pass it there.
The function pointer points to a function in mshtml that simply does the necessary things (typically, just invokes invoke_builtin_function, or for accessors, builtin_propget/put and the hooks). No actual object is used, but I still need the hooks patch of course.
I still don't see why you need that. IID is enough to make sure that we're trying to call the function on the right object type. Once we know that the object type is right, DISPID already uniquely identifies func_info_t, which MSHTML may get as needed when the function is called.
Well it's simpler to pass an opaque pointer that includes all the information rather than store two separate pieces and then have to look it up. The lookup would have to be done on mshtml side anyway (since it has func_info_t and hooks), so there's no advantage.
As long as you need a function object in mshtml, even if you don't call it an actual object, I don't see how it's simpler.
I don't really use an object at all. Here's a rough sketch of how it is:
On mshtml side:
static HRESULT proxy_func_invoke(IDispatch *this_obj, void *func_info, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { func_info_t *func = func_info;
So why not get func_info_t from DISPID here? Of course, you also need to validate that we're called on the right type somewhere as well.
return invoke_builtin_function(this_obj, func, DISPATCH_METHOD, dp, res, ei, caller); }
then in the proxy interface, we have a method that returns...
- Address of proxy_func_invoke
- The func_info_t
...back to jscript. Jscript uses it when creating a ProxyFunction and stores it inside, then during ProxyFunction_call:
ProxyFunction_call(...): { ... function->func.invoke(this_disp, function->func.info, ...); ... }
Where 'invoke' is the function pointer from mshtml (that points to proxy_func_invoke) and 'info' is the func_into_t from mshtml. jscript doesn't have to know anything about them.
That sounds like a very ad-hoc way to expose it. MSHTML objects will need to expose some new interface anyway, right? Why not make it a part of that interface?
The catch is that, of course, I need the *same* underlying mechanism as invoking a function object without proxies, so that's why I'm sending it now. It doesn't mean I actually use the function object, though, but since the function object needs the same mechanism more or less (and invoke_builtin_function fixed to call hooks and do everything on arbitrary "this" dispatches), it's an opportunity to fix it as well.
Of course, I also have to do this for accessors (which can be retrieved with getOwnPropertyDescriptor), but it's the same idea, nothing special.
Also note that (at least currently, prototypes support may change it, but likely not) func_info_t, separated object types will use separated function infos. For example div element's function info for setAttribute is not the same as body element's. It happens to work if you use the other one, but that's now how it's meant to be used.
Isn't that technically correct? Imagine, for a hypothetical example, that body element's setAttribute has a quirk on native, where div element's does not; i.e. it does not have the stringifying hook, where all other elements do. In this case, doing something like:
document.body.setAttribute.call(divElem, "attr", obj);
Needs to *not* stringify the obj value, because we are using body's setAttribute (which has the quirk) rather than divElem's, so in fact using func_info_t is more correct than IID/DIPSID pair, which would look it up on divElem and use the wrong setAttribute with the wrong hook.
This is of course, not a problem in practice, also because setAttribute is part of the prototype, so it's the same thing that's called.
That said there's some special cases (for example, style's prototype having a separate setAttribute, not using the element prototype chain), so I believe should we encounter such quirks in the future, it's still more correct anyway.
That just doesn't make sense at all. Once we support prototypes document.body.setAttribute === document.createElement("div").setAttribute === document.head.__proto__.setAttribute === Element.setAttribute. It's one and the same function object, not separated quirk holders. Hooks are an implementation details of such abstract functions in context of a specific object type and there is nothing special about that. They are not a part of function object itself.
That all said, I'm not attached to representing those as DISPIDs. It just feels safe to continue using them here, but it's possible that something separated will be better at some point. Your current solution just exposes some MSHTML internals for no real need.
Jacek
On 07/12/2021 18:10, Jacek Caban wrote:
On 12/7/21 4:32 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 14:28, Jacek Caban wrote:
On 12/6/21 4:40 PM, Gabriel Ivăncescu wrote:
On 06/12/2021 16:48, Jacek Caban wrote:
On 12/5/21 5:54 PM, Gabriel Ivăncescu wrote:
>>>>>> >>>>> >>>>> >>>>> This seems to be a good place to call the hook, but could you >>>>> just keep typeinfo_invoke call here and don't expose >>>>> invoke_builtin_function? >>>>> >>>>> >>>> >>>> But I need to expose it for hooks so they can forward to it. >>>> It's either that or I expose typeinfo_invoke. Keep in mind >>>> that, for hooks, the Dispatch object itself may not exist at >>>> all, we can't use it to look up the function, that's incorrect. >>>> >>>> That's not the case right now, no, but it will be when I'll >>>> either implement function.apply/call (for all modes) or the >>>> proxy jscript implementation, in further patches. >>>> >>>> Here's a future example: >>>> >>>> f = elem.setAttribute; >>>> f.call(some_other_obj, "a", blah); >>>> >>>> The hook needs to run on some_other_obj and stringify blah >>>> appropriately before calling the builtin function on >>>> some_other_obj. In fact, we won't have a DispatchEx at all, >>>> just a generic IDispatch with "some_other_obj". >>> >>> >>> I hoped that the result of your 'proxy' patches will be that >>> those functions will be true JavaScript objects. It means that >>> MSHTML's function objects will not be relevant in ES5 mode. Why >>> do you still need them? >>> > >> >> Yes, that's true, but I need a way to encapsulate a builtin >> function (including its hook) into a jscript function. >> Currently, I create a ProxyFunction that holds the func_info >> opaque pointer and an internal interface pointer that it uses to >> call into mshtml. >> >> mshtml then uses this entry point to call the hook first, >> passing it the func_info and the 'this' dispatch object, and if >> no hook reverts back to invoke_builtin_function. Of course the >> hook also has to use invoke_builtin_function at some point, >> after massaging the args. >> >> Either way, the point is that the hook *has* to be called on an >> arbitrary object, not the original dispatch it's from, so that's >> why I'm passing func_info_t to it, which is needed to be >> forwarded into invoke_builtin_function (or another wrapper). > > > I don't think we need that internal interface pointer. Did you > consider something similar to storing a builtin function as > (IID,DISPID) like I suggested earlier? This would not need any > object representing functions on MSHTML side. >
Yes, I had it that way, but I had to change it to handle hooks. I don't actually use any object though, so it's not a problem. I just give the func_info_t as an opaque pointer to jscript, and a function pointer so that it knows what to call (in ProxyFunction_call) and pass it there.
The function pointer points to a function in mshtml that simply does the necessary things (typically, just invokes invoke_builtin_function, or for accessors, builtin_propget/put and the hooks). No actual object is used, but I still need the hooks patch of course.
I still don't see why you need that. IID is enough to make sure that we're trying to call the function on the right object type. Once we know that the object type is right, DISPID already uniquely identifies func_info_t, which MSHTML may get as needed when the function is called.
Well it's simpler to pass an opaque pointer that includes all the information rather than store two separate pieces and then have to look it up. The lookup would have to be done on mshtml side anyway (since it has func_info_t and hooks), so there's no advantage.
As long as you need a function object in mshtml, even if you don't call it an actual object, I don't see how it's simpler.
I don't really use an object at all. Here's a rough sketch of how it is:
On mshtml side:
static HRESULT proxy_func_invoke(IDispatch *this_obj, void *func_info, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { func_info_t *func = func_info;
So why not get func_info_t from DISPID here? Of course, you also need to validate that we're called on the right type somewhere as well.
return invoke_builtin_function(this_obj, func, DISPATCH_METHOD, dp, res, ei, caller); }
then in the proxy interface, we have a method that returns...
- Address of proxy_func_invoke
- The func_info_t
...back to jscript. Jscript uses it when creating a ProxyFunction and stores it inside, then during ProxyFunction_call:
ProxyFunction_call(...): { ... function->func.invoke(this_disp, function->func.info, ...); ... }
Where 'invoke' is the function pointer from mshtml (that points to proxy_func_invoke) and 'info' is the func_into_t from mshtml. jscript doesn't have to know anything about them.
That sounds like a very ad-hoc way to expose it. MSHTML objects will need to expose some new interface anyway, right? Why not make it a part of that interface?
The catch is that, of course, I need the *same* underlying mechanism as invoking a function object without proxies, so that's why I'm sending it now. It doesn't mean I actually use the function object, though, but since the function object needs the same mechanism more or less (and invoke_builtin_function fixed to call hooks and do everything on arbitrary "this" dispatches), it's an opportunity to fix it as well.
Of course, I also have to do this for accessors (which can be retrieved with getOwnPropertyDescriptor), but it's the same idea, nothing special.
Also note that (at least currently, prototypes support may change it, but likely not) func_info_t, separated object types will use separated function infos. For example div element's function info for setAttribute is not the same as body element's. It happens to work if you use the other one, but that's now how it's meant to be used.
Isn't that technically correct? Imagine, for a hypothetical example, that body element's setAttribute has a quirk on native, where div element's does not; i.e. it does not have the stringifying hook, where all other elements do. In this case, doing something like:
document.body.setAttribute.call(divElem, "attr", obj);
Needs to *not* stringify the obj value, because we are using body's setAttribute (which has the quirk) rather than divElem's, so in fact using func_info_t is more correct than IID/DIPSID pair, which would look it up on divElem and use the wrong setAttribute with the wrong hook.
This is of course, not a problem in practice, also because setAttribute is part of the prototype, so it's the same thing that's called.
That said there's some special cases (for example, style's prototype having a separate setAttribute, not using the element prototype chain), so I believe should we encounter such quirks in the future, it's still more correct anyway.
That just doesn't make sense at all. Once we support prototypes document.body.setAttribute === document.createElement("div").setAttribute === document.head.__proto__.setAttribute === Element.setAttribute. It's one and the same function object, not separated quirk holders. Hooks are an implementation details of such abstract functions in context of a specific object type and there is nothing special about that. They are not a part of function object itself.
I did mention the prototype means it is the same function object, I was using a hypothetical example with quirks. My point was that *if* they end up being different functions (for any reason), using func_info_t is more correct because it represents two different functions, with possibly two different hooks.
Don't get me wrong, I did not find yet a case where such a quirk exists, that's why I mentioned it's hypothetical. Although I did find some duplicated props in some places. Anyway I think it's more technically correct, and can be easier handled in the future *if* we find such quirks.
That all said, I'm not attached to representing those as DISPIDs. It just feels safe to continue using them here, but it's possible that something separated will be better at some point. Your current solution just exposes some MSHTML internals for no real need.
Well, they're opaque, so not exposed at all. It's pretty common to pass "context" or "user" pointers around in callbacks (which is what this is). Do you think renaming it to "context" is better then? jscript won't really care what it is, just has to pass it back to the callback.
On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote:
That just doesn't make sense at all. Once we support prototypes document.body.setAttribute === document.createElement("div").setAttribute === document.head.__proto__.setAttribute === Element.setAttribute. It's one and the same function object, not separated quirk holders. Hooks are an implementation details of such abstract functions in context of a specific object type and there is nothing special about that. They are not a part of function object itself.
I did mention the prototype means it is the same function object, I was using a hypothetical example with quirks. My point was that *if* they end up being different functions (for any reason), using func_info_t is more correct because it represents two different functions, with possibly two different hooks.
Don't get me wrong, I did not find yet a case where such a quirk exists, that's why I mentioned it's hypothetical. Although I did find some duplicated props in some places. Anyway I think it's more technically correct, and can be easier handled in the future *if* we find such quirks.
No, it's not correct. body element hooks from your example are free to cast 'this' object to HTMLBodyElement. If it did that, you'd end up casting div element object to HTMLBodyElement and likely crash.
That all said, I'm not attached to representing those as DISPIDs. It just feels safe to continue using them here, but it's possible that something separated will be better at some point. Your current solution just exposes some MSHTML internals for no real need.
Well, they're opaque, so not exposed at all. It's pretty common to pass "context" or "user" pointers around in callbacks (which is what this is). Do you think renaming it to "context" is better then? jscript won't really care what it is, just has to pass it back to the callback.
I think that it needs to fit the rest of the design, so I would need to see more of it to answer properly. It's not really something I expected. I imagined that the interface exposed by MSHTML object could look like this:
interface IJSDispatchHost
{
HRESULT getJSDispatch(IJSDispatch **p);
HRESULT setJSDispatch(IJSDispatch *jsdisp); // or maybe expose a constructor from the script engine itself and call it from MSHTML instead
HRESULT getOwnProperty( ... );
HRESULT call(DISPID dispid, unsigned int argc, VARIANT *argv, VARIANT *r);
// probably more
}
On top of that, you'd need a constructor for such wrapped objects, so another interface exposed by script engine itself will likely be needed. I don't see why you need anything else.
Thanks,
Jacek
On 07/12/2021 21:18, Jacek Caban wrote:
On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote:
That just doesn't make sense at all. Once we support prototypes document.body.setAttribute === document.createElement("div").setAttribute === document.head.__proto__.setAttribute === Element.setAttribute. It's one and the same function object, not separated quirk holders. Hooks are an implementation details of such abstract functions in context of a specific object type and there is nothing special about that. They are not a part of function object itself.
I did mention the prototype means it is the same function object, I was using a hypothetical example with quirks. My point was that *if* they end up being different functions (for any reason), using func_info_t is more correct because it represents two different functions, with possibly two different hooks.
Don't get me wrong, I did not find yet a case where such a quirk exists, that's why I mentioned it's hypothetical. Although I did find some duplicated props in some places. Anyway I think it's more technically correct, and can be easier handled in the future *if* we find such quirks.
No, it's not correct. body element hooks from your example are free to cast 'this' object to HTMLBodyElement. If it did that, you'd end up casting div element object to HTMLBodyElement and likely crash.
Oh I see what you mean now, but that's not an issue because the hooks behavior needs to change. I have patches for that of course, though I don't know if they'll make it before code freeze.
In short, the hooks will not take any DispatchEx* argument at all (in fact, you can't really know *what* object they are called on), but a generic IDispatch *this_obj arg.
This has nothing to do with the things mentioned above: it is much more general. Think of the following with an actual, real hook:
elem.setAttribute.call(arbitrary_dispatch_object, "A", "B");
As you can see we cannot guarantee that the hook itself is called on the respective element anymore, so casting it is already wrong. The correct thing would be to QueryInterface, or detect it some other ways (but that's not needed with the hooks we have so far).
But the point is: hooks need to operate on arbitrary this_obj IDispatch, and it's a general issue, not related to the proxy interface.
That all said, I'm not attached to representing those as DISPIDs. It just feels safe to continue using them here, but it's possible that something separated will be better at some point. Your current solution just exposes some MSHTML internals for no real need.
Well, they're opaque, so not exposed at all. It's pretty common to pass "context" or "user" pointers around in callbacks (which is what this is). Do you think renaming it to "context" is better then? jscript won't really care what it is, just has to pass it back to the callback.
I think that it needs to fit the rest of the design, so I would need to see more of it to answer properly. It's not really something I expected. I imagined that the interface exposed by MSHTML object could look like this:
interface IJSDispatchHost
{
HRESULT getJSDispatch(IJSDispatch **p);
HRESULT setJSDispatch(IJSDispatch *jsdisp); // or maybe expose a constructor from the script engine itself and call it from MSHTML instead
HRESULT getOwnProperty( ... );
HRESULT call(DISPID dispid, unsigned int argc, VARIANT *argv, VARIANT *r);
// probably more
}
On top of that, you'd need a constructor for such wrapped objects, so another interface exposed by script engine itself will likely be needed. I don't see why you need anything else.
Hmm. I have it quite different in that I create it on demand. Mshtml objects expose a specific interface that jscript queries, then jscript uses it for retrieving prop flags, invoking props, prop information (i.e. the callbacks mentioned), etc.
Basically, I use a similar model to how the PROP_BUILTIN props are implement in jscript right now, except that instead of using jscript builtin vtables, I use the interface exposed by mshtml, and mshtml does the rest of the job.
Sometimes mshtml calls back into jscript for specific things (mostly notifications), using a different interface but one that is always present in jscript (so mshtml knows once it's set up).
I got to the point where everything relevant, I believe, works like native. All constructors are the same, prototypes are similar (there's some undocumented stuff that I didn't bother with), prototype chains are the same (e.g. HTMLBodyElement->HTMLElement->Element->Node->Object) with same props exposed and all that in each prototype. I mentioned it because at least I know it works and isn't some dead end.
Anyway this is for later. :-)
On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 21:18, Jacek Caban wrote:
On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote:
That just doesn't make sense at all. Once we support prototypes document.body.setAttribute === document.createElement("div").setAttribute === document.head.__proto__.setAttribute === Element.setAttribute. It's one and the same function object, not separated quirk holders. Hooks are an implementation details of such abstract functions in context of a specific object type and there is nothing special about that. They are not a part of function object itself.
I did mention the prototype means it is the same function object, I was using a hypothetical example with quirks. My point was that *if* they end up being different functions (for any reason), using func_info_t is more correct because it represents two different functions, with possibly two different hooks.
Don't get me wrong, I did not find yet a case where such a quirk exists, that's why I mentioned it's hypothetical. Although I did find some duplicated props in some places. Anyway I think it's more technically correct, and can be easier handled in the future *if* we find such quirks.
No, it's not correct. body element hooks from your example are free to cast 'this' object to HTMLBodyElement. If it did that, you'd end up casting div element object to HTMLBodyElement and likely crash.
Oh I see what you mean now, but that's not an issue because the hooks behavior needs to change. I have patches for that of course, though I don't know if they'll make it before code freeze.
In short, the hooks will not take any DispatchEx* argument at all (in fact, you can't really know *what* object they are called on), but a generic IDispatch *this_obj arg.
This has nothing to do with the things mentioned above: it is much more general. Think of the following with an actual, real hook:
elem.setAttribute.call(arbitrary_dispatch_object, "A", "B");
As you can see we cannot guarantee that the hook itself is called on the respective element anymore, so casting it is already wrong. The correct thing would be to QueryInterface, or detect it some other ways (but that's not needed with the hooks we have so far).
But the point is: hooks need to operate on arbitrary this_obj IDispatch, and it's a general issue, not related to the proxy interface.
By the time the code reaches hooks, we should already have the type validated. I don't see why you need to change that.
Jacek
On 07/12/2021 22:34, Jacek Caban wrote:
On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 21:18, Jacek Caban wrote:
On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote:
That just doesn't make sense at all. Once we support prototypes document.body.setAttribute === document.createElement("div").setAttribute === document.head.__proto__.setAttribute === Element.setAttribute. It's one and the same function object, not separated quirk holders. Hooks are an implementation details of such abstract functions in context of a specific object type and there is nothing special about that. They are not a part of function object itself.
I did mention the prototype means it is the same function object, I was using a hypothetical example with quirks. My point was that *if* they end up being different functions (for any reason), using func_info_t is more correct because it represents two different functions, with possibly two different hooks.
Don't get me wrong, I did not find yet a case where such a quirk exists, that's why I mentioned it's hypothetical. Although I did find some duplicated props in some places. Anyway I think it's more technically correct, and can be easier handled in the future *if* we find such quirks.
No, it's not correct. body element hooks from your example are free to cast 'this' object to HTMLBodyElement. If it did that, you'd end up casting div element object to HTMLBodyElement and likely crash.
Oh I see what you mean now, but that's not an issue because the hooks behavior needs to change. I have patches for that of course, though I don't know if they'll make it before code freeze.
In short, the hooks will not take any DispatchEx* argument at all (in fact, you can't really know *what* object they are called on), but a generic IDispatch *this_obj arg.
This has nothing to do with the things mentioned above: it is much more general. Think of the following with an actual, real hook:
elem.setAttribute.call(arbitrary_dispatch_object, "A", "B");
As you can see we cannot guarantee that the hook itself is called on the respective element anymore, so casting it is already wrong. The correct thing would be to QueryInterface, or detect it some other ways (but that's not needed with the hooks we have so far).
But the point is: hooks need to operate on arbitrary this_obj IDispatch, and it's a general issue, not related to the proxy interface.
By the time the code reaches hooks, we should already have the type validated. I don't see why you need to change that.
Currently the type is validated during the builtin invocation, with QueryInterface. I think the hooks should be kept generic without type validation unless necessary (done within the hook itself) because:
1) We currently have no hooks requiring a *specific* type until it is forwarded (which already handles failure). Adding such validation would duplicate validation for no real gain.
2) Type checking within the hook is pretty simple. If we use a specific interface, QueryInterface() should do it. If we rely on a specific internal object layout, we can check the vtbl, because in the hook we know what vtbl we want. But checking this before calling the hook in a generic way seems non-trivial in comparison.
3) There's some special cases wrt the special constructors/prototypes (in compat modes) where all builtin accessors on them return undefined / do nothing (but only accessors). I currently use a hook to do that, which makes it trivial. They are already called on an "incompatible" object, though, because calling the prototype props *on the prototype* should fail in normal circumstances (error code depends on doc mode). So if I do type validation *before* the hook, the hook will never run in this case.
Maybe I'm missing something but what would be a way to validate the type in generic way then? If we are to check for the exact internal object layout, rather than just one exposing the interface, we'll have to check the vtbl. This is assuming hooks can use the internal object layout (and not just the interface, which the forwarded builtin does).
On 12/8/21 3:11 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 22:34, Jacek Caban wrote:
On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 21:18, Jacek Caban wrote:
On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote:
That just doesn't make sense at all. Once we support prototypes document.body.setAttribute === document.createElement("div").setAttribute === document.head.__proto__.setAttribute === Element.setAttribute. It's one and the same function object, not separated quirk holders. Hooks are an implementation details of such abstract functions in context of a specific object type and there is nothing special about that. They are not a part of function object itself.
I did mention the prototype means it is the same function object, I was using a hypothetical example with quirks. My point was that *if* they end up being different functions (for any reason), using func_info_t is more correct because it represents two different functions, with possibly two different hooks.
Don't get me wrong, I did not find yet a case where such a quirk exists, that's why I mentioned it's hypothetical. Although I did find some duplicated props in some places. Anyway I think it's more technically correct, and can be easier handled in the future *if* we find such quirks.
No, it's not correct. body element hooks from your example are free to cast 'this' object to HTMLBodyElement. If it did that, you'd end up casting div element object to HTMLBodyElement and likely crash.
Oh I see what you mean now, but that's not an issue because the hooks behavior needs to change. I have patches for that of course, though I don't know if they'll make it before code freeze.
In short, the hooks will not take any DispatchEx* argument at all (in fact, you can't really know *what* object they are called on), but a generic IDispatch *this_obj arg.
This has nothing to do with the things mentioned above: it is much more general. Think of the following with an actual, real hook:
elem.setAttribute.call(arbitrary_dispatch_object, "A", "B");
As you can see we cannot guarantee that the hook itself is called on the respective element anymore, so casting it is already wrong. The correct thing would be to QueryInterface, or detect it some other ways (but that's not needed with the hooks we have so far).
But the point is: hooks need to operate on arbitrary this_obj IDispatch, and it's a general issue, not related to the proxy interface.
By the time the code reaches hooks, we should already have the type validated. I don't see why you need to change that.
Currently the type is validated during the builtin invocation, with QueryInterface. I think the hooks should be kept generic without type validation unless necessary (done within the hook itself) because:
- We currently have no hooks requiring a *specific* type until it is
forwarded (which already handles failure). Adding such validation would duplicate validation for no real gain.
Hooks are part of function implementation and just like HTMLElement_setAttribute is free to cast iface to HTMLElement, its hook are free to do that too.
- Type checking within the hook is pretty simple. If we use a
specific interface, QueryInterface() should do it. If we rely on a specific internal object layout, we can check the vtbl, because in the hook we know what vtbl we want. But checking this before calling the hook in a generic way seems non-trivial in comparison.
Well, it's trivial. Just don't change them and it should be fine, they already have proper validation.
- There's some special cases wrt the special constructors/prototypes
(in compat modes) where all builtin accessors on them return undefined / do nothing (but only accessors). I currently use a hook to do that, which makes it trivial. They are already called on an "incompatible" object, though, because calling the prototype props *on the prototype* should fail in normal circumstances (error code depends on doc mode). So if I do type validation *before* the hook, the hook will never run in this case.
It seems to me like you're doing something else wrong, but it's hard to comment without seeing the code.
Maybe I'm missing something but what would be a way to validate the type in generic way then? If we are to check for the exact internal object layout, rather than just one exposing the interface, we'll have to check the vtbl. This is assuming hooks can use the internal object layout (and not just the interface, which the forwarded builtin does).
If we have (IID,DISPID), then you could just do that in jscript:
if (FAILED(IDispatch_QueryInterface(this_obj, iid, &iface)) //object has wrong type
IJSDispatch_call(this_obj, dispid, ....); // now we know that DISPID is valid in context of this object, call it
then in MSHTML, you can get func_info_t from dispid and be sure that it's the right func_info_t for this object, but that's an internal detail of mshtml/dispid.c and nothing to worry in the rest of the interface.
Jacek
On 08/12/2021 17:22, Jacek Caban wrote:
On 12/8/21 3:11 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 22:34, Jacek Caban wrote:
On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 21:18, Jacek Caban wrote:
On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote:
> That just doesn't make sense at all. Once we support prototypes > document.body.setAttribute === > document.createElement("div").setAttribute === > document.head.__proto__.setAttribute === Element.setAttribute. > It's one and the same function object, not separated quirk > holders. Hooks are an implementation details of such abstract > functions in context of a specific object type and there is > nothing special about that. They are not a part of function > object itself. >
I did mention the prototype means it is the same function object, I was using a hypothetical example with quirks. My point was that *if* they end up being different functions (for any reason), using func_info_t is more correct because it represents two different functions, with possibly two different hooks.
Don't get me wrong, I did not find yet a case where such a quirk exists, that's why I mentioned it's hypothetical. Although I did find some duplicated props in some places. Anyway I think it's more technically correct, and can be easier handled in the future *if* we find such quirks.
No, it's not correct. body element hooks from your example are free to cast 'this' object to HTMLBodyElement. If it did that, you'd end up casting div element object to HTMLBodyElement and likely crash.
Oh I see what you mean now, but that's not an issue because the hooks behavior needs to change. I have patches for that of course, though I don't know if they'll make it before code freeze.
In short, the hooks will not take any DispatchEx* argument at all (in fact, you can't really know *what* object they are called on), but a generic IDispatch *this_obj arg.
This has nothing to do with the things mentioned above: it is much more general. Think of the following with an actual, real hook:
elem.setAttribute.call(arbitrary_dispatch_object, "A", "B");
As you can see we cannot guarantee that the hook itself is called on the respective element anymore, so casting it is already wrong. The correct thing would be to QueryInterface, or detect it some other ways (but that's not needed with the hooks we have so far).
But the point is: hooks need to operate on arbitrary this_obj IDispatch, and it's a general issue, not related to the proxy interface.
By the time the code reaches hooks, we should already have the type validated. I don't see why you need to change that.
Currently the type is validated during the builtin invocation, with QueryInterface. I think the hooks should be kept generic without type validation unless necessary (done within the hook itself) because:
- We currently have no hooks requiring a *specific* type until it is
forwarded (which already handles failure). Adding such validation would duplicate validation for no real gain.
Hooks are part of function implementation and just like HTMLElement_setAttribute is free to cast iface to HTMLElement, its hook are free to do that too.
But HTMLElement_setAttribute is called after its interface is validated in typeinfo_invoke or invoke_builtin_function (QueryInterface). It knows that the object is proper because its vtbl implements setAttribute for that given object. If we have a different object exposing same interface, it has a different setAttribute in the vtbl for a different layout.
Hooks are called *before* that, for obvious reasons.
Of course, hooks will still be free to validate it themselves and then cast it, if needed, and it's not hard to do. But in case of hooks we can't just cast it to HTMLElement if the interface matches. There's no guarantee that the interface has the specific layout there. We have to check the vtbl.
For example, imagine there's an external object implementing that interface, but with a completely different layout (not HTMLElement's layout). It passes the interface test, you can call setAttribute on it just fine because it invokes its own setAttribute, and so on. But you can't cast it to HTMLElement* outside of the vtbl method.
And I don't see how we can do that in a generic way in a simple manner.
- Type checking within the hook is pretty simple. If we use a
specific interface, QueryInterface() should do it. If we rely on a specific internal object layout, we can check the vtbl, because in the hook we know what vtbl we want. But checking this before calling the hook in a generic way seems non-trivial in comparison.
Well, it's trivial. Just don't change them and it should be fine, they already have proper validation.
They don't though. They have validation right now because hooks do not work with arbitrary this_obj IDispatches, as it is now.
The only thing implemented currently is the function object dispatches for pre IE9 modes, which only have the "value" implemented, as in they act on the same object they were retrieved from.
apply or call are not implemented, and those *have* to work on arbitrary dispatch objects. It's the same with proxies of course, same thing applies. Both need changed hooks.
- There's some special cases wrt the special constructors/prototypes
(in compat modes) where all builtin accessors on them return undefined / do nothing (but only accessors). I currently use a hook to do that, which makes it trivial. They are already called on an "incompatible" object, though, because calling the prototype props *on the prototype* should fail in normal circumstances (error code depends on doc mode). So if I do type validation *before* the hook, the hook will never run in this case.
It seems to me like you're doing something else wrong, but it's hard to comment without seeing the code.
Maybe I'm missing something but what would be a way to validate the type in generic way then? If we are to check for the exact internal object layout, rather than just one exposing the interface, we'll have to check the vtbl. This is assuming hooks can use the internal object layout (and not just the interface, which the forwarded builtin does).
If we have (IID,DISPID), then you could just do that in jscript:
if (FAILED(IDispatch_QueryInterface(this_obj, iid, &iface)) //object has wrong type
IJSDispatch_call(this_obj, dispid, ....); // now we know that DISPID is valid in context of this object, call it
then in MSHTML, you can get func_info_t from dispid and be sure that it's the right func_info_t for this object, but that's an internal detail of mshtml/dispid.c and nothing to worry in the rest of the interface.
Well that doesn't really help at all, it's no different than now. With the way I have it, the interface is checked before it is used in mshtml side, not in jscript (already done in invoke_builtin_function for example, nothing extra).
The problem, of course, are hooks. When you call this function on an *arbitrary* dispatch, you have no guarantee that the object has the layout you want. You are *not* free to cast it to, for example, HTMLElement, even if it implements IID_IHTMLElement. The interface being present does not tell you anything about its layout, it's just an interface.
The actual methods implemented are allowed to, because they are called through the interface, so they know the object is the proper one. Hooks, however, are *not* part of the vtbl. They will be called on *any* object implementing this interface, whether it's HTMLElement or some other structure.
So they are not free to cast it to HTMLElement at all without validating the vtbl. And that's what I mean: the hooks should do this validation *if* they need to, within the hook, and accept and know that they will be called on arbitrary IDispatch objects. Frankly, I don't see a need for hooks to ever check the vtbl, but it's still an available option.
Otherwise, how exactly will we implement apply/call (proxy or not, doesn't matter) with proper hooks?
e.g. this_obj = IDispatch external object implementing IHTMLElement but not being ours, so not HTMLElement struct. How to call the setAttribute hook now?
I know it's not likely, but I'd like to implement this correctly, especially since it's not hard at all for hooks to accept arbitrary IDispatch objects.
On 12/8/21 5:02 PM, Gabriel Ivăncescu wrote:
On 08/12/2021 17:22, Jacek Caban wrote:
On 12/8/21 3:11 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 22:34, Jacek Caban wrote:
On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 21:18, Jacek Caban wrote:
On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote: >> That just doesn't make sense at all. Once we support prototypes >> document.body.setAttribute === >> document.createElement("div").setAttribute === >> document.head.__proto__.setAttribute === Element.setAttribute. >> It's one and the same function object, not separated quirk >> holders. Hooks are an implementation details of such abstract >> functions in context of a specific object type and there is >> nothing special about that. They are not a part of function >> object itself. >> > > I did mention the prototype means it is the same function > object, I was using a hypothetical example with quirks. My point > was that *if* they end up being different functions (for any > reason), using func_info_t is more correct because it represents > two different functions, with possibly two different hooks. > > Don't get me wrong, I did not find yet a case where such a quirk > exists, that's why I mentioned it's hypothetical. Although I did > find some duplicated props in some places. Anyway I think it's > more technically correct, and can be easier handled in the > future *if* we find such quirks.
No, it's not correct. body element hooks from your example are free to cast 'this' object to HTMLBodyElement. If it did that, you'd end up casting div element object to HTMLBodyElement and likely crash.
Oh I see what you mean now, but that's not an issue because the hooks behavior needs to change. I have patches for that of course, though I don't know if they'll make it before code freeze.
In short, the hooks will not take any DispatchEx* argument at all (in fact, you can't really know *what* object they are called on), but a generic IDispatch *this_obj arg.
This has nothing to do with the things mentioned above: it is much more general. Think of the following with an actual, real hook:
elem.setAttribute.call(arbitrary_dispatch_object, "A", "B");
As you can see we cannot guarantee that the hook itself is called on the respective element anymore, so casting it is already wrong. The correct thing would be to QueryInterface, or detect it some other ways (but that's not needed with the hooks we have so far).
But the point is: hooks need to operate on arbitrary this_obj IDispatch, and it's a general issue, not related to the proxy interface.
By the time the code reaches hooks, we should already have the type validated. I don't see why you need to change that.
Currently the type is validated during the builtin invocation, with QueryInterface. I think the hooks should be kept generic without type validation unless necessary (done within the hook itself) because:
- We currently have no hooks requiring a *specific* type until it
is forwarded (which already handles failure). Adding such validation would duplicate validation for no real gain.
Hooks are part of function implementation and just like HTMLElement_setAttribute is free to cast iface to HTMLElement, its hook are free to do that too.
But HTMLElement_setAttribute is called after its interface is validated in typeinfo_invoke or invoke_builtin_function (QueryInterface). It knows that the object is proper because its vtbl implements setAttribute for that given object. If we have a different object exposing same interface, it has a different setAttribute in the vtbl for a different layout.
Hooks are called *before* that, for obvious reasons.
They are retrieved from the current object info, so we know that they match info.
Of course, hooks will still be free to validate it themselves and then cast it, if needed, and it's not hard to do. But in case of hooks we can't just cast it to HTMLElement if the interface matches. There's no guarantee that the interface has the specific layout there. We have to check the vtbl.
They only reason hooks need to do that is because of your design choices and the above is one of the reasons why I think that some of those choices are wrong.
For example, imagine there's an external object implementing that interface, but with a completely different layout (not HTMLElement's layout). It passes the interface test, you can call setAttribute on it just fine because it invokes its own setAttribute, and so on. But you can't cast it to HTMLElement* outside of the vtbl method.
Sure and you shouldn't call HTMLElement's hook on such external object in the first place. They are HTMLElement's implementation detail and applying them to external implementation is wrong. If the external object has its own hooks, it's up to this object to call them.
And I don't see how we can do that in a generic way in a simple manner.
- Type checking within the hook is pretty simple. If we use a
specific interface, QueryInterface() should do it. If we rely on a specific internal object layout, we can check the vtbl, because in the hook we know what vtbl we want. But checking this before calling the hook in a generic way seems non-trivial in comparison.
Well, it's trivial. Just don't change them and it should be fine, they already have proper validation.
They don't though. They have validation right now because hooks do not work with arbitrary this_obj IDispatches, as it is now.
The fact that they don't need explicit validation is not an accident, that's how the code is structured.
The only thing implemented currently is the function object dispatches for pre IE9 modes, which only have the "value" implemented, as in they act on the same object they were retrieved from.
apply or call are not implemented, and those *have* to work on arbitrary dispatch objects. It's the same with proxies of course, same thing applies. Both need changed hooks.
Again: no, they don't. They need that change only because of your other choices.
- There's some special cases wrt the special
constructors/prototypes (in compat modes) where all builtin accessors on them return undefined / do nothing (but only accessors). I currently use a hook to do that, which makes it trivial. They are already called on an "incompatible" object, though, because calling the prototype props *on the prototype* should fail in normal circumstances (error code depends on doc mode). So if I do type validation *before* the hook, the hook will never run in this case.
It seems to me like you're doing something else wrong, but it's hard to comment without seeing the code.
Maybe I'm missing something but what would be a way to validate the type in generic way then? If we are to check for the exact internal object layout, rather than just one exposing the interface, we'll have to check the vtbl. This is assuming hooks can use the internal object layout (and not just the interface, which the forwarded builtin does).
If we have (IID,DISPID), then you could just do that in jscript:
if (FAILED(IDispatch_QueryInterface(this_obj, iid, &iface)) //object has wrong type
IJSDispatch_call(this_obj, dispid, ....); // now we know that DISPID is valid in context of this object, call it
then in MSHTML, you can get func_info_t from dispid and be sure that it's the right func_info_t for this object, but that's an internal detail of mshtml/dispid.c and nothing to worry in the rest of the interface.
Well that doesn't really help at all, it's no different than now. With the way I have it, the interface is checked before it is used in mshtml side, not in jscript (already done in invoke_builtin_function for example, nothing extra).
The problem, of course, are hooks. When you call this function on an *arbitrary* dispatch, you have no guarantee that the object has the layout you want. You are *not* free to cast it to, for example, HTMLElement, even if it implements IID_IHTMLElement. The interface being present does not tell you anything about its layout, it's just an interface.
The actual methods implemented are allowed to, because they are called through the interface, so they know the object is the proper one. Hooks, however, are *not* part of the vtbl. They will be called on *any* object implementing this interface, whether it's HTMLElement or some other structure.
So they are not free to cast it to HTMLElement at all without validating the vtbl. And that's what I mean: the hooks should do this validation *if* they need to, within the hook, and accept and know that they will be called on arbitrary IDispatch objects. Frankly, I don't see a need for hooks to ever check the vtbl, but it's still an available option.
Otherwise, how exactly will we implement apply/call (proxy or not, doesn't matter) with proper hooks?
e.g. this_obj = IDispatch external object implementing IHTMLElement but not being ours, so not HTMLElement struct. How to call the setAttribute hook now?
Again, don't call those hooks on arbitrary objects at all. This hook is irrelevant in this case.
Jacek
On 08/12/2021 18:28, Jacek Caban wrote:
On 12/8/21 5:02 PM, Gabriel Ivăncescu wrote:
On 08/12/2021 17:22, Jacek Caban wrote:
On 12/8/21 3:11 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 22:34, Jacek Caban wrote:
On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 21:18, Jacek Caban wrote: > On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote: >>> That just doesn't make sense at all. Once we support prototypes >>> document.body.setAttribute === >>> document.createElement("div").setAttribute === >>> document.head.__proto__.setAttribute === Element.setAttribute. >>> It's one and the same function object, not separated quirk >>> holders. Hooks are an implementation details of such abstract >>> functions in context of a specific object type and there is >>> nothing special about that. They are not a part of function >>> object itself. >>> >> >> I did mention the prototype means it is the same function >> object, I was using a hypothetical example with quirks. My point >> was that *if* they end up being different functions (for any >> reason), using func_info_t is more correct because it represents >> two different functions, with possibly two different hooks. >> >> Don't get me wrong, I did not find yet a case where such a quirk >> exists, that's why I mentioned it's hypothetical. Although I did >> find some duplicated props in some places. Anyway I think it's >> more technically correct, and can be easier handled in the >> future *if* we find such quirks. > > > No, it's not correct. body element hooks from your example are > free to cast 'this' object to HTMLBodyElement. If it did that, > you'd end up casting div element object to HTMLBodyElement and > likely crash. >
Oh I see what you mean now, but that's not an issue because the hooks behavior needs to change. I have patches for that of course, though I don't know if they'll make it before code freeze.
In short, the hooks will not take any DispatchEx* argument at all (in fact, you can't really know *what* object they are called on), but a generic IDispatch *this_obj arg.
This has nothing to do with the things mentioned above: it is much more general. Think of the following with an actual, real hook:
elem.setAttribute.call(arbitrary_dispatch_object, "A", "B");
As you can see we cannot guarantee that the hook itself is called on the respective element anymore, so casting it is already wrong. The correct thing would be to QueryInterface, or detect it some other ways (but that's not needed with the hooks we have so far).
But the point is: hooks need to operate on arbitrary this_obj IDispatch, and it's a general issue, not related to the proxy interface.
By the time the code reaches hooks, we should already have the type validated. I don't see why you need to change that.
Currently the type is validated during the builtin invocation, with QueryInterface. I think the hooks should be kept generic without type validation unless necessary (done within the hook itself) because:
- We currently have no hooks requiring a *specific* type until it
is forwarded (which already handles failure). Adding such validation would duplicate validation for no real gain.
Hooks are part of function implementation and just like HTMLElement_setAttribute is free to cast iface to HTMLElement, its hook are free to do that too.
But HTMLElement_setAttribute is called after its interface is validated in typeinfo_invoke or invoke_builtin_function (QueryInterface). It knows that the object is proper because its vtbl implements setAttribute for that given object. If we have a different object exposing same interface, it has a different setAttribute in the vtbl for a different layout.
Hooks are called *before* that, for obvious reasons.
They are retrieved from the current object info, so we know that they match info.
Of course, hooks will still be free to validate it themselves and then cast it, if needed, and it's not hard to do. But in case of hooks we can't just cast it to HTMLElement if the interface matches. There's no guarantee that the interface has the specific layout there. We have to check the vtbl.
They only reason hooks need to do that is because of your design choices and the above is one of the reasons why I think that some of those choices are wrong.
For example, imagine there's an external object implementing that interface, but with a completely different layout (not HTMLElement's layout). It passes the interface test, you can call setAttribute on it just fine because it invokes its own setAttribute, and so on. But you can't cast it to HTMLElement* outside of the vtbl method.
Sure and you shouldn't call HTMLElement's hook on such external object in the first place. They are HTMLElement's implementation detail and applying them to external implementation is wrong. If the external object has its own hooks, it's up to this object to call them.
I see. But to have a generic validation, this would require to somehow store the object's vtbl address in the info so it can be validated with it and then skip the hook otherwise. The IID is obviously not sufficient since that only checks for the exposed interface.
Alternatively, we could just *always* call the hook like in my design, and validate it and skip it in the hook if the vtbl doesn't match (i.e. the hook itself does the validation). This would also work for the weird prototypes later where the hooks return undefined without validation, otherwise I'd have to add a special casing...
Which one do you prefer?
BTW, sorry forgot to mention, but all of this doesn't have much to do with the current patches I sent. If possible I'd like to get them in before code freeze since they change a lot (especially the jscript ones), and would massively reduce the diffs for my patches.
It's for later, of course.
On 12/8/21 7:11 PM, Gabriel Ivăncescu wrote:
BTW, sorry forgot to mention, but all of this doesn't have much to do with the current patches I sent. If possible I'd like to get them in before code freeze since they change a lot (especially the jscript ones), and would massively reduce the diffs for my patches.
Well, patch 2 from the series changes func_info_t in a direction that we discuss in this thread.
Jacek
On 12/8/21 7:05 PM, Gabriel Ivăncescu wrote:
On 08/12/2021 18:28, Jacek Caban wrote:
On 12/8/21 5:02 PM, Gabriel Ivăncescu wrote:
On 08/12/2021 17:22, Jacek Caban wrote:
On 12/8/21 3:11 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 22:34, Jacek Caban wrote:
On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote: > On 07/12/2021 21:18, Jacek Caban wrote: >> On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote: >>>> That just doesn't make sense at all. Once we support >>>> prototypes document.body.setAttribute === >>>> document.createElement("div").setAttribute === >>>> document.head.__proto__.setAttribute === >>>> Element.setAttribute. It's one and the same function object, >>>> not separated quirk holders. Hooks are an implementation >>>> details of such abstract functions in context of a specific >>>> object type and there is nothing special about that. They are >>>> not a part of function object itself. >>>> >>> >>> I did mention the prototype means it is the same function >>> object, I was using a hypothetical example with quirks. My >>> point was that *if* they end up being different functions (for >>> any reason), using func_info_t is more correct because it >>> represents two different functions, with possibly two >>> different hooks. >>> >>> Don't get me wrong, I did not find yet a case where such a >>> quirk exists, that's why I mentioned it's hypothetical. >>> Although I did find some duplicated props in some places. >>> Anyway I think it's more technically correct, and can be >>> easier handled in the future *if* we find such quirks. >> >> >> No, it's not correct. body element hooks from your example are >> free to cast 'this' object to HTMLBodyElement. If it did that, >> you'd end up casting div element object to HTMLBodyElement and >> likely crash. >> > > Oh I see what you mean now, but that's not an issue because the > hooks behavior needs to change. I have patches for that of > course, though I don't know if they'll make it before code freeze. > > In short, the hooks will not take any DispatchEx* argument at > all (in fact, you can't really know *what* object they are > called on), but a generic IDispatch *this_obj arg. > > This has nothing to do with the things mentioned above: it is > much more general. Think of the following with an actual, real > hook: > > elem.setAttribute.call(arbitrary_dispatch_object, "A", "B"); > > As you can see we cannot guarantee that the hook itself is > called on the respective element anymore, so casting it is > already wrong. The correct thing would be to QueryInterface, or > detect it some other ways (but that's not needed with the hooks > we have so far). > > But the point is: hooks need to operate on arbitrary this_obj > IDispatch, and it's a general issue, not related to the proxy > interface.
By the time the code reaches hooks, we should already have the type validated. I don't see why you need to change that.
Currently the type is validated during the builtin invocation, with QueryInterface. I think the hooks should be kept generic without type validation unless necessary (done within the hook itself) because:
- We currently have no hooks requiring a *specific* type until it
is forwarded (which already handles failure). Adding such validation would duplicate validation for no real gain.
Hooks are part of function implementation and just like HTMLElement_setAttribute is free to cast iface to HTMLElement, its hook are free to do that too.
But HTMLElement_setAttribute is called after its interface is validated in typeinfo_invoke or invoke_builtin_function (QueryInterface). It knows that the object is proper because its vtbl implements setAttribute for that given object. If we have a different object exposing same interface, it has a different setAttribute in the vtbl for a different layout.
Hooks are called *before* that, for obvious reasons.
They are retrieved from the current object info, so we know that they match info.
Of course, hooks will still be free to validate it themselves and then cast it, if needed, and it's not hard to do. But in case of hooks we can't just cast it to HTMLElement if the interface matches. There's no guarantee that the interface has the specific layout there. We have to check the vtbl.
They only reason hooks need to do that is because of your design choices and the above is one of the reasons why I think that some of those choices are wrong.
For example, imagine there's an external object implementing that interface, but with a completely different layout (not HTMLElement's layout). It passes the interface test, you can call setAttribute on it just fine because it invokes its own setAttribute, and so on. But you can't cast it to HTMLElement* outside of the vtbl method.
Sure and you shouldn't call HTMLElement's hook on such external object in the first place. They are HTMLElement's implementation detail and applying them to external implementation is wrong. If the external object has its own hooks, it's up to this object to call them.
I see. But to have a generic validation, this would require to somehow store the object's vtbl address in the info so it can be validated with it and then skip the hook otherwise. The IID is obviously not sufficient since that only checks for the exposed interface.
Alternatively, we could just *always* call the hook like in my design, and validate it and skip it in the hook if the vtbl doesn't match (i.e. the hook itself does the validation). This would also work for the weird prototypes later where the hooks return undefined without validation, otherwise I'd have to add a special casing...
Which one do you prefer?
The problem exists only because you expose functions as func_info_t (even if you make it an opaque; it's important how you treat them, not what's in the header). If you didn't do that, the problem wouldn't exist in the first place. That's one of the reasons why I'd like to revisit that decision.
Jacek
On 08/12/2021 20:39, Jacek Caban wrote:
On 12/8/21 7:05 PM, Gabriel Ivăncescu wrote:
On 08/12/2021 18:28, Jacek Caban wrote:
On 12/8/21 5:02 PM, Gabriel Ivăncescu wrote:
On 08/12/2021 17:22, Jacek Caban wrote:
On 12/8/21 3:11 PM, Gabriel Ivăncescu wrote:
On 07/12/2021 22:34, Jacek Caban wrote: > On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote: >> On 07/12/2021 21:18, Jacek Caban wrote: >>> On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote: >>>>> That just doesn't make sense at all. Once we support >>>>> prototypes document.body.setAttribute === >>>>> document.createElement("div").setAttribute === >>>>> document.head.__proto__.setAttribute === >>>>> Element.setAttribute. It's one and the same function object, >>>>> not separated quirk holders. Hooks are an implementation >>>>> details of such abstract functions in context of a specific >>>>> object type and there is nothing special about that. They are >>>>> not a part of function object itself. >>>>> >>>> >>>> I did mention the prototype means it is the same function >>>> object, I was using a hypothetical example with quirks. My >>>> point was that *if* they end up being different functions (for >>>> any reason), using func_info_t is more correct because it >>>> represents two different functions, with possibly two >>>> different hooks. >>>> >>>> Don't get me wrong, I did not find yet a case where such a >>>> quirk exists, that's why I mentioned it's hypothetical. >>>> Although I did find some duplicated props in some places. >>>> Anyway I think it's more technically correct, and can be >>>> easier handled in the future *if* we find such quirks. >>> >>> >>> No, it's not correct. body element hooks from your example are >>> free to cast 'this' object to HTMLBodyElement. If it did that, >>> you'd end up casting div element object to HTMLBodyElement and >>> likely crash. >>> >> >> Oh I see what you mean now, but that's not an issue because the >> hooks behavior needs to change. I have patches for that of >> course, though I don't know if they'll make it before code freeze. >> >> In short, the hooks will not take any DispatchEx* argument at >> all (in fact, you can't really know *what* object they are >> called on), but a generic IDispatch *this_obj arg. >> >> This has nothing to do with the things mentioned above: it is >> much more general. Think of the following with an actual, real >> hook: >> >> elem.setAttribute.call(arbitrary_dispatch_object, "A", "B"); >> >> As you can see we cannot guarantee that the hook itself is >> called on the respective element anymore, so casting it is >> already wrong. The correct thing would be to QueryInterface, or >> detect it some other ways (but that's not needed with the hooks >> we have so far). >> >> But the point is: hooks need to operate on arbitrary this_obj >> IDispatch, and it's a general issue, not related to the proxy >> interface. > > > > By the time the code reaches hooks, we should already have the > type validated. I don't see why you need to change that. > Currently the type is validated during the builtin invocation, with QueryInterface. I think the hooks should be kept generic without type validation unless necessary (done within the hook itself) because:
- We currently have no hooks requiring a *specific* type until it
is forwarded (which already handles failure). Adding such validation would duplicate validation for no real gain.
Hooks are part of function implementation and just like HTMLElement_setAttribute is free to cast iface to HTMLElement, its hook are free to do that too.
But HTMLElement_setAttribute is called after its interface is validated in typeinfo_invoke or invoke_builtin_function (QueryInterface). It knows that the object is proper because its vtbl implements setAttribute for that given object. If we have a different object exposing same interface, it has a different setAttribute in the vtbl for a different layout.
Hooks are called *before* that, for obvious reasons.
They are retrieved from the current object info, so we know that they match info.
Of course, hooks will still be free to validate it themselves and then cast it, if needed, and it's not hard to do. But in case of hooks we can't just cast it to HTMLElement if the interface matches. There's no guarantee that the interface has the specific layout there. We have to check the vtbl.
They only reason hooks need to do that is because of your design choices and the above is one of the reasons why I think that some of those choices are wrong.
For example, imagine there's an external object implementing that interface, but with a completely different layout (not HTMLElement's layout). It passes the interface test, you can call setAttribute on it just fine because it invokes its own setAttribute, and so on. But you can't cast it to HTMLElement* outside of the vtbl method.
Sure and you shouldn't call HTMLElement's hook on such external object in the first place. They are HTMLElement's implementation detail and applying them to external implementation is wrong. If the external object has its own hooks, it's up to this object to call them.
I see. But to have a generic validation, this would require to somehow store the object's vtbl address in the info so it can be validated with it and then skip the hook otherwise. The IID is obviously not sufficient since that only checks for the exposed interface.
Alternatively, we could just *always* call the hook like in my design, and validate it and skip it in the hook if the vtbl doesn't match (i.e. the hook itself does the validation). This would also work for the weird prototypes later where the hooks return undefined without validation, otherwise I'd have to add a special casing...
Which one do you prefer?
The problem exists only because you expose functions as func_info_t (even if you make it an opaque; it's important how you treat them, not what's in the header). If you didn't do that, the problem wouldn't exist in the first place. That's one of the reasons why I'd like to revisit that decision.
Jacek
Wait, how am I supposed to forward the hook then? (in the existing patches I mean, not in the future patches). The func_info_t now is used just to forward it as needed, it assumes the hook is already validated, so there shouldn't be any problem...?
The previous method with InvokeEx is wrong—it will call the function dispatch object in that slot. For example:
var func = elem.setAttribute; elem.setAttribute = function() {}; func("id", "foo");
The hook will end up calling the empty function which is clearly wrong.
On the other future note, I still don't see how the problem wouldn't exist without func_info_t. Again, each and every hook/InvokeEx will have to handle an arbitrary this pointer for jscript to work properly in the future. Now, let's say we have an IHTMLElement external obj that's not our implementation passed as "this".
How does IID help? We'll query for it and it returns success, it doesn't mean it's ours. We *still* have to check the vtbl.
func_info_t also holds the IID, plus the DISPID and everything else, so it's already a superset of the DISPID/IID pair so it clearly cannot be any worse in terms of functionality. Am I missing something?
Thinking about this overnight, there's only one other idea I could come up with to forward it properly: have the hook modify the DISPPARAMS in-place as required, and either return a special value to indicate this, or return S_FALSE and we check if they were modified (to free them after the call).
I'm not sure how much of a hack this is, though. It sounds a bit ugly to me, but it avoids passing a func_info_t, so if it's what it takes...
BTW how about the jscript patches? They're technically not dependent on these ones, and those are the ones I mainly would like before code freeze since they have huge changes (and implications for proxies), please don't let this hook thing stay in the way of them getting reviewed or upstreamed.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=103322
Your paranoid android.
=== w8adm (32 bit report) ===
mshtml: events.c:1089: Test failed: unexpected call img_onerror events: Timeout
=== w10pro64_zh_CN (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
And get rid of vdisp_t since it's no longer needed.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/activex.c | 2 +- dlls/jscript/array.c | 84 ++++++++-------- dlls/jscript/bool.c | 22 ++--- dlls/jscript/date.c | 199 +++++++++++++++++++------------------- dlls/jscript/dispex.c | 17 +--- dlls/jscript/enumerator.c | 28 +++--- dlls/jscript/error.c | 25 ++--- dlls/jscript/function.c | 51 ++++------ dlls/jscript/global.c | 34 +++---- dlls/jscript/jscript.h | 75 +------------- dlls/jscript/json.c | 4 +- dlls/jscript/jsregexp.c | 32 +++--- dlls/jscript/math.c | 36 +++---- dlls/jscript/number.c | 34 +++---- dlls/jscript/object.c | 97 +++++++++++-------- dlls/jscript/set.c | 81 ++++++++++------ dlls/jscript/string.c | 180 +++++++++++++++++----------------- dlls/jscript/vbarray.c | 24 ++--- 18 files changed, 482 insertions(+), 543 deletions(-)
diff --git a/dlls/jscript/activex.c b/dlls/jscript/activex.c index 80a89b5..c84f269 100644 --- a/dlls/jscript/activex.c +++ b/dlls/jscript/activex.c @@ -138,7 +138,7 @@ static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid) return obj; }
-static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT ActiveXObject_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t * progid_str; diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 5f61f99..3ebc623 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -37,14 +37,10 @@ static inline ArrayInstance *array_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, ArrayInstance, dispex); }
-static inline ArrayInstance *array_from_vdisp(vdisp_t *vdisp) +static inline ArrayInstance *array_this(jsval_t vthis) { - return array_from_jsdisp(vdisp->u.jsdisp); -} - -static inline ArrayInstance *array_this(vdisp_t *jsthis) -{ - return is_vclass(jsthis, JSCLASS_ARRAY) ? array_from_vdisp(jsthis) : NULL; + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_ARRAY)) ? array_from_jsdisp(jsdisp) : NULL; }
unsigned array_get_length(jsdisp_t *array) @@ -53,33 +49,30 @@ unsigned array_get_length(jsdisp_t *array) return array_from_jsdisp(array)->length; }
-static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsdisp_t **jsthis, DWORD *ret) +static HRESULT get_length(script_ctx_t *ctx, jsval_t vthis, jsdisp_t **jsthis, DWORD *ret) { - ArrayInstance *array; + jsdisp_t *jsdisp; jsval_t val; HRESULT hres;
- array = array_this(vdisp); - if(array) { - *jsthis = &array->dispex; - *ret = array->length; + if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + if(!(jsdisp = to_jsdisp(get_object(vthis)))) + return JS_E_JSCRIPT_EXPECTED; + *jsthis = jsdisp; + + if(is_class(jsdisp, JSCLASS_ARRAY)) { + *ret = array_from_jsdisp(jsdisp)->length; return S_OK; }
- if(!is_jsdisp(vdisp)) - return JS_E_JSCRIPT_EXPECTED; - - hres = jsdisp_propget_name(vdisp->u.jsdisp, L"length", &val); + hres = jsdisp_propget_name(jsdisp, L"length", &val); if(FAILED(hres)) return hres;
hres = to_uint32(ctx, val, ret); jsval_release(val); - if(FAILED(hres)) - return hres; - - *jsthis = vdisp->u.jsdisp; - return S_OK; + return hres; }
static HRESULT set_length(jsdisp_t *obj, DWORD length) @@ -183,20 +176,25 @@ static HRESULT concat_obj(jsdisp_t *array, IDispatch *obj, DWORD *len) return jsdisp_propput_idx(array, (*len)++, jsval_disp(obj)); }
-static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_concat(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + IDispatch *jsthis; jsdisp_t *ret; DWORD len = 0; HRESULT hres;
TRACE("\n");
+ if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + jsthis = get_object(vthis); + hres = create_array(ctx, 0, &ret); if(FAILED(hres)) return hres;
- hres = concat_obj(ret, jsthis->u.disp, &len); + hres = concat_obj(ret, jsthis, &len); if(SUCCEEDED(hres)) { DWORD i;
@@ -310,7 +308,7 @@ static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, cons }
/* ECMA-262 3rd Edition 15.4.4.5 */ -static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_join(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; @@ -341,7 +339,7 @@ static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigne return hres; }
-static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_pop(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; @@ -391,7 +389,7 @@ static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned }
/* ECMA-262 3rd Edition 15.4.4.7 */ -static HRESULT Array_push(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_push(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; @@ -420,7 +418,7 @@ static HRESULT Array_push(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigne return S_OK; }
-static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_reverse(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; @@ -475,7 +473,7 @@ static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsi }
/* ECMA-262 3rd Edition 15.4.4.9 */ -static HRESULT Array_shift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_shift(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; @@ -530,7 +528,7 @@ static HRESULT Array_shift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsign }
/* ECMA-262 3rd Edition 15.4.4.10 */ -static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Array_slice(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *arr, *jsthis; DOUBLE range; @@ -651,7 +649,7 @@ static HRESULT sort_cmp(script_ctx_t *ctx, jsdisp_t *cmp_func, jsval_t v1, jsval }
/* ECMA-262 3rd Edition 15.4.4.11 */ -static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_sort(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis, *cmp_func = NULL; @@ -797,7 +795,7 @@ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigne }
/* ECMA-262 3rd Edition 15.4.4.12 */ -static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_splice(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DWORD length, start=0, delete_cnt=0, i, add_args = 0; @@ -905,28 +903,28 @@ static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsig }
/* ECMA-262 3rd Edition 15.4.4.2 */ -static HRESULT Array_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { ArrayInstance *array;
TRACE("\n");
- array = array_this(jsthis); + array = array_this(vthis); if(!array) return JS_E_ARRAY_EXPECTED;
return array_join(ctx, &array->dispex, array->length, L",", 1, r); }
-static HRESULT Array_toLocaleString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_toLocaleString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); return E_NOTIMPL; }
-static HRESULT Array_forEach(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { IDispatch *context_obj = NULL, *callback; @@ -977,7 +975,7 @@ static HRESULT Array_forEach(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsi return S_OK; }
-static HRESULT Array_indexOf(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_indexOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; @@ -1032,7 +1030,7 @@ static HRESULT Array_indexOf(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsi return S_OK; }
-static HRESULT Array_map(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Array_map(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { IDispatch *context_this = NULL, *callback; jsval_t callback_args[3], mapped_value; @@ -1094,7 +1092,7 @@ static HRESULT Array_map(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned return hres; }
-static HRESULT Array_reduce(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Array_reduce(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { IDispatch *context_this = NULL, *callback; jsval_t callback_args[4], acc, new_acc; @@ -1163,7 +1161,7 @@ static HRESULT Array_reduce(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsig }
/* ECMA-262 3rd Edition 15.4.4.13 */ -static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Array_unshift(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; @@ -1196,7 +1194,7 @@ static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsi hres = jsdisp_propput_idx(jsthis, i+argc, val); jsval_release(val); }else if(hres == DISP_E_UNKNOWNNAME) { - hres = IDispatchEx_DeleteMemberByDispID(vthis->u.dispex, id); + hres = IDispatchEx_DeleteMemberByDispID(&jsthis->IDispatchEx_iface, id); } }
@@ -1291,7 +1289,7 @@ static const builtin_info_t ArrayInst_info = { };
/* ECMA-262 5.1 Edition 15.4.3.2 */ -static HRESULT ArrayConstr_isArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT ArrayConstr_isArray(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj;
@@ -1308,7 +1306,7 @@ static HRESULT ArrayConstr_isArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags return S_OK; }
-static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT ArrayConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; diff --git a/dlls/jscript/bool.c b/dlls/jscript/bool.c index 184d8d0..289c47b 100644 --- a/dlls/jscript/bool.c +++ b/dlls/jscript/bool.c @@ -36,14 +36,10 @@ static inline BoolInstance *bool_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, BoolInstance, dispex); }
-static inline BoolInstance *bool_from_vdisp(vdisp_t *vdisp) +static inline BoolInstance *bool_this(jsval_t vthis) { - return bool_from_jsdisp(vdisp->u.jsdisp); -} - -static inline BoolInstance *bool_this(vdisp_t *jsthis) -{ - return is_vclass(jsthis, JSCLASS_BOOLEAN) ? bool_from_vdisp(jsthis) : NULL; + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_BOOLEAN)) ? bool_from_jsdisp(jsdisp) : NULL; }
BOOL bool_obj_value(jsdisp_t *obj) @@ -53,13 +49,13 @@ BOOL bool_obj_value(jsdisp_t *obj) }
/* ECMA-262 3rd Edition 15.6.4.2 */ -static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Bool_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { BoolInstance *bool;
TRACE("\n");
- if(!(bool = bool_this(jsthis))) + if(!(bool = bool_this(vthis))) return JS_E_BOOLEAN_EXPECTED;
if(r) { @@ -76,13 +72,13 @@ static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns }
/* ECMA-262 3rd Edition 15.6.4.3 */ -static HRESULT Bool_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Bool_valueOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { BoolInstance *bool;
TRACE("\n");
- if(!(bool = bool_this(jsthis))) + if(!(bool = bool_this(vthis))) return JS_E_BOOLEAN_EXPECTED;
if(r) @@ -90,7 +86,7 @@ static HRESULT Bool_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi return S_OK; }
-static HRESULT Bool_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Bool_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); @@ -129,7 +125,7 @@ static const builtin_info_t BoolInst_info = { NULL };
-static HRESULT BoolConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT BoolConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { BOOL value = FALSE; diff --git a/dlls/jscript/date.c b/dlls/jscript/date.c index b130c83..e482c4a 100644 --- a/dlls/jscript/date.c +++ b/dlls/jscript/date.c @@ -49,9 +49,10 @@ static inline DateInstance *date_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, DateInstance, dispex); }
-static inline DateInstance *date_this(vdisp_t *jsthis) +static inline DateInstance *date_this(jsval_t vthis) { - return is_vclass(jsthis, JSCLASS_DATE) ? date_from_jsdisp(jsthis->u.jsdisp) : NULL; + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_DATE)) ? date_from_jsdisp(jsdisp) : NULL; }
/*ECMA-262 3rd Edition 15.9.1.2 */ @@ -513,20 +514,20 @@ static HRESULT dateobj_to_string(DateInstance *date, jsval_t *r) return date_to_string(time, TRUE, offset, r); }
-static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Date_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
return dateobj_to_string(date, r); }
/* ECMA-262 3rd Edition 15.9.1.5 */ -static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_toLocaleString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { SYSTEMTIME st; @@ -536,7 +537,7 @@ static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(isnan(date->time)) { @@ -569,7 +570,7 @@ static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag return S_OK; }
-static HRESULT Date_toISOString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_toISOString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -578,7 +579,7 @@ static HRESULT Date_toISOString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
year = year_from_time(date->time); @@ -611,14 +612,14 @@ static HRESULT Date_toISOString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return S_OK; }
-static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_valueOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -626,7 +627,7 @@ static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi return S_OK; }
-static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r) +static inline HRESULT create_utc_string(script_ctx_t *ctx, jsval_t vthis, jsval_t *r) { static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, @@ -646,7 +647,7 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva int year, day; DWORD lcid_en;
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(isnan(date->time)) { @@ -687,18 +688,18 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva }
/* ECMA-262 3rd Edition 15.9.5.42 */ -static HRESULT Date_toUTCString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_toUTCString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return create_utc_string(ctx, jsthis, r); + return create_utc_string(ctx, vthis, r); }
-static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_toGMTString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return create_utc_string(ctx, jsthis, r); + return create_utc_string(ctx, vthis, r); }
/* ECMA-262 3rd Edition 15.9.5.3 */ @@ -758,19 +759,19 @@ static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r) return S_OK; }
-static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_toDateString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
return dateobj_to_date_string(date, r); }
/* ECMA-262 3rd Edition 15.9.5.4 */ -static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_toTimeString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -782,7 +783,7 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(isnan(date->time)) { @@ -821,7 +822,7 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition 15.9.5.6 */ -static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { SYSTEMTIME st; @@ -831,7 +832,7 @@ static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(isnan(date->time)) { @@ -860,7 +861,7 @@ static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD }
/* ECMA-262 3rd Edition 15.9.5.7 */ -static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { SYSTEMTIME st; @@ -870,7 +871,7 @@ static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(isnan(date->time)) { @@ -882,7 +883,7 @@ static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD st = create_systemtime(local_time(date->time, date));
if(st.wYear<1601 || st.wYear>9999) - return Date_toTimeString(ctx, jsthis, flags, argc, argv, r); + return Date_toTimeString(ctx, vthis, flags, argc, argv, r);
if(r) { WCHAR *ptr; @@ -899,14 +900,14 @@ static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD }
/* ECMA-262 3rd Edition 15.9.5.9 */ -static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getTime(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -915,14 +916,14 @@ static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi }
/* ECMA-262 3rd Edition 15.9.5.10 */ -static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getFullYear(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) { @@ -934,14 +935,14 @@ static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition 15.9.5.11 */ -static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -950,13 +951,13 @@ static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag }
/* ECMA-262 3rd Edition 15.9.5.12 */ -static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Date_getMonth(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -965,14 +966,14 @@ static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns }
/* ECMA-262 3rd Edition 15.9.5.13 */ -static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getUTCMonth(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -981,13 +982,13 @@ static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition 15.9.5.14 */ -static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Date_getDate(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -996,14 +997,14 @@ static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi }
/* ECMA-262 3rd Edition 15.9.5.15 */ -static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getUTCDate(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1012,14 +1013,14 @@ static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u }
/* ECMA-262 3rd Edition 15.9.5.16 */ -static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getDay(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1028,14 +1029,14 @@ static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig }
/* ECMA-262 3rd Edition 15.9.5.17 */ -static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getUTCDay(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1044,14 +1045,14 @@ static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un }
/* ECMA-262 3rd Edition 15.9.5.18 */ -static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getHours(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1060,14 +1061,14 @@ static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns }
/* ECMA-262 3rd Edition 15.9.5.19 */ -static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getUTCHours(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1076,14 +1077,14 @@ static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition 15.9.5.20 */ -static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getMinutes(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1092,14 +1093,14 @@ static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u }
/* ECMA-262 3rd Edition 15.9.5.21 */ -static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1108,13 +1109,13 @@ static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags }
/* ECMA-262 3rd Edition 15.9.5.22 */ -static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Date_getSeconds(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1123,14 +1124,14 @@ static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u }
/* ECMA-262 3rd Edition 15.9.5.23 */ -static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1139,14 +1140,14 @@ static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags }
/* ECMA-262 3rd Edition 15.9.5.24 */ -static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getMilliseconds(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1155,14 +1156,14 @@ static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla }
/* ECMA-262 3rd Edition 15.9.5.25 */ -static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1171,14 +1172,14 @@ static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD }
/* ECMA-262 3rd Edition 15.9.5.26 */ -static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date;
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(r) @@ -1187,7 +1188,7 @@ static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD f }
/* ECMA-262 3rd Edition 15.9.5.27 */ -static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setTime(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double n; @@ -1196,7 +1197,7 @@ static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1214,7 +1215,7 @@ static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi }
/* ECMA-262 3rd Edition 15.9.5.28 */ -static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setMilliseconds(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1223,7 +1224,7 @@ static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1244,7 +1245,7 @@ static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla }
/* ECMA-262 3rd Edition 15.9.5.29 */ -static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1253,7 +1254,7 @@ static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1274,7 +1275,7 @@ static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD }
/* ECMA-262 3rd Edition 15.9.5.30 */ -static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setSeconds(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1283,7 +1284,7 @@ static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1313,7 +1314,7 @@ static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u }
/* ECMA-262 3rd Edition 15.9.5.31 */ -static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1322,7 +1323,7 @@ static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1352,7 +1353,7 @@ static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags }
/* ECMA-262 3rd Edition 15.9.5.33 */ -static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setMinutes(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1361,7 +1362,7 @@ static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1399,7 +1400,7 @@ static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u }
/* ECMA-262 3rd Edition 15.9.5.34 */ -static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1408,7 +1409,7 @@ static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1446,7 +1447,7 @@ static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags }
/* ECMA-262 3rd Edition 15.9.5.35 */ -static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setHours(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1455,7 +1456,7 @@ static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1500,7 +1501,7 @@ static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns }
/* ECMA-262 3rd Edition 15.9.5.36 */ -static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setUTCHours(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1509,7 +1510,7 @@ static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1554,7 +1555,7 @@ static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition 15.9.5.36 */ -static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setDate(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1563,7 +1564,7 @@ static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1583,7 +1584,7 @@ static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi }
/* ECMA-262 3rd Edition 15.9.5.37 */ -static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setUTCDate(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1592,7 +1593,7 @@ static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1612,7 +1613,7 @@ static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u }
/* ECMA-262 3rd Edition 15.9.5.38 */ -static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setMonth(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1621,7 +1622,7 @@ static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1651,7 +1652,7 @@ static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns }
/* ECMA-262 3rd Edition 15.9.5.39 */ -static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setUTCMonth(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1660,7 +1661,7 @@ static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1690,7 +1691,7 @@ static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition 15.9.5.40 */ -static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setFullYear(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1699,7 +1700,7 @@ static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1736,7 +1737,7 @@ static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition 15.9.5.41 */ -static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1745,7 +1746,7 @@ static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -1782,7 +1783,7 @@ static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag }
/* ECMA-262 3rd Edition B2.4 */ -static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_getYear(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1790,7 +1791,7 @@ static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
t = local_time(date->time, date); @@ -1807,7 +1808,7 @@ static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi }
/* ECMA-262 3rd Edition B2.5 */ -static HRESULT Date_setYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Date_setYear(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; @@ -1816,7 +1817,7 @@ static HRESULT Date_setYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
TRACE("\n");
- if(!(date = date_this(jsthis))) + if(!(date = date_this(vthis))) return JS_E_DATE_EXPECTED;
if(!argc) @@ -2223,7 +2224,7 @@ static inline HRESULT date_parse(jsstr_t *input_str, double *ret) { return S_OK; }
-static HRESULT DateConstr_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT DateConstr_parse(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *parse_str; @@ -2321,7 +2322,7 @@ static HRESULT date_utc(script_ctx_t *ctx, unsigned argc, jsval_t *argv, double return S_OK; }
-static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT DateConstr_UTC(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double n; @@ -2336,7 +2337,7 @@ static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un }
/* ECMA-262 5.1 Edition 15.9.4.4 */ -static HRESULT DateConstr_now(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT DateConstr_now(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n");
@@ -2344,7 +2345,7 @@ static HRESULT DateConstr_now(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un return S_OK; }
-static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT DateConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DateInstance *date; diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 5e09553..3a1d380 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -550,7 +550,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
switch(prop->type) { case PROP_BUILTIN: { - vdisp_t vthis; + jsval_t vthis;
if(flags == DISPATCH_CONSTRUCT && (prop->flags & PROPF_METHOD)) { WARN("%s is not a constructor\n", debugstr_w(prop->name)); @@ -560,13 +560,10 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t if(This->builtin_info->class != JSCLASS_FUNCTION && prop->u.p->invoke != JSGlobal_eval) flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; if(jsthis) - set_disp(&vthis, jsthis); + vthis = jsval_disp(jsthis); else - set_jsdisp(&vthis, This); - hres = prop->u.p->invoke(This->ctx, &vthis, flags, argc, argv, r); - vdisp_release(&vthis); - - return hres; + vthis = jsval_obj(This); + return prop->u.p->invoke(This->ctx, vthis, flags, argc, argv, r); } case PROP_PROTREF: return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, @@ -1979,17 +1976,13 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig if(is_class(jsfunc, JSCLASS_FUNCTION)) { hres = Function_invoke(jsfunc, jsthis, flags, argc, argv, r); }else { - vdisp_t vdisp; - if(!jsfunc->builtin_info->call) { WARN("Not a function\n"); return JS_E_FUNCTION_EXPECTED; }
- set_disp(&vdisp, jsthis); flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; - hres = jsfunc->builtin_info->call(jsfunc->ctx, &vdisp, flags, argc, argv, r); - vdisp_release(&vdisp); + hres = jsfunc->builtin_info->call(jsfunc->ctx, jsval_disp(jsthis), flags, argc, argv, r); } return hres; } diff --git a/dlls/jscript/enumerator.c b/dlls/jscript/enumerator.c index 038b474..0fc6750 100644 --- a/dlls/jscript/enumerator.c +++ b/dlls/jscript/enumerator.c @@ -38,14 +38,10 @@ static inline EnumeratorInstance *enumerator_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, EnumeratorInstance, dispex); }
-static inline EnumeratorInstance *enumerator_from_vdisp(vdisp_t *vdisp) +static inline EnumeratorInstance *enumerator_this(jsval_t vthis) { - return enumerator_from_jsdisp(vdisp->u.jsdisp); -} - -static inline EnumeratorInstance *enumerator_this(vdisp_t *jsthis) -{ - return is_vclass(jsthis, JSCLASS_ENUMERATOR) ? enumerator_from_vdisp(jsthis) : NULL; + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_ENUMERATOR)) ? enumerator_from_jsdisp(jsdisp) : NULL; }
static inline HRESULT enumvar_get_next_item(EnumeratorInstance *This) @@ -92,12 +88,12 @@ static void Enumerator_destructor(jsdisp_t *dispex) heap_free(dispex); }
-static HRESULT Enumerator_atEnd(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Enumerator_atEnd(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { EnumeratorInstance *This;
- if (!(This = enumerator_this(jsthis))) + if (!(This = enumerator_this(vthis))) return JS_E_ENUMERATOR_EXPECTED;
TRACE("%d\n", This->atend); @@ -107,20 +103,20 @@ static HRESULT Enumerator_atEnd(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return S_OK; }
-static HRESULT Enumerator_item(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Enumerator_item(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { EnumeratorInstance *This;
TRACE("\n");
- if (!(This = enumerator_this(jsthis))) + if (!(This = enumerator_this(vthis))) return JS_E_ENUMERATOR_EXPECTED;
return r ? jsval_copy(This->item, r) : S_OK; }
-static HRESULT Enumerator_moveFirst(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Enumerator_moveFirst(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { EnumeratorInstance *This; @@ -128,7 +124,7 @@ static HRESULT Enumerator_moveFirst(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla
TRACE("\n");
- if (!(This = enumerator_this(jsthis))) + if (!(This = enumerator_this(vthis))) return JS_E_ENUMERATOR_EXPECTED;
if (This->enumvar) @@ -148,7 +144,7 @@ static HRESULT Enumerator_moveFirst(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla return S_OK; }
-static HRESULT Enumerator_moveNext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Enumerator_moveNext(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { EnumeratorInstance *This; @@ -156,7 +152,7 @@ static HRESULT Enumerator_moveNext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
TRACE("\n");
- if (!(This = enumerator_this(jsthis))) + if (!(This = enumerator_this(vthis))) return JS_E_ENUMERATOR_EXPECTED;
if (This->enumvar) @@ -287,7 +283,7 @@ static HRESULT create_enumerator(script_ctx_t *ctx, jsval_t *argv, jsdisp_t **re return S_OK; }
-static HRESULT EnumeratorConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT EnumeratorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index 49adaeb..3b13e8c 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -29,7 +29,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript);
/* ECMA-262 3rd Edition 15.11.4.4 */ -static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, +static HRESULT Error_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; @@ -39,7 +39,10 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags,
TRACE("\n");
- jsthis = get_jsdisp(vthis); + if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + + jsthis = to_jsdisp(get_object(vthis)); if(!jsthis || ctx->version < 2) { if(r) { jsstr_t *str; @@ -114,7 +117,7 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, return S_OK; }
-static HRESULT Error_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT Error_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); @@ -260,56 +263,56 @@ static HRESULT error_constr(script_ctx_t *ctx, WORD flags, unsigned argc, jsval_ } }
-static HRESULT ErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT ErrorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); return error_constr(ctx, flags, argc, argv, r, ctx->error_constr); }
-static HRESULT EvalErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT EvalErrorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); return error_constr(ctx, flags, argc, argv, r, ctx->eval_error_constr); }
-static HRESULT RangeErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT RangeErrorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); return error_constr(ctx, flags, argc, argv, r, ctx->range_error_constr); }
-static HRESULT ReferenceErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT ReferenceErrorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); return error_constr(ctx, flags, argc, argv, r, ctx->reference_error_constr); }
-static HRESULT RegExpErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT RegExpErrorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); return error_constr(ctx, flags, argc, argv, r, ctx->regexp_error_constr); }
-static HRESULT SyntaxErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT SyntaxErrorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); return error_constr(ctx, flags, argc, argv, r, ctx->syntax_error_constr); }
-static HRESULT TypeErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT TypeErrorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); return error_constr(ctx, flags, argc, argv, r, ctx->type_error_constr); }
-static HRESULT URIErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT URIErrorConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 3eef1aa..3730915 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -77,14 +77,10 @@ static inline FunctionInstance *function_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, FunctionInstance, dispex); }
-static inline FunctionInstance *function_from_vdisp(vdisp_t *vdisp) +static inline FunctionInstance *function_this(jsval_t vthis) { - return function_from_jsdisp(vdisp->u.jsdisp); -} - -static inline FunctionInstance *function_this(vdisp_t *jsthis) -{ - return is_vclass(jsthis, JSCLASS_FUNCTION) ? function_from_vdisp(jsthis) : NULL; + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_FUNCTION)) ? function_from_jsdisp(jsdisp) : NULL; }
static inline ArgumentsInstance *arguments_from_jsdisp(jsdisp_t *jsdisp) @@ -92,7 +88,7 @@ static inline ArgumentsInstance *arguments_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, ArgumentsInstance, jsdisp); }
-static HRESULT Arguments_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Arguments_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); @@ -271,7 +267,7 @@ static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t return S_OK; }
-static HRESULT Function_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Function_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FunctionInstance *function; @@ -280,7 +276,7 @@ static HRESULT Function_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
- if(!(function = function_this(jsthis))) + if(!(function = function_this(vthis))) return JS_E_FUNCTION_EXPECTED;
hres = function->vtbl->toString(function, &str); @@ -330,7 +326,7 @@ static HRESULT array_to_args(script_ctx_t *ctx, jsdisp_t *arg_array, unsigned *a return S_OK; }
-static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FunctionInstance *function; jsval_t *args = NULL; @@ -340,7 +336,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
TRACE("\n");
- if(!(function = function_this(jsthis)) && (jsthis->flags & VDISP_JSDISP)) + if(!is_object_instance(vthis) || (!(function = function_this(vthis)) && to_jsdisp(get_object(vthis)))) return JS_E_FUNCTION_EXPECTED;
if(argc) { @@ -377,7 +373,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un hres = function->vtbl->call(ctx, function, this_obj, flags, cnt, args, r); }else { jsval_t res; - hres = disp_call_value(ctx, jsthis->u.disp, this_obj, DISPATCH_METHOD, cnt, args, &res); + hres = disp_call_value(ctx, get_object(vthis), this_obj, DISPATCH_METHOD, cnt, args, &res); if(SUCCEEDED(hres)) { if(r) *r = res; @@ -395,7 +391,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un return hres; }
-static HRESULT Function_call(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Function_call(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FunctionInstance *function; @@ -405,7 +401,7 @@ static HRESULT Function_call(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
TRACE("\n");
- if(!(function = function_this(jsthis))) + if(!(function = function_this(vthis))) return JS_E_FUNCTION_EXPECTED;
if(argc) { @@ -425,7 +421,7 @@ static HRESULT Function_call(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns return hres; }
-static HRESULT Function_bind(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Function_bind(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { IDispatch *bound_this = NULL; @@ -435,7 +431,7 @@ static HRESULT Function_bind(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
TRACE("\n");
- if(!(function = function_this(jsthis))) + if(!(function = function_this(vthis))) return JS_E_FUNCTION_EXPECTED;
if(argc < 1) { @@ -461,19 +457,18 @@ static HRESULT Function_bind(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns return S_OK; }
-HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +HRESULT Function_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FunctionInstance *function;
TRACE("\n");
- if(!is_vclass(jsthis, JSCLASS_FUNCTION)) { + if(!(function = function_this(vthis))) { ERR("dispex is not a function\n"); return E_FAIL; }
- function = function_from_jsdisp(jsthis->u.jsdisp); return function->vtbl->call(ctx, function, NULL, flags, argc, argv, r); }
@@ -599,18 +594,14 @@ static HRESULT NativeFunction_call(script_ctx_t *ctx, FunctionInstance *func, ID unsigned argc, jsval_t *argv, jsval_t *r) { NativeFunction *function = (NativeFunction*)func; - vdisp_t vthis; - HRESULT hres; + jsval_t vthis;
if(this_disp) - set_disp(&vthis, this_disp); + vthis = jsval_disp(this_disp); else - set_disp(&vthis, lookup_global_host(ctx)); - - hres = function->proc(ctx, &vthis, flags & ~DISPATCH_JSCRIPT_INTERNAL_MASK, argc, argv, r); + vthis = jsval_disp(lookup_global_host(ctx));
- vdisp_release(&vthis); - return hres; + return function->proc(ctx, vthis, flags & ~DISPATCH_JSCRIPT_INTERNAL_MASK, argc, argv, r); }
static HRESULT NativeFunction_toString(FunctionInstance *func, jsstr_t **ret) @@ -984,7 +975,7 @@ static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *arg return S_OK; }
-static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT FunctionConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { HRESULT hres; @@ -1011,7 +1002,7 @@ static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla return S_OK; }
-static HRESULT FunctionProt_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT FunctionProt_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index c9a00d1..5186f47 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -65,7 +65,7 @@ static WCHAR int_to_char(int i) return 'A'+i-10; }
-static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_escape(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *ret_str, *str; @@ -130,7 +130,7 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u }
/* ECMA-262 3rd Edition 15.1.2.1 */ -HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +HRESULT JSGlobal_eval(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { call_frame_t *frame = ctx->call_ctx; @@ -174,7 +174,7 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a return hres; }
-static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { BOOL ret = TRUE; @@ -197,7 +197,7 @@ static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un return S_OK; }
-static HRESULT JSGlobal_isFinite(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_isFinite(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { BOOL ret = FALSE; @@ -231,7 +231,7 @@ static INT char_to_int(WCHAR c) return 100; }
-static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { BOOL neg = FALSE, empty = TRUE; @@ -314,7 +314,7 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return S_OK; }
-static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { LONGLONG d = 0, hlp; @@ -421,7 +421,7 @@ static inline int hex_to_int(const WCHAR wch) { return -1; }
-static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_unescape(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *ret_str, *str; @@ -491,14 +491,14 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return S_OK; }
-static HRESULT JSGlobal_GetObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_GetObject(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); return E_NOTIMPL; }
-static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); @@ -516,7 +516,7 @@ static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl return S_OK; }
-static HRESULT JSGlobal_ScriptEngineMajorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_ScriptEngineMajorVersion(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); @@ -526,7 +526,7 @@ static HRESULT JSGlobal_ScriptEngineMajorVersion(script_ctx_t *ctx, vdisp_t *jst return S_OK; }
-static HRESULT JSGlobal_ScriptEngineMinorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_ScriptEngineMinorVersion(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); @@ -536,7 +536,7 @@ static HRESULT JSGlobal_ScriptEngineMinorVersion(script_ctx_t *ctx, vdisp_t *jst return S_OK; }
-static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); @@ -546,7 +546,7 @@ static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, vdisp_t *jst return S_OK; }
-static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { static int once = 0; @@ -555,7 +555,7 @@ static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD return S_OK; }
-static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { const WCHAR *ptr, *uri; @@ -620,7 +620,7 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags return S_OK; }
-static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { const WCHAR *ptr, *uri; @@ -706,7 +706,7 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags return S_OK; }
-static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *str, *ret_str; @@ -770,7 +770,7 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W }
/* ECMA-262 3rd Edition 15.1.3.2 */ -static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { const WCHAR *ptr, *uri; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index c192ec7..f4e8782 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -138,71 +138,7 @@ typedef enum {
jsdisp_t *iface_to_jsdisp(IDispatch*) DECLSPEC_HIDDEN;
-typedef struct { - union { - IDispatch *disp; - IDispatchEx *dispex; - jsdisp_t *jsdisp; - } u; - DWORD flags; -} vdisp_t; - -#define VDISP_DISPEX 0x0001 -#define VDISP_JSDISP 0x0002 - -static inline void vdisp_release(vdisp_t *vdisp) -{ - IDispatch_Release(vdisp->u.disp); -} - -static inline BOOL is_jsdisp(vdisp_t *vdisp) -{ - return (vdisp->flags & VDISP_JSDISP) != 0; -} - -static inline BOOL is_dispex(vdisp_t *vdisp) -{ - return (vdisp->flags & VDISP_DISPEX) != 0; -} - -static inline void set_jsdisp(vdisp_t *vdisp, jsdisp_t *jsdisp) -{ - vdisp->u.jsdisp = jsdisp; - vdisp->flags = VDISP_JSDISP | VDISP_DISPEX; - IDispatch_AddRef(vdisp->u.disp); -} - -static inline void set_disp(vdisp_t *vdisp, IDispatch *disp) -{ - IDispatchEx *dispex; - jsdisp_t *jsdisp; - HRESULT hres; - - jsdisp = iface_to_jsdisp(disp); - if(jsdisp) { - vdisp->u.jsdisp = jsdisp; - vdisp->flags = VDISP_JSDISP | VDISP_DISPEX; - return; - } - - hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - if(SUCCEEDED(hres)) { - vdisp->u.dispex = dispex; - vdisp->flags = VDISP_DISPEX; - return; - } - - IDispatch_AddRef(disp); - vdisp->u.disp = disp; - vdisp->flags = 0; -} - -static inline jsdisp_t *get_jsdisp(vdisp_t *vdisp) -{ - return is_jsdisp(vdisp) ? vdisp->u.jsdisp : NULL; -} - -typedef HRESULT (*builtin_invoke_t)(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*); +typedef HRESULT (*builtin_invoke_t)(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*); typedef HRESULT (*builtin_getter_t)(script_ctx_t*,jsdisp_t*,jsval_t*); typedef HRESULT (*builtin_setter_t)(script_ctx_t*,jsdisp_t*,jsval_t);
@@ -337,7 +273,7 @@ HRESULT create_builtin_constructor(script_ctx_t*,builtin_invoke_t,const WCHAR*,c jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT Function_invoke(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
-HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT Function_value(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; HRESULT Function_get_value(script_ctx_t*,jsdisp_t*,jsval_t*) DECLSPEC_HIDDEN; struct _function_code_t *Function_get_code(jsdisp_t*) DECLSPEC_HIDDEN;
@@ -513,18 +449,13 @@ HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*) DECLSPEC_ BOOL bool_obj_value(jsdisp_t*) DECLSPEC_HIDDEN; unsigned array_get_length(jsdisp_t*) DECLSPEC_HIDDEN;
-HRESULT JSGlobal_eval(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT JSGlobal_eval(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
static inline BOOL is_class(jsdisp_t *jsdisp, jsclass_t class) { return jsdisp->builtin_info->class == class; }
-static inline BOOL is_vclass(vdisp_t *vdisp, jsclass_t class) -{ - return is_jsdisp(vdisp) && is_class(vdisp->u.jsdisp, class); -} - static inline BOOL is_int32(double d) { return INT32_MIN <= d && d <= INT32_MAX && (double)(int)d == d; diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c index d3896ca..e0867eb 100644 --- a/dlls/jscript/json.c +++ b/dlls/jscript/json.c @@ -268,7 +268,7 @@ static HRESULT parse_json_value(json_parse_ctx_t *ctx, jsval_t *r) }
/* ECMA-262 5.1 Edition 15.12.2 */ -static HRESULT JSON_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT JSON_parse(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { json_parse_ctx_t parse_ctx; const WCHAR *buf; @@ -749,7 +749,7 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *na }
/* ECMA-262 5.1 Edition 15.12.3 */ -static HRESULT JSON_stringify(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT JSON_stringify(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { stringify_ctx_t stringify_ctx = { ctx }; jsdisp_t *obj = NULL, *replacer; diff --git a/dlls/jscript/jsregexp.c b/dlls/jscript/jsregexp.c index cb6c051..33f1538 100644 --- a/dlls/jscript/jsregexp.c +++ b/dlls/jscript/jsregexp.c @@ -39,9 +39,10 @@ static inline RegExpInstance *regexp_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, RegExpInstance, dispex); }
-static inline RegExpInstance *regexp_from_vdisp(vdisp_t *vdisp) +static inline RegExpInstance *regexp_this(jsval_t vthis) { - return regexp_from_jsdisp(vdisp->u.jsdisp); + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_REGEXP)) ? regexp_from_jsdisp(jsdisp) : NULL; }
static void set_last_index(RegExpInstance *This, DWORD last_index) @@ -294,7 +295,7 @@ static HRESULT RegExp_set_lastIndex(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t return S_OK; }
-static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT RegExp_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { RegExpInstance *regexp; @@ -304,12 +305,11 @@ static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
TRACE("\n");
- if(!is_vclass(jsthis, JSCLASS_REGEXP)) { + if(!(regexp = regexp_this(vthis))) { WARN("Not a RegExp\n"); return JS_E_REGEXP_EXPECTED; }
- regexp = regexp_from_vdisp(jsthis);
if(!r) return S_OK; @@ -408,7 +408,7 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input_str, return S_OK; }
-static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, +static HRESULT run_exec(script_ctx_t *ctx, jsval_t vthis, jsval_t arg, jsstr_t **input, match_state_t **result, BOOL *ret) { RegExpInstance *regexp; @@ -418,13 +418,11 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, jsstr_t *jsstr; HRESULT hres;
- if(!is_vclass(jsthis, JSCLASS_REGEXP)) { - FIXME("Not a RegExp\n"); - return E_NOTIMPL; + if(!(regexp = regexp_this(vthis))) { + WARN("Not a RegExp\n"); + return JS_E_REGEXP_EXPECTED; }
- regexp = regexp_from_vdisp(jsthis); - hres = to_flat_string(ctx, arg, &jsstr, &string); if(FAILED(hres)) return hres; @@ -463,7 +461,7 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, return S_OK; }
-static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT RegExp_exec(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { match_state_t *match; @@ -476,7 +474,7 @@ static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig
mark = heap_pool_mark(&ctx->tmp_heap);
- hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(jsstr_empty()), &string, &match, &b); + hres = run_exec(ctx, vthis, argc ? argv[0] : jsval_string(jsstr_empty()), &string, &match, &b); if(FAILED(hres)) { heap_pool_clear(mark); return hres; @@ -499,7 +497,7 @@ static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig return hres; }
-static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT RegExp_test(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { match_state_t *match; @@ -511,7 +509,7 @@ static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig TRACE("\n");
mark = heap_pool_mark(&ctx->tmp_heap); - hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(undef_str = jsstr_undefined()), NULL, &match, &b); + hres = run_exec(ctx, vthis, argc ? argv[0] : jsval_string(undef_str = jsstr_undefined()), NULL, &match, &b); heap_pool_clear(mark); if(!argc) jsstr_release(undef_str); @@ -523,7 +521,7 @@ static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig return S_OK; }
-static HRESULT RegExp_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT RegExp_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); @@ -886,7 +884,7 @@ static HRESULT RegExpConstr_get_rightContext(script_ctx_t *ctx, jsdisp_t *jsthis return S_OK; }
-static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT RegExpConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); diff --git a/dlls/jscript/math.c b/dlls/jscript/math.c index c65bbaf..46dd58c 100644 --- a/dlls/jscript/math.c +++ b/dlls/jscript/math.c @@ -29,7 +29,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript);
/* ECMA-262 3rd Edition 15.8.2.12 */ -static HRESULT Math_abs(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_abs(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double d; @@ -52,7 +52,7 @@ static HRESULT Math_abs(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned return S_OK; }
-static HRESULT Math_acos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_acos(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -75,7 +75,7 @@ static HRESULT Math_acos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigne return S_OK; }
-static HRESULT Math_asin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_asin(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -98,7 +98,7 @@ static HRESULT Math_asin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigne return S_OK; }
-static HRESULT Math_atan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_atan(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -121,7 +121,7 @@ static HRESULT Math_atan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigne return S_OK; }
-static HRESULT Math_atan2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_atan2(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x, y; @@ -149,7 +149,7 @@ static HRESULT Math_atan2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsign }
/* ECMA-262 3rd Edition 15.8.2.6 */ -static HRESULT Math_ceil(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_ceil(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -172,7 +172,7 @@ static HRESULT Math_ceil(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigne return S_OK; }
-static HRESULT Math_cos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_cos(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -195,7 +195,7 @@ static HRESULT Math_cos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned return S_OK; }
-static HRESULT Math_exp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_exp(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -218,7 +218,7 @@ static HRESULT Math_exp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned return S_OK; }
-static HRESULT Math_floor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_floor(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -241,7 +241,7 @@ static HRESULT Math_floor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsign return S_OK; }
-static HRESULT Math_log(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_log(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -265,7 +265,7 @@ static HRESULT Math_log(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned }
/* ECMA-262 3rd Edition 15.8.2.11 */ -static HRESULT Math_max(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_max(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DOUBLE max, d; @@ -299,7 +299,7 @@ static HRESULT Math_max(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned }
/* ECMA-262 3rd Edition 15.8.2.12 */ -static HRESULT Math_min(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_min(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { DOUBLE min, d; @@ -333,7 +333,7 @@ static HRESULT Math_min(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned }
/* ECMA-262 3rd Edition 15.8.2.13 */ -static HRESULT Math_pow(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_pow(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x, y; @@ -361,7 +361,7 @@ static HRESULT Math_pow(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned }
/* ECMA-262 3rd Edition 15.8.2.14 */ -static HRESULT Math_random(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_random(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { UINT x; @@ -377,7 +377,7 @@ static HRESULT Math_random(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig }
/* ECMA-262 3rd Edition 15.8.2.15 */ -static HRESULT Math_round(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_round(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -400,7 +400,7 @@ static HRESULT Math_round(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsign return S_OK; }
-static HRESULT Math_sin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_sin(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -423,7 +423,7 @@ static HRESULT Math_sin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned return S_OK; }
-static HRESULT Math_sqrt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_sqrt(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; @@ -446,7 +446,7 @@ static HRESULT Math_sqrt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigne return S_OK; }
-static HRESULT Math_tan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Math_tan(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double x; diff --git a/dlls/jscript/number.c b/dlls/jscript/number.c index 410f27b..12cb527 100644 --- a/dlls/jscript/number.c +++ b/dlls/jscript/number.c @@ -39,14 +39,10 @@ static inline NumberInstance *number_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, NumberInstance, dispex); }
-static inline NumberInstance *number_from_vdisp(vdisp_t *vdisp) +static inline NumberInstance *number_this(jsval_t vthis) { - return number_from_jsdisp(vdisp->u.jsdisp); -} - -static inline NumberInstance *number_this(vdisp_t *jsthis) -{ - return is_vclass(jsthis, JSCLASS_NUMBER) ? number_from_vdisp(jsthis) : NULL; + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_NUMBER)) ? number_from_jsdisp(jsdisp) : NULL; }
static inline void number_to_str(double d, WCHAR *buf, int size, int *dec_point) @@ -222,7 +218,7 @@ static inline jsstr_t *number_to_exponential(double val, int prec) }
/* ECMA-262 3rd Edition 15.7.4.2 */ -static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Number_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number; @@ -233,7 +229,7 @@ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
TRACE("\n");
- if(!(number = number_this(jsthis))) + if(!(number = number_this(vthis))) return JS_E_NUMBER_EXPECTED;
if(argc) { @@ -341,14 +337,14 @@ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u return S_OK; }
-static HRESULT Number_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Number_toLocaleString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); return E_NOTIMPL; }
-static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Number_toFixed(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number; @@ -359,7 +355,7 @@ static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
TRACE("\n");
- if(!(number = number_this(jsthis))) + if(!(number = number_this(vthis))) return JS_E_NUMBER_EXPECTED;
if(argc) { @@ -389,7 +385,7 @@ static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un return S_OK; }
-static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Number_toExponential(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number; @@ -400,7 +396,7 @@ static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla
TRACE("\n");
- if(!(number = number_this(jsthis))) + if(!(number = number_this(vthis))) return JS_E_NUMBER_EXPECTED;
if(argc) { @@ -432,7 +428,7 @@ static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla return S_OK; }
-static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Number_toPrecision(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number; @@ -441,7 +437,7 @@ static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags DOUBLE val; HRESULT hres;
- if(!(number = number_this(jsthis))) + if(!(number = number_this(vthis))) return JS_E_NUMBER_EXPECTED;
if(argc) { @@ -479,14 +475,14 @@ static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags return S_OK; }
-static HRESULT Number_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Number_valueOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number;
TRACE("\n");
- if(!(number = number_this(jsthis))) + if(!(number = number_this(vthis))) return JS_E_NUMBER_EXPECTED;
if(r) @@ -520,7 +516,7 @@ static const builtin_info_t NumberInst_info = { NULL };
-static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT NumberConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { double n; diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 24692f8..96a52be 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -24,10 +24,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
-static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - jsdisp_t *jsdisp; + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; const WCHAR *str;
/* Keep in sync with jsclass_t enum */ @@ -54,7 +54,6 @@ static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
TRACE("\n");
- jsdisp = get_jsdisp(jsthis); if(!jsdisp) { str = L"[object Object]"; }else if(names[jsdisp->builtin_info->class]) { @@ -76,34 +75,39 @@ static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u return S_OK; }
-static HRESULT Object_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_toLocaleString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + jsdisp_t *jsdisp; + TRACE("\n");
- if(!is_jsdisp(jsthis)) { + if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + + if(!(jsdisp = to_jsdisp(get_object(vthis)))) { FIXME("Host object this\n"); return E_FAIL; }
- return jsdisp_call_name(jsthis->u.jsdisp, L"toString", DISPATCH_METHOD, 0, NULL, r); + return jsdisp_call_name(jsdisp, L"toString", DISPATCH_METHOD, 0, NULL, r); }
-static HRESULT Object_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_valueOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n");
- if(r) { - IDispatch_AddRef(jsthis->u.disp); - *r = jsval_disp(jsthis->u.disp); - } + if(r) + jsval_copy(vthis, r); return S_OK; }
-static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + IDispatchEx *dispex; + jsdisp_t *jsdisp; jsstr_t *name; DISPID id; BSTR bstr; @@ -111,6 +115,9 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl
TRACE("\n");
+ if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + if(!argc) { if(r) *r = jsval_bool(FALSE); @@ -121,7 +128,7 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl if(FAILED(hres)) return hres;
- if(is_jsdisp(jsthis)) { + if((jsdisp = to_jsdisp(get_object(vthis)))) { property_desc_t prop_desc; const WCHAR *name_str;
@@ -131,7 +138,7 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl return E_OUTOFMEMORY; }
- hres = jsdisp_get_own_property(jsthis->u.jsdisp, name_str, TRUE, &prop_desc); + hres = jsdisp_get_own_property(jsdisp, name_str, TRUE, &prop_desc); jsstr_release(name); if(FAILED(hres) && hres != DISP_E_UNKNOWNNAME) return hres; @@ -148,33 +155,39 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl if(!bstr) return E_OUTOFMEMORY;
- if(is_dispex(jsthis)) - hres = IDispatchEx_GetDispID(jsthis->u.dispex, bstr, make_grfdex(ctx, fdexNameCaseSensitive), &id); - else - hres = IDispatch_GetIDsOfNames(jsthis->u.disp, &IID_NULL, &bstr, 1, ctx->lcid, &id); - + hres = IDispatch_QueryInterface(get_object(vthis), &IID_IDispatchEx, (void**)&dispex); + if(SUCCEEDED(hres)) { + hres = IDispatchEx_GetDispID(dispex, bstr, make_grfdex(ctx, fdexNameCaseSensitive), &id); + IDispatchEx_Release(dispex); + }else { + hres = IDispatch_GetIDsOfNames(get_object(vthis), &IID_NULL, &bstr, 1, ctx->lcid, &id); + } SysFreeString(bstr); if(r) *r = jsval_bool(SUCCEEDED(hres)); return S_OK; }
-static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { property_desc_t prop_desc; const WCHAR *name; jsstr_t *name_str; + jsdisp_t *jsdisp; HRESULT hres;
TRACE("\n");
+ if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + if(argc != 1) { FIXME("argc %d not supported\n", argc); return E_NOTIMPL; }
- if(!is_jsdisp(jsthis)) { + if(!(jsdisp = to_jsdisp(get_object(vthis)))) { FIXME("Host object this\n"); return E_FAIL; } @@ -183,7 +196,7 @@ static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, W if(FAILED(hres)) return hres;
- hres = jsdisp_get_own_property(jsthis->u.jsdisp, name, TRUE, &prop_desc); + hres = jsdisp_get_own_property(jsdisp, name, TRUE, &prop_desc); jsstr_release(name_str); if(FAILED(hres) && hres != DISP_E_UNKNOWNNAME) return hres; @@ -193,18 +206,22 @@ static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, W return S_OK; }
-static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - jsdisp_t *jsdisp; + jsdisp_t *jsthis, *jsdisp; BOOL ret = FALSE;
+ if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + if(!r) return S_OK;
- if(argc && is_jsdisp(jsthis) && is_object_instance(argv[0]) && (jsdisp = to_jsdisp(get_object(argv[0])))) { + if(argc && (jsthis = to_jsdisp(get_object(vthis))) && is_object_instance(argv[0]) && + (jsdisp = to_jsdisp(get_object(argv[0])))) { while(jsdisp->prototype) { - if(jsdisp->prototype == jsthis->u.jsdisp) { + if(jsdisp->prototype == jsthis) { ret = TRUE; break; } @@ -466,7 +483,7 @@ static HRESULT jsdisp_define_properties(script_ctx_t *ctx, jsdisp_t *obj, jsval_ return FAILED(hres) ? hres : S_OK; }
-static HRESULT Object_defineProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT Object_defineProperty(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { property_desc_t prop_desc; @@ -515,7 +532,7 @@ static HRESULT Object_defineProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl return hres; }
-static HRESULT Object_defineProperties(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT Object_defineProperties(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; @@ -534,7 +551,7 @@ static HRESULT Object_defineProperties(script_ctx_t *ctx, vdisp_t *jsthis, WORD return hres; }
-static HRESULT Object_getOwnPropertyDescriptor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT Object_getOwnPropertyDescriptor(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { property_desc_t prop_desc; @@ -597,7 +614,7 @@ static HRESULT Object_getOwnPropertyDescriptor(script_ctx_t *ctx, vdisp_t *jsthi return hres; }
-static HRESULT Object_create(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT Object_create(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *proto = NULL, *obj; @@ -636,7 +653,7 @@ static HRESULT Object_create(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return hres; }
-static HRESULT Object_getPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT Object_getPrototypeOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; @@ -704,7 +721,7 @@ static HRESULT object_keys(script_ctx_t *ctx, jsval_t arg, enum jsdisp_enum_type return hres; }
-static HRESULT Object_keys(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT Object_keys(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsval_t arg = argc ? argv[0] : jsval_undefined(); @@ -714,7 +731,7 @@ static HRESULT Object_keys(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return object_keys(ctx, arg, JSDISP_ENUM_OWN_ENUMERABLE, r); }
-static HRESULT Object_getOwnPropertyNames(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT Object_getOwnPropertyNames(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsval_t arg = argc ? argv[0] : jsval_undefined(); @@ -724,7 +741,7 @@ static HRESULT Object_getOwnPropertyNames(script_ctx_t *ctx, vdisp_t *jsthis, WO return object_keys(ctx, arg, JSDISP_ENUM_OWN, r); }
-static HRESULT Object_preventExtensions(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Object_preventExtensions(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj;
@@ -746,7 +763,7 @@ static HRESULT Object_preventExtensions(script_ctx_t *ctx, vdisp_t *jsthis, WORD return S_OK; }
-static HRESULT Object_freeze(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, +static HRESULT Object_freeze(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; @@ -769,7 +786,7 @@ static HRESULT Object_freeze(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns return S_OK; }
-static HRESULT Object_seal(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, +static HRESULT Object_seal(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; @@ -792,7 +809,7 @@ static HRESULT Object_seal(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig return S_OK; }
-static HRESULT Object_isExtensible(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) +static HRESULT Object_isExtensible(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj;
@@ -813,7 +830,7 @@ static HRESULT Object_isExtensible(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag return S_OK; }
-static HRESULT Object_isFrozen(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, +static HRESULT Object_isFrozen(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; @@ -835,7 +852,7 @@ static HRESULT Object_isFrozen(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u return S_OK; }
-static HRESULT Object_isSealed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, +static HRESULT Object_isSealed(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; @@ -882,7 +899,7 @@ static const builtin_info_t ObjectConstr_info = { NULL };
-static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT ObjectConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { HRESULT hres; diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c index 5ae41d8..35edcf8 100644 --- a/dlls/jscript/set.c +++ b/dlls/jscript/set.c @@ -37,42 +37,42 @@ typedef struct { size_t size; } MapInstance;
-static HRESULT Set_add(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Set_add(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - FIXME("%p\n", jsthis); + FIXME("%p\n", debugstr_jsval(vthis)); return E_NOTIMPL; }
-static HRESULT Set_clear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Set_clear(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - FIXME("%p\n", jsthis); + FIXME("%p\n", debugstr_jsval(vthis)); return E_NOTIMPL; }
-static HRESULT Set_delete(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Set_delete(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - FIXME("%p\n", jsthis); + FIXME("%p\n", debugstr_jsval(vthis)); return E_NOTIMPL; }
-static HRESULT Set_forEach(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Set_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - FIXME("%p\n", jsthis); + FIXME("%p\n", debugstr_jsval(vthis)); return E_NOTIMPL; }
-static HRESULT Set_has(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Set_has(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - FIXME("%p\n", jsthis); + FIXME("%p\n", debugstr_jsval(vthis)); return E_NOTIMPL; }
-static HRESULT Set_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Set_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); @@ -104,7 +104,7 @@ static const builtin_info_t Set_info = { NULL };
-static HRESULT Set_constructor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Set_constructor(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { SetInstance *set; @@ -176,14 +176,19 @@ static int jsval_map_compare(const void *k, const struct wine_rb_entry *e) } }
-static MapInstance *get_map_this(vdisp_t *jsthis) +static HRESULT get_map_this(jsval_t vthis, MapInstance **ret) { - if(!(jsthis->flags & VDISP_JSDISP) || !is_class(jsthis->u.jsdisp, JSCLASS_MAP)) { + jsdisp_t *jsdisp; + + if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + if(!(jsdisp = to_jsdisp(get_object(vthis))) || !is_class(jsdisp, JSCLASS_MAP)) { WARN("not a Map object passed as 'this'\n"); - return NULL; + return JS_E_MAP_EXPECTED; }
- return CONTAINING_RECORD(jsthis->u.jsdisp, MapInstance, dispex); + *ret = CONTAINING_RECORD(jsdisp, MapInstance, dispex); + return S_OK; }
static struct jsval_map_entry *get_map_entry(MapInstance *map, jsval_t key) @@ -215,12 +220,15 @@ static void delete_map_entry(MapInstance *map, struct jsval_map_entry *entry) release_map_entry(entry); }
-static HRESULT Map_clear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Map_clear(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { MapInstance *map; + HRESULT hres;
- if(!(map = get_map_this(jsthis))) return JS_E_MAP_EXPECTED; + hres = get_map_this(vthis, &map); + if(FAILED(hres)) + return hres;
TRACE("%p\n", map);
@@ -233,14 +241,17 @@ static HRESULT Map_clear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigne return S_OK; }
-static HRESULT Map_delete(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Map_delete(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsval_t key = argc >= 1 ? argv[0] : jsval_undefined(); struct jsval_map_entry *entry; MapInstance *map; + HRESULT hres;
- if(!(map = get_map_this(jsthis))) return JS_E_MAP_EXPECTED; + hres = get_map_this(vthis, &map); + if(FAILED(hres)) + return hres;
TRACE("%p (%s)\n", map, debugstr_jsval(key));
@@ -249,7 +260,7 @@ static HRESULT Map_delete(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsign return S_OK; }
-static HRESULT Map_forEach(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Map_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsval_t callback = argc ? argv[0] : jsval_undefined(); @@ -257,7 +268,9 @@ static HRESULT Map_forEach(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig MapInstance *map; HRESULT hres;
- if(!(map = get_map_this(jsthis))) return JS_E_MAP_EXPECTED; + hres = get_map_this(vthis, &map); + if(FAILED(hres)) + return hres;
TRACE("%p (%s)\n", map, debugstr_jsval(argc >= 1 ? argv[0] : jsval_undefined()));
@@ -290,14 +303,17 @@ static HRESULT Map_forEach(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig return S_OK; }
-static HRESULT Map_get(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Map_get(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsval_t key = argc >= 1 ? argv[0] : jsval_undefined(); struct jsval_map_entry *entry; MapInstance *map; + HRESULT hres;
- if(!(map = get_map_this(jsthis))) return JS_E_MAP_EXPECTED; + hres = get_map_this(vthis, &map); + if(FAILED(hres)) + return hres;
TRACE("%p (%s)\n", map, debugstr_jsval(key));
@@ -309,7 +325,7 @@ static HRESULT Map_get(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned return r ? jsval_copy(entry->value, r) : S_OK; }
-static HRESULT Map_set(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Map_set(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsval_t key = argc >= 1 ? argv[0] : jsval_undefined(); @@ -318,7 +334,9 @@ static HRESULT Map_set(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned MapInstance *map; HRESULT hres;
- if(!(map = get_map_this(jsthis))) return JS_E_MAP_EXPECTED; + hres = get_map_this(vthis, &map); + if(FAILED(hres)) + return hres;
TRACE("%p (%s %s)\n", map, debugstr_jsval(key), debugstr_jsval(value));
@@ -353,14 +371,17 @@ static HRESULT Map_set(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned return S_OK; }
-static HRESULT Map_has(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Map_has(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsval_t key = argc >= 1 ? argv[0] : jsval_undefined(); struct jsval_map_entry *entry; MapInstance *map; + HRESULT hres;
- if(!(map = get_map_this(jsthis))) return JS_E_MAP_EXPECTED; + hres = get_map_this(vthis, &map); + if(FAILED(hres)) + return hres;
TRACE("%p (%s)\n", map, debugstr_jsval(key));
@@ -379,7 +400,7 @@ static HRESULT Map_get_size(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) return S_OK; }
-static HRESULT Map_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Map_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); @@ -430,7 +451,7 @@ static const builtin_info_t Map_info = { NULL };
-static HRESULT Map_constructor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Map_constructor(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { MapInstance *map; diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 5958216..70bef38 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -36,33 +36,32 @@ static inline StringInstance *string_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, StringInstance, dispex); }
-static inline StringInstance *string_from_vdisp(vdisp_t *vdisp) +static inline StringInstance *string_this(jsval_t vthis) { - return string_from_jsdisp(vdisp->u.jsdisp); + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_STRING)) ? string_from_jsdisp(jsdisp) : NULL; }
-static inline StringInstance *string_this(vdisp_t *jsthis) -{ - return is_vclass(jsthis, JSCLASS_STRING) ? string_from_vdisp(jsthis) : NULL; -} - -static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **val) +static HRESULT get_string_val(script_ctx_t *ctx, jsval_t vthis, jsstr_t **val) { StringInstance *string;
- if((string = string_this(jsthis))) { + if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + + if((string = string_this(vthis))) { *val = jsstr_addref(string->str); return S_OK; }
- return to_string(ctx, jsval_disp(jsthis->u.disp), val); + return to_string(ctx, vthis, val); }
-static HRESULT get_string_flat_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **jsval, const WCHAR **val) +static HRESULT get_string_flat_val(script_ctx_t *ctx, jsval_t vthis, jsstr_t **jsval, const WCHAR **val) { HRESULT hres;
- hres = get_string_val(ctx, jsthis, jsval); + hres = get_string_val(ctx, vthis, jsval); if(FAILED(hres)) return hres;
@@ -84,11 +83,11 @@ static HRESULT String_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r return S_OK; }
-static HRESULT stringobj_to_string(vdisp_t *jsthis, jsval_t *r) +static HRESULT stringobj_to_string(jsval_t vthis, jsval_t *r) { StringInstance *string;
- if(!(string = string_this(jsthis))) { + if(!(string = string_this(vthis))) { WARN("this is not a string object\n"); return E_FAIL; } @@ -99,31 +98,31 @@ static HRESULT stringobj_to_string(vdisp_t *jsthis, jsval_t *r) }
/* ECMA-262 3rd Edition 15.5.4.2 */ -static HRESULT String_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n");
- return stringobj_to_string(jsthis, r); + return stringobj_to_string(vthis, r); }
/* ECMA-262 3rd Edition 15.5.4.2 */ -static HRESULT String_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_valueOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n");
- return stringobj_to_string(jsthis, r); + return stringobj_to_string(vthis, r); }
-static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r, const WCHAR *tagname) +static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, jsval_t vthis, jsval_t *r, const WCHAR *tagname) { unsigned tagname_len; jsstr_t *str, *ret; WCHAR *ptr; HRESULT hres;
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -158,13 +157,13 @@ static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, j return S_OK; }
-static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, unsigned argc, jsval_t *argv, jsval_t *r, +static HRESULT do_attribute_tag_format(script_ctx_t *ctx, jsval_t vthis, unsigned argc, jsval_t *argv, jsval_t *r, const WCHAR *tagname, const WCHAR *attrname) { jsstr_t *str, *attr_value = NULL; HRESULT hres;
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -216,32 +215,32 @@ static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, unsig return hres; }
-static HRESULT String_anchor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_anchor(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attribute_tag_format(ctx, jsthis, argc, argv, r, L"A", L"NAME"); + return do_attribute_tag_format(ctx, vthis, argc, argv, r, L"A", L"NAME"); }
-static HRESULT String_big(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_big(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"BIG"); + return do_attributeless_tag_format(ctx, vthis, r, L"BIG"); }
-static HRESULT String_blink(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_blink(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"BLINK"); + return do_attributeless_tag_format(ctx, vthis, r, L"BLINK"); }
-static HRESULT String_bold(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_bold(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"B"); + return do_attributeless_tag_format(ctx, vthis, r, L"B"); }
/* ECMA-262 3rd Edition 15.5.4.5 */ -static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_charAt(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *str, *ret; @@ -250,7 +249,7 @@ static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
TRACE("\n");
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -283,7 +282,7 @@ static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns }
/* ECMA-262 3rd Edition 15.5.4.5 */ -static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_charCodeAt(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *str; @@ -292,7 +291,7 @@ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -326,7 +325,7 @@ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition 15.5.4.6 */ -static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_concat(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *ret = NULL, *str; @@ -334,7 +333,7 @@ static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
TRACE("\n");
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -411,25 +410,25 @@ static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns return S_OK; }
-static HRESULT String_fixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_fixed(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"TT"); + return do_attributeless_tag_format(ctx, vthis, r, L"TT"); }
-static HRESULT String_fontcolor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_fontcolor(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attribute_tag_format(ctx, jsthis, argc, argv, r, L"FONT", L"COLOR"); + return do_attribute_tag_format(ctx, vthis, argc, argv, r, L"FONT", L"COLOR"); }
-static HRESULT String_fontsize(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_fontsize(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attribute_tag_format(ctx, jsthis, argc, argv, r, L"FONT", L"SIZE"); + return do_attribute_tag_format(ctx, vthis, argc, argv, r, L"FONT", L"SIZE"); }
-static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_indexOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { unsigned pos = 0, search_len, length; @@ -440,7 +439,7 @@ static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
TRACE("\n");
- hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); + hres = get_string_flat_val(ctx, vthis, &jsstr, &str); if(FAILED(hres)) return hres;
@@ -490,14 +489,14 @@ static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un return S_OK; }
-static HRESULT String_italics(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_italics(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"I"); + return do_attributeless_tag_format(ctx, vthis, r, L"I"); }
/* ECMA-262 3rd Edition 15.5.4.8 */ -static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_lastIndexOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { unsigned pos = 0, search_len, length; @@ -508,7 +507,7 @@ static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
TRACE("\n");
- hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); + hres = get_string_flat_val(ctx, vthis, &jsstr, &str); if(FAILED(hres)) return hres;
@@ -559,14 +558,14 @@ static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags return S_OK; }
-static HRESULT String_link(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_link(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attribute_tag_format(ctx, jsthis, argc, argv, r, L"A", L"HREF"); + return do_attribute_tag_format(ctx, vthis, argc, argv, r, L"A", L"HREF"); }
/* ECMA-262 3rd Edition 15.5.4.10 */ -static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_match(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *regexp = NULL; @@ -602,7 +601,7 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi return hres; }
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(SUCCEEDED(hres)) hres = regexp_string_match(ctx, regexp, str, r);
@@ -718,7 +717,7 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, }
/* ECMA-262 3rd Edition 15.5.4.11 */ -static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_replace(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { const WCHAR *str, *match_str = NULL, *rep_str = NULL; @@ -732,7 +731,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
TRACE("\n");
- hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); + hres = get_string_flat_val(ctx, vthis, &jsstr, &str); if(FAILED(hres)) return hres;
@@ -938,7 +937,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un return hres; }
-static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_search(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *regexp = NULL; @@ -949,7 +948,7 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
TRACE("\n");
- hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); + hres = get_string_flat_val(ctx, vthis, &jsstr, &str); if(FAILED(hres)) return hres;
@@ -989,7 +988,7 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns }
/* ECMA-262 3rd Edition 15.5.4.13 */ -static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_slice(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { int start=0, end, length; @@ -999,7 +998,7 @@ static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
TRACE("\n");
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -1065,13 +1064,13 @@ static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi return S_OK; }
-static HRESULT String_small(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_small(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"SMALL"); + return do_attributeless_tag_format(ctx, vthis, r, L"SMALL"); }
-static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_split(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { match_state_t match_result, *match_ptr = &match_result; @@ -1082,7 +1081,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi jsstr_t *jsstr, *match_jsstr, *tmp_str; HRESULT hres;
- hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); + hres = get_string_flat_val(ctx, vthis, &jsstr, &str); if(FAILED(hres)) return hres; length = jsstr_length(jsstr); @@ -1231,20 +1230,20 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi return hres; }
-static HRESULT String_strike(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_strike(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"STRIKE"); + return do_attributeless_tag_format(ctx, vthis, r, L"STRIKE"); }
-static HRESULT String_sub(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_sub(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"SUB"); + return do_attributeless_tag_format(ctx, vthis, r, L"SUB"); }
/* ECMA-262 3rd Edition 15.5.4.15 */ -static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_substring(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { INT start=0, end, length; @@ -1254,7 +1253,7 @@ static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -1303,7 +1302,7 @@ static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, }
/* ECMA-262 3rd Edition B.2.3 */ -static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_substr(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { int start=0, len, length; @@ -1313,7 +1312,7 @@ static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
TRACE("\n");
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -1357,19 +1356,19 @@ static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns return hres; }
-static HRESULT String_sup(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_sup(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - return do_attributeless_tag_format(ctx, jsthis, r, L"SUP"); + return do_attributeless_tag_format(ctx, vthis, r, L"SUP"); }
-static HRESULT to_upper_case(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r) +static HRESULT to_upper_case(script_ctx_t *ctx, jsval_t vthis, jsval_t *r) { jsstr_t *str; HRESULT hres;
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -1393,13 +1392,13 @@ static HRESULT to_upper_case(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r) return S_OK; }
-static HRESULT to_lower_case(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r) +static HRESULT to_lower_case(script_ctx_t *ctx, jsval_t vthis, jsval_t *r) { jsstr_t *str; HRESULT hres;
- hres = get_string_val(ctx, jsthis, &str); + hres = get_string_val(ctx, vthis, &str); if(FAILED(hres)) return hres;
@@ -1423,35 +1422,35 @@ static HRESULT to_lower_case(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r) return S_OK; }
-static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_toLowerCase(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return to_lower_case(ctx, jsthis, r); + return to_lower_case(ctx, vthis, r); }
-static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_toUpperCase(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return to_upper_case(ctx, jsthis, r); + return to_upper_case(ctx, vthis, r); }
-static HRESULT String_toLocaleLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_toLocaleLowerCase(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return to_lower_case(ctx, jsthis, r); + return to_lower_case(ctx, vthis, r); }
-static HRESULT String_toLocaleUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_toLocaleUpperCase(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); - return to_upper_case(ctx, jsthis, r); + return to_upper_case(ctx, vthis, r); }
-static HRESULT String_trim(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, +static HRESULT String_trim(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { const WCHAR *str, *begin, *end; @@ -1459,7 +1458,10 @@ static HRESULT String_trim(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig unsigned len; HRESULT hres;
- hres = to_flat_string(ctx, jsval_disp(jsthis->u.disp), &jsstr, &str); + if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED; + + hres = to_flat_string(ctx, vthis, &jsstr, &str); if(FAILED(hres)) { WARN("to_flat_string failed: %08x\n", hres); return hres; @@ -1486,7 +1488,7 @@ static HRESULT String_trim(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig return hres; }
-static HRESULT String_localeCompare(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT String_localeCompare(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); @@ -1592,7 +1594,7 @@ static const builtin_info_t StringInst_info = { };
/* ECMA-262 3rd Edition 15.5.3.2 */ -static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, +static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { WCHAR *ret_str; @@ -1623,7 +1625,7 @@ static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WOR return S_OK; }
-static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT StringConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { HRESULT hres; diff --git a/dlls/jscript/vbarray.c b/dlls/jscript/vbarray.c index 41faa20..0198030 100644 --- a/dlls/jscript/vbarray.c +++ b/dlls/jscript/vbarray.c @@ -33,17 +33,13 @@ static inline VBArrayInstance *vbarray_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, VBArrayInstance, dispex); }
-static inline VBArrayInstance *vbarray_from_vdisp(vdisp_t *vdisp) +static inline VBArrayInstance *vbarray_this(jsval_t vthis) { - return vbarray_from_jsdisp(vdisp->u.jsdisp); + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, JSCLASS_VBARRAY)) ? vbarray_from_jsdisp(jsdisp) : NULL; }
-static inline VBArrayInstance *vbarray_this(vdisp_t *jsthis) -{ - return is_vclass(jsthis, JSCLASS_VBARRAY) ? vbarray_from_vdisp(jsthis) : NULL; -} - -static HRESULT VBArray_dimensions(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT VBArray_dimensions(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { VBArrayInstance *vbarray; @@ -59,7 +55,7 @@ static HRESULT VBArray_dimensions(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, return S_OK; }
-static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT VBArray_getItem(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { VBArrayInstance *vbarray; @@ -102,7 +98,7 @@ static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, un return hres; }
-static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT VBArray_lbound(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { VBArrayInstance *vbarray; @@ -133,7 +129,7 @@ static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, uns return S_OK; }
-static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT VBArray_toArray(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { VBArrayInstance *vbarray; @@ -188,7 +184,7 @@ static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, un return S_OK; }
-static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT VBArray_ubound(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { VBArrayInstance *vbarray; @@ -219,7 +215,7 @@ static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, uns return S_OK; }
-static HRESULT VBArray_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT VBArray_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FIXME("\n"); @@ -281,7 +277,7 @@ static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBAr return S_OK; }
-static HRESULT VBArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT VBArrayConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { VBArrayInstance *vbarray;
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
-static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) {
- jsdisp_t *jsdisp;
jsdisp_t *jsthis, *jsdisp; BOOL ret = FALSE;
if(!is_object_instance(vthis))
return JS_E_OBJECT_EXPECTED;
This is not what spec says. I caught this one, but it shows a wider problem: a ton of builtin functions are supposed to call to_object on this argument. With later patches, they will start failing instead. In fact, to_object on this argument is so common that maybe we could continue doing that before calling the function based on some flag in the description, opt-in or opt-out. Did you review the spec in that context?
Thanks,
Jacek
On 03/12/2021 17:01, Jacek Caban wrote:
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
-static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - jsdisp_t *jsdisp; + jsdisp_t *jsthis, *jsdisp; BOOL ret = FALSE; + if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED;
This is not what spec says. I caught this one, but it shows a wider problem: a ton of builtin functions are supposed to call to_object on this argument. With later patches, they will start failing instead. In fact, to_object on this argument is so common that maybe we could continue doing that before calling the function based on some flag in the description, opt-in or opt-out. Did you review the spec in that context?
So basically all functions should have to_object called except for toString, right? Or at least, first (no-op) patch will have them all call to_object so it is like now, and then we can selectively enable to pass raw value instead?
On 12/3/21 7:24 PM, Gabriel Ivăncescu wrote:
On 03/12/2021 17:01, Jacek Caban wrote:
Hi Gabriel,
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
-static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, +static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - jsdisp_t *jsdisp; + jsdisp_t *jsthis, *jsdisp; BOOL ret = FALSE; + if(!is_object_instance(vthis)) + return JS_E_OBJECT_EXPECTED;
This is not what spec says. I caught this one, but it shows a wider problem: a ton of builtin functions are supposed to call to_object on this argument. With later patches, they will start failing instead. In fact, to_object on this argument is so common that maybe we could continue doing that before calling the function based on some flag in the description, opt-in or opt-out. Did you review the spec in that context?
So basically all functions should have to_object called except for toString, right?
I don't think it's the only one. At very least some functions don't care about 'this' argument.
Or at least, first (no-op) patch will have them all call to_object so it is like now, and then we can selectively enable to pass raw value instead?
That's likely, but a closer look at spec is needed to analyse what exactly we will need.
Jacek
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/function.c | 2 +- dlls/jscript/tests/api.js | 22 +++++++++++++++++ dlls/mshtml/tests/es5.js | 52 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 3730915..43f2441 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -599,7 +599,7 @@ static HRESULT NativeFunction_call(script_ctx_t *ctx, FunctionInstance *func, ID if(this_disp) vthis = jsval_disp(this_disp); else - vthis = jsval_disp(lookup_global_host(ctx)); + vthis = jsval_null();
return function->proc(ctx, vthis, flags & ~DISPATCH_JSCRIPT_INTERNAL_MASK, argc, argv, r); } diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index d5d8e7d..07a15f3 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -3061,6 +3061,28 @@ ok(unescape.length == 1, "unescape.length = " + unescape.length); String.length = 3; ok(String.length == 1, "String.length = " + String.length);
+try { + Array.prototype.sort.call(null); + ok(false, "expected exception calling Array.sort with null context"); +}catch(e) { + var n = e.number + 0x100000000; + ok(n === 0x800a138f, "Array.sort with null context exception code = " + n); +} +try { + Array.prototype.sort.call(undefined); + ok(false, "expected exception calling Array.sort with undefined context"); +}catch(e) { + var n = e.number + 0x100000000; + ok(n === 0x800a138f, "Array.sort with undefined context exception code = " + n); +} +try { + Object.prototype.isPrototypeOf.call(null, Object); + ok(false, "expected exception calling Object.isPrototypeOf with null context"); +}catch(e) { + var n = e.number + 0x100000000; + ok(n === 0x800a138f, "Object.isPrototypeOf with null context exception code = " + n); +} + var tmp = createArray(); ok(getVT(tmp) == "VT_ARRAY|VT_VARIANT", "getVT(createArray()) = " + getVT(tmp)); ok(getVT(VBArray(tmp)) == "VT_ARRAY|VT_VARIANT", "getVT(VBArray(tmp)) = " + getVT(VBArray(tmp))); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 58b0d43..d6d52df 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -17,6 +17,14 @@ */
var JS_E_PROP_DESC_MISMATCH = 0x800a01bd; +var JS_E_NUMBER_EXPECTED = 0x800a1389; +var JS_E_FUNCTION_EXPECTED = 0x800a138a; +var JS_E_DATE_EXPECTED = 0x800a138e; +var JS_E_OBJECT_EXPECTED = 0x800a138f; +var JS_E_BOOLEAN_EXPECTED = 0x800a1392; +var JS_E_VBARRAY_EXPECTED = 0x800a1395; +var JS_E_ENUMERATOR_EXPECTED = 0x800a1397; +var JS_E_REGEXP_EXPECTED = 0x800a1398; var JS_E_INVALID_WRITABLE_PROP_DESC = 0x800a13ac; var JS_E_NONCONFIGURABLE_REDEFINED = 0x800a13d6; var JS_E_NONWRITABLE_MODIFIED = 0x800a13d7; @@ -1222,6 +1230,50 @@ sync_test("isFrozen", function() { ok(Object.isExtensible(o) === false, "o is extensible"); });
+sync_test("builtin_context", function() { + var tests = [ + [ "Array.map", JS_E_OBJECT_EXPECTED, function(ctx) { Array.prototype.map.call(ctx, function(a, b) {}); } ], + [ "Array.sort", JS_E_OBJECT_EXPECTED, function(ctx) { Array.prototype.sort.call(ctx); } ], + [ "Boolean.toString", JS_E_BOOLEAN_EXPECTED, function(ctx) { Boolean.prototype.toString.call(ctx); } ], + [ "Date.getTime", JS_E_DATE_EXPECTED, function(ctx) { Date.prototype.getTime.call(ctx); } ], + [ "Date.toGMTString", JS_E_DATE_EXPECTED, function(ctx) { Date.prototype.toGMTString.call(ctx); } ], + [ "Enumerator.item", JS_E_ENUMERATOR_EXPECTED, function(ctx) { Enumerator.prototype.item.call(ctx); } ], + [ "Error.toString", JS_E_OBJECT_EXPECTED, function(ctx) { Error.prototype.toString.call(ctx); } ], + [ "Function.call", JS_E_FUNCTION_EXPECTED, function(ctx) { Function.prototype.call.call(ctx, function() {}); } ], + [ "Map.clear", JS_E_OBJECT_EXPECTED, function(ctx) { Map.prototype.clear.call(ctx); } ], + [ "Number.toFixed", JS_E_NUMBER_EXPECTED, function(ctx) { Number.prototype.toFixed.call(ctx); } ], + [ "Object.isPrototypeOf", JS_E_OBJECT_EXPECTED, function(ctx) { Object.prototype.isPrototypeOf.call(ctx, Object); } ], + [ "RegExp.exec", JS_E_REGEXP_EXPECTED, function(ctx) { RegExp.prototype.exec.call(ctx, "foobar"); } ], + [ "String.search", JS_E_OBJECT_EXPECTED, function(ctx) { String.prototype.search.call(ctx, /foobar/g); } ], + [ "VBArray.dimensions", JS_E_VBARRAY_EXPECTED, function(ctx) { VBArray.prototype.dimensions.call(ctx); } ] + ]; + + /* make global object suitable for some calls */ + window[0] = "foo"; + window[1] = "bar"; + window.length = 2; + + for(var i = 0; i < tests.length; i++) { + try { + tests[i][2](null); + ok(false, "expected exception calling " + tests[i][0] + " with null context"); + }catch(ex) { + var n = ex.number + 0x100000000; /* make it unsigned like HRESULT */ + ok(n === tests[i][1], tests[i][0] + " with null context exception code = " + n); + } + try { + tests[i][2](undefined); + ok(false, "expected exception calling " + tests[i][0] + " with undefined context"); + }catch(ex) { + var n = ex.number + 0x100000000; + ok(n === tests[i][1], tests[i][0] + " with undefined context exception code = " + n); + } + } + + var obj = (function() { return this; }).call(null); + ok(obj === window, "obj = " + obj); +}); + sync_test("head_setter", function() { document.head = ""; ok(typeof(document.head) === "object", "typeof(document.head) = " + typeof(document.head));
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=103324
Your paranoid android.
=== w8adm (32 bit report) ===
mshtml: htmldoc.c:3084: Test failed: Incorrect error code: -2146697211 htmldoc.c:3089: Test failed: Page address: L"http://test.winehq.org/tests/winehq_snapshot/" htmldoc.c:5861: Test failed: expected OnChanged_1012 htmldoc.c:5862: Test failed: expected Exec_HTTPEQUIV htmldoc.c:5864: Test failed: expected Exec_SETTITLE htmldoc.c:5905: Test failed: expected FireNavigateComplete2
=== w1064_tsign (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
=== w10pro64_ar (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS
=== w10pro64_he (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
=== w10pro64_ja (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/object.c | 5 ++++- dlls/mshtml/tests/documentmode.js | 2 +- dlls/mshtml/tests/es5.js | 1 - 3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 96a52be..53f174d 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -55,7 +55,10 @@ static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns TRACE("\n");
if(!jsdisp) { - str = L"[object Object]"; + if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && is_null(vthis)) + str = L"[object Null]"; + else + str = L"[object Object]"; }else if(names[jsdisp->builtin_info->class]) { str = names[jsdisp->builtin_info->class]; }else { diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 2af5fae..8f96222 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1243,7 +1243,7 @@ sync_test("elem_attr", function() { r = elem.removeAttribute("ondblclick"); ok(r === (v < 8 ? false : (v < 9 ? true : undefined)), "ondblclick removeAttribute returned " + r); r = Object.prototype.toString.call(elem.ondblclick); - todo_wine_if(v >= 9). + todo_wine_if(v >= 11). ok(r === (v < 8 ? "[object Array]" : (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]"))), "removed ondblclick Object.toString returned " + r);
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index d6d52df..dd34c9d 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -805,7 +805,6 @@ sync_test("toString", function() { todo_wine. ok(tmp === "[object Window]", "toString.call(null) = " + tmp); tmp = Object.prototype.toString.call(null); - todo_wine. ok(tmp === "[object Null]", "toString.call(null) = " + tmp); tmp = Object.prototype.toString.call(undefined); todo_wine.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=103325
Your paranoid android.
=== w8 (32 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS htmldoc.c:350: Test failed: expected Exec_SETTITLE htmldoc.c:2859: Test failed: unexpected call Exec_SETTITLE
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/function.c | 57 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 26 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 43f2441..80b8d9c 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -35,7 +35,7 @@ typedef struct { } FunctionInstance;
struct _function_vtbl_t { - HRESULT (*call)(script_ctx_t*,FunctionInstance*,IDispatch*,unsigned,unsigned,jsval_t*,jsval_t*); + HRESULT (*call)(script_ctx_t*,FunctionInstance*,jsval_t,unsigned,unsigned,jsval_t*,jsval_t*); HRESULT (*toString)(FunctionInstance*,jsstr_t**); function_code_t* (*get_code)(FunctionInstance*); void (*destructor)(FunctionInstance*); @@ -256,7 +256,7 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi assert(is_class(func_this, JSCLASS_FUNCTION)); function = function_from_jsdisp(func_this);
- return function->vtbl->call(function->dispex.ctx, function, jsthis, flags, argc, argv, r); + return function->vtbl->call(function->dispex.ctx, function, jsval_disp(jsthis), flags, argc, argv, r); }
static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) @@ -331,8 +331,8 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi FunctionInstance *function; jsval_t *args = NULL; unsigned i, cnt = 0; - IDispatch *this_obj = NULL; HRESULT hres = S_OK; + jsval_t this_val;
TRACE("\n");
@@ -341,11 +341,15 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi
if(argc) { if(!is_undefined(argv[0]) && !is_null(argv[0])) { + IDispatch *this_obj; hres = to_object(ctx, argv[0], &this_obj); if(FAILED(hres)) return hres; - } - } + this_val = jsval_disp(this_obj); + }else + this_val = argv[0]; + }else + this_val = jsval_undefined();
if(argc >= 2) { jsdisp_t *arg_array = NULL; @@ -370,10 +374,11 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi
if(SUCCEEDED(hres)) { if(function) { - hres = function->vtbl->call(ctx, function, this_obj, flags, cnt, args, r); + hres = function->vtbl->call(ctx, function, this_val, flags, cnt, args, r); }else { jsval_t res; - hres = disp_call_value(ctx, get_object(vthis), this_obj, DISPATCH_METHOD, cnt, args, &res); + hres = disp_call_value(ctx, get_object(vthis), is_object_instance(this_val) ? get_object(this_val) : NULL, + DISPATCH_METHOD, cnt, args, &res); if(SUCCEEDED(hres)) { if(r) *r = res; @@ -383,8 +388,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi } }
- if(this_obj) - IDispatch_Release(this_obj); + jsval_release(this_val); for(i=0; i < cnt; i++) jsval_release(args[i]); heap_free(args); @@ -395,8 +399,8 @@ static HRESULT Function_call(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig jsval_t *r) { FunctionInstance *function; - IDispatch *this_obj = NULL; unsigned cnt = 0; + jsval_t this_val; HRESULT hres;
TRACE("\n"); @@ -406,18 +410,21 @@ static HRESULT Function_call(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig
if(argc) { if(!is_undefined(argv[0]) && !is_null(argv[0])) { + IDispatch *this_obj; hres = to_object(ctx, argv[0], &this_obj); if(FAILED(hres)) return hres; - } + this_val = jsval_disp(this_obj); + }else + this_val = argv[0];
cnt = argc-1; - } + }else + this_val = jsval_undefined();
- hres = function->vtbl->call(ctx, function, this_obj, flags, cnt, argv + 1, r); + hres = function->vtbl->call(ctx, function, this_val, flags, cnt, argv + 1, r);
- if(this_obj) - IDispatch_Release(this_obj); + jsval_release(this_val); return hres; }
@@ -469,7 +476,7 @@ HRESULT Function_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned ar return E_FAIL; }
- return function->vtbl->call(ctx, function, NULL, flags, argc, argv, r); + return function->vtbl->call(ctx, function, vthis, flags, argc, argv, r); }
HRESULT Function_get_value(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) @@ -590,16 +597,10 @@ static HRESULT create_function(script_ctx_t *ctx, const builtin_info_t *builtin_ return S_OK; }
-static HRESULT NativeFunction_call(script_ctx_t *ctx, FunctionInstance *func, IDispatch *this_disp, unsigned flags, +static HRESULT NativeFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsval_t vthis, unsigned flags, unsigned argc, jsval_t *argv, jsval_t *r) { NativeFunction *function = (NativeFunction*)func; - jsval_t vthis; - - if(this_disp) - vthis = jsval_disp(this_disp); - else - vthis = jsval_null();
return function->proc(ctx, vthis, flags & ~DISPATCH_JSCRIPT_INTERNAL_MASK, argc, argv, r); } @@ -698,10 +699,11 @@ HRESULT create_builtin_constructor(script_ctx_t *ctx, builtin_invoke_t value_pro return S_OK; }
-static HRESULT InterpretedFunction_call(script_ctx_t *ctx, FunctionInstance *func, IDispatch *this_obj, unsigned flags, +static HRESULT InterpretedFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsval_t vthis, unsigned flags, unsigned argc, jsval_t *argv, jsval_t *r) { InterpretedFunction *function = (InterpretedFunction*)func; + IDispatch *this_obj = NULL; jsdisp_t *new_obj = NULL; DWORD exec_flags = 0; HRESULT hres; @@ -718,6 +720,8 @@ static HRESULT InterpretedFunction_call(script_ctx_t *ctx, FunctionInstance *fun if(FAILED(hres)) return hres; this_obj = to_disp(new_obj); + }else if(is_object_instance(vthis)) { + this_obj = get_object(vthis); }
if(flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) @@ -801,7 +805,7 @@ HRESULT create_source_function(script_ctx_t *ctx, bytecode_t *code, function_cod return S_OK; }
-static HRESULT BindFunction_call(script_ctx_t *ctx, FunctionInstance *func, IDispatch *this_obj, unsigned flags, +static HRESULT BindFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsval_t vthis, unsigned flags, unsigned argc, jsval_t *argv, jsval_t *r) { BindFunction *function = (BindFunction*)func; @@ -823,7 +827,8 @@ static HRESULT BindFunction_call(script_ctx_t *ctx, FunctionInstance *func, IDis memcpy(call_args + function->argc, argv, argc * sizeof(*call_args)); }
- hres = function->target->vtbl->call(ctx, function->target, function->this, flags, call_argc, call_args, r); + hres = function->target->vtbl->call(ctx, function->target, jsval_disp(function->this), + flags, call_argc, call_args, r);
heap_free(call_args); return hres;
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/jscript/function.c | 57 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 26 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 43f2441..80b8d9c 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -35,7 +35,7 @@ typedef struct { } FunctionInstance;
struct _function_vtbl_t {
- HRESULT (*call)(script_ctx_t*,FunctionInstance*,IDispatch*,unsigned,unsigned,jsval_t*,jsval_t*);
- HRESULT (*call)(script_ctx_t*,FunctionInstance*,jsval_t,unsigned,unsigned,jsval_t*,jsval_t*); HRESULT (*toString)(FunctionInstance*,jsstr_t**); function_code_t* (*get_code)(FunctionInstance*); void (*destructor)(FunctionInstance*);
@@ -256,7 +256,7 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi assert(is_class(func_this, JSCLASS_FUNCTION)); function = function_from_jsdisp(func_this);
- return function->vtbl->call(function->dispex.ctx, function, jsthis, flags, argc, argv, r);
return function->vtbl->call(function->dispex.ctx, function, jsval_disp(jsthis), flags, argc, argv, r); }
static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
@@ -331,8 +331,8 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi FunctionInstance *function; jsval_t *args = NULL; unsigned i, cnt = 0;
- IDispatch *this_obj = NULL; HRESULT hres = S_OK;
jsval_t this_val;
TRACE("\n");
@@ -341,11 +341,15 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi
if(argc) { if(!is_undefined(argv[0]) && !is_null(argv[0])) {
IDispatch *this_obj; hres = to_object(ctx, argv[0], &this_obj); if(FAILED(hres)) return hres;
}
- }
this_val = jsval_disp(this_obj);
}else
this_val = argv[0];
- }else
this_val = jsval_undefined();
According to spec, this we should just always pass the original argument.
Jacek
On 03/12/2021 17:04, Jacek Caban wrote:
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/jscript/function.c | 57 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 26 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 43f2441..80b8d9c 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -35,7 +35,7 @@ typedef struct { } FunctionInstance; struct _function_vtbl_t { - HRESULT (*call)(script_ctx_t*,FunctionInstance*,IDispatch*,unsigned,unsigned,jsval_t*,jsval_t*);
+ HRESULT (*call)(script_ctx_t*,FunctionInstance*,jsval_t,unsigned,unsigned,jsval_t*,jsval_t*);
HRESULT (*toString)(FunctionInstance*,jsstr_t**); function_code_t* (*get_code)(FunctionInstance*); void (*destructor)(FunctionInstance*); @@ -256,7 +256,7 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi assert(is_class(func_this, JSCLASS_FUNCTION)); function = function_from_jsdisp(func_this); - return function->vtbl->call(function->dispex.ctx, function, jsthis, flags, argc, argv, r); + return function->vtbl->call(function->dispex.ctx, function, jsval_disp(jsthis), flags, argc, argv, r); } static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) @@ -331,8 +331,8 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi FunctionInstance *function; jsval_t *args = NULL; unsigned i, cnt = 0; - IDispatch *this_obj = NULL; HRESULT hres = S_OK; + jsval_t this_val; TRACE("\n"); @@ -341,11 +341,15 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi if(argc) { if(!is_undefined(argv[0]) && !is_null(argv[0])) { + IDispatch *this_obj; hres = to_object(ctx, argv[0], &this_obj); if(FAILED(hres)) return hres; - } - } + this_val = jsval_disp(this_obj); + }else + this_val = argv[0]; + }else + this_val = jsval_undefined();
According to spec, this we should just always pass the original argument.
Jacek
So the existing code is wrong? (I was trying to make it a no-op)
On 12/3/21 7:28 PM, Gabriel Ivăncescu wrote:
On 03/12/2021 17:04, Jacek Caban wrote:
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/jscript/function.c | 57 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 26 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 43f2441..80b8d9c 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -35,7 +35,7 @@ typedef struct { } FunctionInstance; struct _function_vtbl_t { - HRESULT (*call)(script_ctx_t*,FunctionInstance*,IDispatch*,unsigned,unsigned,jsval_t*,jsval_t*);
+ HRESULT (*call)(script_ctx_t*,FunctionInstance*,jsval_t,unsigned,unsigned,jsval_t*,jsval_t*);
HRESULT (*toString)(FunctionInstance*,jsstr_t**); function_code_t* (*get_code)(FunctionInstance*); void (*destructor)(FunctionInstance*); @@ -256,7 +256,7 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi assert(is_class(func_this, JSCLASS_FUNCTION)); function = function_from_jsdisp(func_this); - return function->vtbl->call(function->dispex.ctx, function, jsthis, flags, argc, argv, r); + return function->vtbl->call(function->dispex.ctx, function, jsval_disp(jsthis), flags, argc, argv, r); } static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) @@ -331,8 +331,8 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi FunctionInstance *function; jsval_t *args = NULL; unsigned i, cnt = 0; - IDispatch *this_obj = NULL; HRESULT hres = S_OK; + jsval_t this_val; TRACE("\n"); @@ -341,11 +341,15 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi if(argc) { if(!is_undefined(argv[0]) && !is_null(argv[0])) { + IDispatch *this_obj; hres = to_object(ctx, argv[0], &this_obj); if(FAILED(hres)) return hres; - } - } + this_val = jsval_disp(this_obj); + }else + this_val = argv[0]; + }else + this_val = jsval_undefined();
According to spec, this we should just always pass the original argument.
Jacek
So the existing code is wrong? (I was trying to make it a no-op)
It wasn't wrong [1]:
<quote>
The thisArg value is passed without modification as the this value. This is a change from Edition 3, where a undefined or null thisArg is replaced with the global object and ToObject is applied to all other values and that result is passed as the this value.
</quote>
Jacek
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/object.c | 2 ++ dlls/mshtml/tests/es5.js | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 53f174d..fcc2afb 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -57,6 +57,8 @@ static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns if(!jsdisp) { if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && is_null(vthis)) str = L"[object Null]"; + else if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && is_undefined(vthis)) + str = L"[object Undefined]"; else str = L"[object Object]"; }else if(names[jsdisp->builtin_info->class]) { diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index dd34c9d..bb7b32e 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -807,10 +807,8 @@ sync_test("toString", function() { tmp = Object.prototype.toString.call(null); ok(tmp === "[object Null]", "toString.call(null) = " + tmp); tmp = Object.prototype.toString.call(undefined); - todo_wine. ok(tmp === "[object Undefined]", "toString.call(undefined) = " + tmp); tmp = Object.prototype.toString.call(); - todo_wine. ok(tmp === "[object Undefined]", "toString.call() = " + tmp);
obj = Object.create(null);
On 12/3/21 2:57 PM, Gabriel Ivăncescu wrote:
diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 53f174d..fcc2afb 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -57,6 +57,8 @@ static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns if(!jsdisp) { if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && is_null(vthis)) str = L"[object Null]";
else if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && is_undefined(vthis))
str = L"[object Undefined]";
The fact that you need those version checks means that you miss a version check when calling those functions. I think that vthis should still always be an object for older modes.
Jacek
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=103327
Your paranoid android.
=== w10pro64_ja (64 bit report) ===
mshtml: htmldoc.c:2541: Test failed: unexpected call UpdateUI htmldoc.c:2853: Test failed: unexpected call Exec_UPDATECOMMANDS