From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
It will be useful for far more objects later down the line. --- dlls/mshtml/dispex.c | 6 +++--- dlls/mshtml/htmlstyle.c | 5 +---- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/mutation.c | 6 +----- 4 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 54e54cfdc96..8e09eae9a26 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -125,6 +125,8 @@ PRIVATE_TID_LIST #undef XDIID };
+const tid_t no_iface_tids[1] = { 0 }; + static HRESULT load_typelib(void) { WCHAR module_path[MAX_PATH + 3]; @@ -1053,13 +1055,11 @@ static const dispex_static_data_vtbl_t function_dispex_vtbl = { .invoke = function_invoke };
-static const tid_t function_iface_tids[] = {0}; - static dispex_static_data_t function_dispex = { "Function", &function_dispex_vtbl, NULL_tid, - function_iface_tids + no_iface_tids };
static func_disp_t *create_func_disp(DispatchEx *obj, func_info_t *info) diff --git a/dlls/mshtml/htmlstyle.c b/dlls/mshtml/htmlstyle.c index f1e30b6872d..c8aae897842 100644 --- a/dlls/mshtml/htmlstyle.c +++ b/dlls/mshtml/htmlstyle.c @@ -9764,14 +9764,11 @@ static const dispex_static_data_vtbl_t HTMLW3CComputedStyle_dispex_vtbl = { .unlink = CSSStyle_unlink };
-static const tid_t HTMLW3CComputedStyle_iface_tids[] = { - 0 -}; static dispex_static_data_t HTMLW3CComputedStyle_dispex = { "CSSStyleDeclaration", &HTMLW3CComputedStyle_dispex_vtbl, DispHTMLW3CComputedStyle_tid, - HTMLW3CComputedStyle_iface_tids, + no_iface_tids, CSSStyle_init_dispex_info };
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index a7a6a2ed0a2..af26447e24a 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -413,6 +413,8 @@ typedef struct { dispex_data_t *delayed_init_info; } dispex_static_data_t;
+extern const tid_t no_iface_tids[1]; + typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,WORD,DISPPARAMS*,VARIANT*, EXCEPINFO*,IServiceProvider*);
diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 4e0276fd5f6..3c1fc945e92 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -1275,15 +1275,11 @@ static dispex_static_data_vtbl_t mutation_observer_ctor_dispex_vtbl = { .value = mutation_observer_ctor_value };
-static const tid_t mutation_observer_ctor_iface_tids[] = { - 0 -}; - static dispex_static_data_t mutation_observer_ctor_dispex = { "Function", &mutation_observer_ctor_dispex_vtbl, NULL_tid, - mutation_observer_ctor_iface_tids + no_iface_tids };
HRESULT create_mutation_observer_ctor(compat_mode_t compat_mode, IDispatch **ret)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/omnavigator.c | 49 ++++++++++++++++++++---------- dlls/mshtml/tests/documentmode.js | 50 +++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 15 deletions(-)
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 900c4ee0ca7..ab6d0548172 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -24,6 +24,7 @@ #include "winbase.h" #include "winuser.h" #include "ole2.h" +#include "mshtmdid.h"
#include "wine/debug.h"
@@ -1520,15 +1521,21 @@ static const dispex_static_data_vtbl_t HTMLPerformanceTiming_dispex_vtbl = { .unlink = HTMLPerformanceTiming_unlink };
-static const tid_t HTMLPerformanceTiming_iface_tids[] = { - IHTMLPerformanceTiming_tid, - 0 -}; +static void HTMLPerformanceTiming_init_dispex_info(dispex_data_t *info, compat_mode_t mode) +{ + static const dispex_hook_t hooks[] = { + {DISPID_IHTMLPERFORMANCETIMING_TOJSON}, + {DISPID_UNKNOWN} + }; + dispex_info_add_interface(info, IHTMLPerformanceTiming_tid, mode < COMPAT_MODE_IE9 ? hooks : NULL); +} + static dispex_static_data_t HTMLPerformanceTiming_dispex = { "PerformanceTiming", &HTMLPerformanceTiming_dispex_vtbl, IHTMLPerformanceTiming_tid, - HTMLPerformanceTiming_iface_tids + no_iface_tids, + HTMLPerformanceTiming_init_dispex_info };
typedef struct { @@ -1641,15 +1648,21 @@ static const dispex_static_data_vtbl_t HTMLPerformanceNavigation_dispex_vtbl = { .unlink = HTMLPerformanceNavigation_unlink };
-static const tid_t HTMLPerformanceNavigation_iface_tids[] = { - IHTMLPerformanceNavigation_tid, - 0 -}; +static void HTMLPerformanceNavigation_init_dispex_info(dispex_data_t *info, compat_mode_t mode) +{ + static const dispex_hook_t hooks[] = { + {DISPID_IHTMLPERFORMANCENAVIGATION_TOJSON}, + {DISPID_UNKNOWN} + }; + dispex_info_add_interface(info, IHTMLPerformanceNavigation_tid, mode < COMPAT_MODE_IE9 ? hooks : NULL); +} + static dispex_static_data_t HTMLPerformanceNavigation_dispex = { "PerformanceNavigation", &HTMLPerformanceNavigation_dispex_vtbl, IHTMLPerformanceNavigation_tid, - HTMLPerformanceNavigation_iface_tids + no_iface_tids, + HTMLPerformanceNavigation_init_dispex_info };
typedef struct { @@ -1804,15 +1817,21 @@ static const dispex_static_data_vtbl_t HTMLPerformance_dispex_vtbl = { .unlink = HTMLPerformance_unlink };
-static const tid_t HTMLPerformance_iface_tids[] = { - IHTMLPerformance_tid, - 0 -}; +static void HTMLPerformance_init_dispex_info(dispex_data_t *info, compat_mode_t mode) +{ + static const dispex_hook_t hooks[] = { + {DISPID_IHTMLPERFORMANCE_TOJSON}, + {DISPID_UNKNOWN} + }; + dispex_info_add_interface(info, IHTMLPerformance_tid, mode < COMPAT_MODE_IE9 ? hooks : NULL); +} + static dispex_static_data_t HTMLPerformance_dispex = { "Performance", &HTMLPerformance_dispex_vtbl, IHTMLPerformance_tid, - HTMLPerformance_iface_tids + no_iface_tids, + HTMLPerformance_init_dispex_info };
HRESULT create_performance(HTMLInnerWindow *window, IHTMLPerformance **ret) diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 16f2056ba93..1394010966e 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -563,6 +563,56 @@ sync_test("domimpl_props", function() { test_exposed("createHTMLDocument", v >= 9); });
+sync_test("perf_props", function() { + var obj = window.performance, name = "Performance"; + var v = document.documentMode; + + function test_exposed(prop, expect) { + if(expect) + ok(prop in obj, prop + " not found in " + name + "."); + else + ok(!(prop in obj), prop + " found in " + name + "."); + } + + test_exposed("navigation", true); + test_exposed("timing", true); + test_exposed("toJSON", v >= 9); + test_exposed("toString", true); + + obj = window.performance.navigation, name = "PerformanceNavigation"; + + test_exposed("redirectCount", true); + test_exposed("type", true); + test_exposed("toJSON", v >= 9); + test_exposed("toString", true); + + obj = window.performance.timing, name = "PerformanceTiming"; + + test_exposed("connectEnd", true); + test_exposed("connectStart", true); + test_exposed("domComplete", true); + test_exposed("domContentLoadedEventEnd", true); + test_exposed("domContentLoadedEventStart", true); + test_exposed("domInteractive", true); + test_exposed("domLoading", true); + test_exposed("domainLookupEnd", true); + test_exposed("domainLookupStart", true); + test_exposed("fetchStart", true); + test_exposed("loadEventEnd", true); + test_exposed("loadEventStart", true); + test_exposed("msFirstPaint", true); + test_exposed("navigationStart", true); + test_exposed("redirectEnd", true); + test_exposed("redirectStart", true); + test_exposed("requestStart", true); + test_exposed("responseEnd", true); + test_exposed("responseStart", true); + test_exposed("unloadEventEnd", true); + test_exposed("unloadEventStart", true); + test_exposed("toJSON", v >= 9); + test_exposed("toString", true); +}); + sync_test("xhr_props", function() { var xhr = new XMLHttpRequest();
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Simplifies when it gets used more instead of having to declare it everytime.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 3 +-- dlls/mshtml/htmlstyle.c | 3 +-- dlls/mshtml/mshtml_private.h | 1 + 3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 8e09eae9a26..2bd2a1b9c63 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -34,6 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
#define MAX_ARGS 16
+DISPID propput_dispid = DISPID_PROPERTYPUT; static ExternalCycleCollectionParticipant dispex_ccp;
static CRITICAL_SECTION cs_dispex_static_data; @@ -1957,8 +1958,6 @@ HRESULT dispex_prop_get(DispatchEx *dispex, DISPID id, LCID lcid, VARIANT *r, EX
HRESULT dispex_prop_put(DispatchEx *dispex, DISPID id, LCID lcid, VARIANT *v, EXCEPINFO *ei, IServiceProvider *caller) { - static DISPID propput_dispid = DISPID_PROPERTYPUT; - switch(get_dispid_type(id)) { case DISPEXPROP_CUSTOM: { DISPPARAMS dp = { .cArgs = 1, .rgvarg = v, .cNamedArgs = 1, .rgdispidNamedArgs = &propput_dispid }; diff --git a/dlls/mshtml/htmlstyle.c b/dlls/mshtml/htmlstyle.c index c8aae897842..4aa3b5f039b 100644 --- a/dlls/mshtml/htmlstyle.c +++ b/dlls/mshtml/htmlstyle.c @@ -2869,13 +2869,12 @@ static HRESULT WINAPI HTMLStyle_setAttribute(IHTMLStyle *iface, BSTR strAttribut if(hres == S_OK) { VARIANT ret; - DISPID dispidNamed = DISPID_PROPERTYPUT; DISPPARAMS params;
params.cArgs = 1; params.rgvarg = &AttributeValue; params.cNamedArgs = 1; - params.rgdispidNamedArgs = &dispidNamed; + params.rgdispidNamedArgs = &propput_dispid;
hres = HTMLStyle_Invoke(iface, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, ¶ms, &ret, NULL, NULL); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index af26447e24a..5f329733c0d 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -414,6 +414,7 @@ typedef struct { } dispex_static_data_t;
extern const tid_t no_iface_tids[1]; +extern DISPID propput_dispid;
typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,WORD,DISPPARAMS*,VARIANT*, EXCEPINFO*,IServiceProvider*);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 13 ++++++++ dlls/jscript/jsdisp.idl | 1 + dlls/mshtml/dispex.c | 42 +++++++++++++++++++++++++ dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/omnavigator.c | 6 ++-- dlls/mshtml/tests/dom.c | 60 ++++++++++++++++++++++++++++++++++++ dlls/mshtml/tests/es5.js | 41 ++++++++++++++++++++++++ 7 files changed, 162 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 79aea60de9c..75089655356 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2304,6 +2304,18 @@ static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IWineJSDispatch *iface, IUnk return E_NOTIMPL; }
+static HRESULT WINAPI WineJSDispatch_CreateObject(IWineJSDispatch *iface, IWineJSDispatch **obj) +{ + jsdisp_t *This = impl_from_IWineJSDispatch(iface); + jsdisp_t *jsdisp; + HRESULT hres; + + hres = create_object(This->ctx, NULL, &jsdisp); + if(SUCCEEDED(hres)) + *obj = &jsdisp->IWineJSDispatch_iface; + return hres; +} + static void WINAPI WineJSDispatch_Free(IWineJSDispatch *iface) { jsdisp_t *This = impl_from_IWineJSDispatch(iface); @@ -2342,6 +2354,7 @@ static IWineJSDispatchVtbl DispatchExVtbl = { DispatchEx_GetNameSpaceParent, WineJSDispatch_Free, WineJSDispatch_GetScriptGlobal, + WineJSDispatch_CreateObject, };
jsdisp_t *as_jsdisp(IDispatch *disp) diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index f01ea95ce48..9e57a0836f2 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -45,6 +45,7 @@ interface IWineJSDispatch : IDispatchEx { void Free(); HRESULT GetScriptGlobal(IWineJSDispatchHost **ret); + HRESULT CreateObject(IWineJSDispatch **obj); }
[ diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 2bd2a1b9c63..8b0f7b9cc92 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2428,6 +2428,48 @@ static IWineJSDispatchHostVtbl JSDispatchHostVtbl = { JSDispatchHost_ToString, };
+HRESULT dispex_builtin_props_to_json(DispatchEx *dispex, VARIANT *ret) +{ + func_info_t *func, *end; + IWineJSDispatch *json; + HRESULT hres; + VARIANT var; + DISPID id; + DISPPARAMS dp = { 0 }, put_dp = { &var, &propput_dispid, 1, 1 }; + + if(!dispex->jsdisp) + return E_UNEXPECTED; + + hres = IWineJSDispatch_CreateObject(dispex->jsdisp, &json); + if(FAILED(hres)) + return hres; + + for(func = dispex->info->funcs, end = func + dispex->info->func_cnt; func < end; func++) { + if(func->func_disp_idx != -1) + continue; + if(!func->hook || (hres = func->hook(dispex, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL)) == S_FALSE) + hres = builtin_propget(dispex, func, &dp, &var); + + if(SUCCEEDED(hres)) { + hres = IWineJSDispatch_GetDispID(json, func->name, fdexNameEnsure | fdexNameCaseSensitive, &id); + if(SUCCEEDED(hres)) { + hres = IWineJSDispatch_InvokeEx(json, id, 0, DISPATCH_PROPERTYPUT, &put_dp, NULL, NULL, NULL); + } + VariantClear(&var); + } + if(FAILED(hres)) { + IWineJSDispatch_Release(json); + return hres; + } + } + + if(ret) { + V_VT(ret) = VT_DISPATCH; + V_DISPATCH(ret) = (IDispatch*)json; + } + return hres; +} + static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb) { DispatchEx *This = impl_from_IWineJSDispatchHost(p); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 5f329733c0d..638b23e1379 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -503,6 +503,7 @@ HRESULT dispex_get_dprop_ref(DispatchEx*,const WCHAR*,BOOL,VARIANT**); HRESULT get_dispids(tid_t,DWORD*,DISPID**); HRESULT remove_attribute(DispatchEx*,DISPID,VARIANT_BOOL*); HRESULT dispex_get_dynid(DispatchEx*,const WCHAR*,BOOL,DISPID*); +HRESULT dispex_builtin_props_to_json(DispatchEx*,VARIANT*); void release_typelib(void); HRESULT get_class_typeinfo(const CLSID*,ITypeInfo**); const void *dispex_get_vtbl(DispatchEx*); diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index ab6d0548172..ccbd9c95538 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1439,8 +1439,10 @@ static HRESULT WINAPI HTMLPerformanceTiming_toString(IHTMLPerformanceTiming *ifa static HRESULT WINAPI HTMLPerformanceTiming_toJSON(IHTMLPerformanceTiming *iface, VARIANT *p) { HTMLPerformanceTiming *This = impl_from_IHTMLPerformanceTiming(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + return dispex_builtin_props_to_json(&This->dispex, p); }
static const IHTMLPerformanceTimingVtbl HTMLPerformanceTimingVtbl = { diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 8383f167cdd..65b9e3aa21c 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -52,6 +52,16 @@ static enum { static const char doc_blank[] = "<html></html>";
+static const char doc_blank_ie8[] = + "<!DOCTYPE html>\n" + "<html>" + " <head>" + " <meta http-equiv="x-ua-compatible" content="IE=8" />" + " </head>" + " <body>" + " </body>" + "</html>"; + static const char doc_blank_ie9[] = "<!DOCTYPE html>\n" "<html>" @@ -11217,6 +11227,54 @@ static void test_quirks_mode_offsetHeight(IHTMLDocument2 *doc) IHTMLElement_Release(elem); }
+static void test_quirks_mode_perf_toJSON(IHTMLDocument2 *doc) +{ + IHTMLPerformanceTiming *timing; + IHTMLPerformance *perf; + DISPPARAMS dp = { 0 }; + IHTMLWindow2 *window; + IDispatchEx *dispex; + DISPID dispid; + HRESULT hres; + VARIANT var; + BSTR bstr; + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "QueryInterface(IID_IDispatchEx) failed: %08lx\n", hres); + IHTMLWindow2_Release(window); + + bstr = SysAllocString(L"performance"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok(hres == S_OK, "GetDispID(performance) failed: %08lx\n", hres); + SysFreeString(bstr); + + V_VT(&var) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok(hres == S_OK, "InvokeEx(performance) failed: %08lx\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "V_VT(performance) = %d\n", V_VT(&var)); + ok(V_DISPATCH(&var) != NULL, "V_DISPATCH(performance) = NULL\n"); + IDispatchEx_Release(dispex); + + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IHTMLPerformance, (void**)&perf); + ok(hres == S_OK, "QueryInterface(IID_IHTMLPerformance) failed: %08lx\n", hres); + ok(perf != NULL, "performance is NULL\n"); + VariantClear(&var); + + hres = IHTMLPerformance_get_timing(perf, &timing); + ok(hres == S_OK, "get_timing failed: %08lx\n", hres); + ok(timing != NULL, "performance.timing is NULL\n"); + + hres = IHTMLPerformanceTiming_toJSON(timing, &var); + ok(hres == E_UNEXPECTED, "timing.toJSON() failed: %08lx\n", hres); + ok(V_VT(&var) == VT_EMPTY, "V_VT(timing.toJSON()) = %d\n", V_VT(&var)); + IHTMLPerformanceTiming_Release(timing); + + IHTMLPerformance_Release(perf); +} + static IHTMLDocument2 *notif_doc; static BOOL doc_complete;
@@ -12220,6 +12278,8 @@ START_TEST(dom) run_domtest(emptydiv_str, test_docfrag); run_domtest(doc_blank, test_replacechild_elems); run_domtest(doctype_str, test_doctype); + run_domtest(doc_blank, test_quirks_mode_perf_toJSON); + run_domtest(doc_blank_ie8, test_quirks_mode_perf_toJSON);
test_quirks_mode(); test_document_mode_lock(); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index f2e025ec864..b8a5198718b 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2433,6 +2433,47 @@ sync_test("functions scope", function() { })(); });
+sync_test("perf toJSON", function() { + var tests = [ + [ "performance.timing", "connectEnd", "connectStart", "domComplete", "domContentLoadedEventEnd", + "domContentLoadedEventStart", "domInteractive", "domLoading", "domainLookupEnd", "domainLookupStart", + "fetchStart", "loadEventEnd", "loadEventStart", "msFirstPaint", "navigationStart", "redirectEnd", + "redirectStart", "requestStart", "responseEnd", "responseStart", "unloadEventEnd", "unloadEventStart" ] + ]; + + for(var i = 0; i < tests.length; i++) { + var desc, name = tests[i][0], obj = eval("window." + name), json; + + Object.defineProperty(obj, "foobar", {writable: true, enumerable: true, configurable: true, value: 1}); + Object.defineProperty(Object.getPrototypeOf(obj), "barfoo", {writable: true, enumerable: true, configurable: true, value: 3}); + json = obj.toJSON(); + + ok(Object.getPrototypeOf(json) === Object.prototype, "prototype of " + name + ".toJSON() != Object.prototype"); + ok(typeof json === "object", "typeof " + name + ".toJSON() != object"); + for(var j = 1; j < tests[i].length; j++) { + desc = Object.getOwnPropertyDescriptor(json, tests[i][j]); + ok(json.hasOwnProperty(tests[i][j]), name + ".toJSON() does not have " + tests[i][j]); + ok(desc.writable === true, name + ".toJSON()." + tests[i][j] + " not writable"); + ok(desc.enumerable === true, name + ".toJSON()." + tests[i][j] + " not enumerable"); + ok(desc.configurable === true, name + ".toJSON()." + tests[i][j] + " not configurable"); + } + ok(!("foobar" in json), "foobar in " + name + ".toJSON()"); + todo_wine. + ok(!("barfoo" in json), "barfoo in " + name + ".toJSON()"); + + delete obj.foobar; + delete Object.getPrototypeOf(obj).barfoo; + + desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), tests[i][1]); + delete Object.getPrototypeOf(obj)[tests[i][1]]; + todo_wine. + ok(!(tests[i][1] in obj), tests[i][1] + " in " + name + " after delete"); + json = obj.toJSON(); + ok(json.hasOwnProperty(tests[i][1]), name + ".toJSON() does not have " + tests[i][1] + " after delete"); + if(desc /* todo_wine */) Object.defineProperty(Object.getPrototypeOf(obj), tests[i][1], desc); + } +}); + sync_test("console", function() { var except
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/omnavigator.c | 6 ++++-- dlls/mshtml/tests/dom.c | 10 ++++++++++ dlls/mshtml/tests/es5.js | 1 + 3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index ccbd9c95538..eb4b78001cc 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1587,8 +1587,10 @@ static HRESULT WINAPI HTMLPerformanceNavigation_toString(IHTMLPerformanceNavigat static HRESULT WINAPI HTMLPerformanceNavigation_toJSON(IHTMLPerformanceNavigation *iface, VARIANT *p) { HTMLPerformanceNavigation *This = impl_from_IHTMLPerformanceNavigation(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + return dispex_builtin_props_to_json(&This->dispex, p); }
static const IHTMLPerformanceNavigationVtbl HTMLPerformanceNavigationVtbl = { diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 65b9e3aa21c..06cd1bd10bd 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -11229,6 +11229,7 @@ static void test_quirks_mode_offsetHeight(IHTMLDocument2 *doc)
static void test_quirks_mode_perf_toJSON(IHTMLDocument2 *doc) { + IHTMLPerformanceNavigation *nav; IHTMLPerformanceTiming *timing; IHTMLPerformance *perf; DISPPARAMS dp = { 0 }; @@ -11263,6 +11264,15 @@ static void test_quirks_mode_perf_toJSON(IHTMLDocument2 *doc) ok(perf != NULL, "performance is NULL\n"); VariantClear(&var);
+ hres = IHTMLPerformance_get_navigation(perf, &nav); + ok(hres == S_OK, "get_navigation failed: %08lx\n", hres); + ok(nav != NULL, "performance.navigation is NULL\n"); + + hres = IHTMLPerformanceNavigation_toJSON(nav, &var); + ok(hres == E_UNEXPECTED, "navigation.toJSON() failed: %08lx\n", hres); + ok(V_VT(&var) == VT_EMPTY, "V_VT(navigation.toJSON()) = %d\n", V_VT(&var)); + IHTMLPerformanceNavigation_Release(nav); + hres = IHTMLPerformance_get_timing(perf, &timing); ok(hres == S_OK, "get_timing failed: %08lx\n", hres); ok(timing != NULL, "performance.timing is NULL\n"); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index b8a5198718b..0df246933dd 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2435,6 +2435,7 @@ sync_test("functions scope", function() {
sync_test("perf toJSON", function() { var tests = [ + [ "performance.navigation", "redirectCount", "type" ], [ "performance.timing", "connectEnd", "connectStart", "domComplete", "domContentLoadedEventEnd", "domContentLoadedEventStart", "domInteractive", "domLoading", "domainLookupEnd", "domainLookupStart", "fetchStart", "loadEventEnd", "loadEventStart", "msFirstPaint", "navigationStart", "redirectEnd",
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 19 ++++++++++++++++--- dlls/mshtml/omnavigator.c | 6 ++++-- dlls/mshtml/tests/dom.c | 4 ++++ dlls/mshtml/tests/es5.js | 1 + 4 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 8b0f7b9cc92..3b3f524ffe6 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2430,11 +2430,13 @@ static IWineJSDispatchHostVtbl JSDispatchHostVtbl = {
HRESULT dispex_builtin_props_to_json(DispatchEx *dispex, VARIANT *ret) { + IWineJSDispatchHost *subdispex_iface; + static WCHAR toJSONW[] = L"toJSON"; func_info_t *func, *end; IWineJSDispatch *json; + DISPID id, to_json; HRESULT hres; VARIANT var; - DISPID id; DISPPARAMS dp = { 0 }, put_dp = { &var, &propput_dispid, 1, 1 };
if(!dispex->jsdisp) @@ -2452,9 +2454,20 @@ HRESULT dispex_builtin_props_to_json(DispatchEx *dispex, VARIANT *ret)
if(SUCCEEDED(hres)) { hres = IWineJSDispatch_GetDispID(json, func->name, fdexNameEnsure | fdexNameCaseSensitive, &id); - if(SUCCEEDED(hres)) { - hres = IWineJSDispatch_InvokeEx(json, id, 0, DISPATCH_PROPERTYPUT, &put_dp, NULL, NULL, NULL); + + if(SUCCEEDED(hres) && V_VT(&var) == VT_DISPATCH && SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IWineJSDispatchHost, (void**)&subdispex_iface))) { + if(subdispex_iface->lpVtbl == &JSDispatchHostVtbl) { + DispatchEx *subdispex = impl_from_IWineJSDispatchHost(subdispex_iface); + + if(SUCCEEDED(get_builtin_id(subdispex, toJSONW, fdexNameCaseSensitive, &to_json))) { + VariantClear(&var); + hres = dispex_call_builtin(subdispex, to_json, &dp, &var, NULL, NULL); + } + } + IWineJSDispatchHost_Release(subdispex_iface); } + if(SUCCEEDED(hres)) + hres = IWineJSDispatch_InvokeEx(json, id, 0, DISPATCH_PROPERTYPUT, &put_dp, NULL, NULL, NULL); VariantClear(&var); } if(FAILED(hres)) { diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index eb4b78001cc..b9f0f677b0a 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1752,8 +1752,10 @@ static HRESULT WINAPI HTMLPerformance_toString(IHTMLPerformance *iface, BSTR *st static HRESULT WINAPI HTMLPerformance_toJSON(IHTMLPerformance *iface, VARIANT *var) { HTMLPerformance *This = impl_from_IHTMLPerformance(iface); - FIXME("(%p)->(%p)\n", This, var); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, var); + + return dispex_builtin_props_to_json(&This->dispex, var); }
static const IHTMLPerformanceVtbl HTMLPerformanceVtbl = { diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 06cd1bd10bd..232cc35f524 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -11264,6 +11264,10 @@ static void test_quirks_mode_perf_toJSON(IHTMLDocument2 *doc) ok(perf != NULL, "performance is NULL\n"); VariantClear(&var);
+ hres = IHTMLPerformance_toJSON(perf, &var); + ok(hres == E_UNEXPECTED, "toJSON() returned: %08lx\n", hres); + ok(V_VT(&var) == VT_EMPTY, "V_VT(toJSON()) = %d\n", V_VT(&var)); + hres = IHTMLPerformance_get_navigation(perf, &nav); ok(hres == S_OK, "get_navigation failed: %08lx\n", hres); ok(nav != NULL, "performance.navigation is NULL\n"); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 0df246933dd..420a72fd455 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2435,6 +2435,7 @@ sync_test("functions scope", function() {
sync_test("perf toJSON", function() { var tests = [ + [ "performance", "navigation", "timing" ], [ "performance.navigation", "redirectCount", "type" ], [ "performance.timing", "connectEnd", "connectStart", "domComplete", "domContentLoadedEventEnd", "domContentLoadedEventStart", "domInteractive", "domLoading", "domainLookupEnd", "domainLookupStart",
From: Gabriel Ivăncescu gabrielopcode@gmail.com
But convert to double as late as possible.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 2 +- dlls/mshtml/task.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 638b23e1379..63e21b44c3a 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1389,7 +1389,7 @@ LONG get_task_target_magic(void); HRESULT push_task(task_t*,task_proc_t,task_proc_t,LONG); HRESULT push_event_task(event_task_t*,HTMLInnerWindow*,event_task_proc_t,event_task_proc_t,LONG); void remove_target_tasks(LONG); -ULONGLONG get_time_stamp(void); +double get_time_stamp(void);
enum timer_type { TIMER_TIMEOUT, diff --git a/dlls/mshtml/task.c b/dlls/mshtml/task.c index 49f76d101a9..5015d7e8cf3 100644 --- a/dlls/mshtml/task.c +++ b/dlls/mshtml/task.c @@ -468,15 +468,15 @@ thread_data_t *get_thread_data(BOOL create) return thread_data; }
-ULONGLONG get_time_stamp(void) +double get_time_stamp(void) { FILETIME time;
/* 1601 to 1970 is 369 years plus 89 leap days */ - const ULONGLONG time_epoch = (ULONGLONG)(369 * 365 + 89) * 86400 * 1000; + const ULONGLONG time_epoch = (ULONGLONG)(369 * 365 + 89) * 86400 * 10000000;
GetSystemTimeAsFileTime(&time); - return (((ULONGLONG)time.dwHighDateTime << 32) + time.dwLowDateTime) / 10000 - time_epoch; + return (((ULONGLONG)time.dwHighDateTime << 32) + time.dwLowDateTime - time_epoch) * 0.0001; }
void unblock_tasks_and_timers(thread_data_t *thread_data)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/mshtml_private_iface.idl | 13 +++++++++++ dlls/mshtml/omnavigator.c | 34 ++++++++++++++++++++++++++++ dlls/mshtml/tests/documentmode.js | 9 ++++++++ 4 files changed, 57 insertions(+)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 63e21b44c3a..c40ef0d6639 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -304,6 +304,7 @@ typedef struct ScriptHost ScriptHost; XIID(IWineHTMLWindowCompatPrivate) \ XIID(IWinePageTransitionEvent) \ XIID(IWineXMLHttpRequestPrivate) \ + XIID(IWinePerformancePrivate) \ XIID(IWineMSHTMLConsole) \ XIID(IWineMSHTMLMediaQueryList) \ XIID(IWineMSHTMLMutationObserver) diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl index 503593d1c25..e43056b6dbe 100644 --- a/dlls/mshtml/mshtml_private_iface.idl +++ b/dlls/mshtml/mshtml_private_iface.idl @@ -113,6 +113,19 @@ interface IWineMSHTMLMediaQueryList : IDispatch HRESULT removeListener([in] VARIANT *listener); }
+[ + odl, + oleautomation, + dual, + hidden, + uuid(6ac5491e-1758-4b82-98a2-83e31a7c8870) +] +interface IWinePerformancePrivate : IDispatch +{ + [id(1)] + HRESULT now([retval, out] double *p); +} + const long DISPID_IWINEHTMLWINDOWPRIVATE_MUTATIONOBSERVER = 55; [ odl, diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index b9f0f677b0a..8b893bd3309 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1672,6 +1672,7 @@ static dispex_static_data_t HTMLPerformanceNavigation_dispex = { typedef struct { DispatchEx dispex; IHTMLPerformance IHTMLPerformance_iface; + IWinePerformancePrivate IWinePerformancePrivate_iface;
HTMLInnerWindow *window; IHTMLPerformanceNavigation *navigation; @@ -1772,6 +1773,34 @@ static const IHTMLPerformanceVtbl HTMLPerformanceVtbl = { HTMLPerformance_toJSON };
+static inline HTMLPerformance *impl_from_IWinePerformancePrivate(IWinePerformancePrivate *iface) +{ + return CONTAINING_RECORD(iface, HTMLPerformance, IWinePerformancePrivate_iface); +} + +DISPEX_IDISPATCH_IMPL(HTMLPerformancePrivate, IWinePerformancePrivate, impl_from_IWinePerformancePrivate(iface)->dispex) + +static HRESULT WINAPI HTMLPerformancePrivate_now(IWinePerformancePrivate *iface, double *p) +{ + HTMLPerformance *This = impl_from_IWinePerformancePrivate(iface); + + TRACE("(%p)->(%p)\n", This, p); + + *p = get_time_stamp() - This->window->navigation_start_time; + return S_OK; +} + +static const IWinePerformancePrivateVtbl WinePerformancePrivateVtbl = { + HTMLPerformancePrivate_QueryInterface, + HTMLPerformancePrivate_AddRef, + HTMLPerformancePrivate_Release, + HTMLPerformancePrivate_GetTypeInfoCount, + HTMLPerformancePrivate_GetTypeInfo, + HTMLPerformancePrivate_GetIDsOfNames, + HTMLPerformancePrivate_Invoke, + HTMLPerformancePrivate_now, +}; + static inline HTMLPerformance *HTMLPerformance_from_DispatchEx(DispatchEx *iface) { return CONTAINING_RECORD(iface, HTMLPerformance, dispex); @@ -1783,6 +1812,8 @@ static void *HTMLPerformance_query_interface(DispatchEx *dispex, REFIID riid)
if(IsEqualGUID(&IID_IHTMLPerformance, riid)) return &This->IHTMLPerformance_iface; + if(IsEqualGUID(&IID_IWinePerformancePrivate, riid)) + return &This->IWinePerformancePrivate_iface;
return NULL; } @@ -1830,6 +1861,8 @@ static void HTMLPerformance_init_dispex_info(dispex_data_t *info, compat_mode_t {DISPID_UNKNOWN} }; dispex_info_add_interface(info, IHTMLPerformance_tid, mode < COMPAT_MODE_IE9 ? hooks : NULL); + if(mode >= COMPAT_MODE_IE10) + dispex_info_add_interface(info, IWinePerformancePrivate_tid, NULL); }
static dispex_static_data_t HTMLPerformance_dispex = { @@ -1850,6 +1883,7 @@ HRESULT create_performance(HTMLInnerWindow *window, IHTMLPerformance **ret) return E_OUTOFMEMORY;
performance->IHTMLPerformance_iface.lpVtbl = &HTMLPerformanceVtbl; + performance->IWinePerformancePrivate_iface.lpVtbl = &WinePerformancePrivateVtbl; performance->window = window; IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 1394010966e..fdf918d95ee 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -19,6 +19,10 @@ var compat_version; var tests = [];
+if(performance.now) { + var t = performance.now(); + ok(t - performance.timing.navigationStart < 2000, "performance.now() more than 2 sec away from navigationStart: " + t + " vs " + performance.timing.navigationStart); +} ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); ok(performance.timing.fetchStart == performance.timing.navigationStart, "fetchStart != navigationStart"); ok(performance.timing.domainLookupStart >= performance.timing.fetchStart, "domainLookupStart < fetchStart"); @@ -578,6 +582,11 @@ sync_test("perf_props", function() { test_exposed("timing", true); test_exposed("toJSON", v >= 9); test_exposed("toString", true); + test_exposed("now", v >= 10); + test_exposed("eventCounts", false); + test_exposed("measureUserAgentSpecificMemory", false); + test_exposed("memory", false); + test_exposed("timeOrigin", false);
obj = window.performance.navigation, name = "PerformanceNavigation";
Jacek Caban (@jacek) commented about dlls/jscript/jsdisp.idl:
{ void Free(); HRESULT GetScriptGlobal(IWineJSDispatchHost **ret);
- HRESULT CreateObject(IWineJSDispatch **obj);
It's not an object method. If anything, it would better fit `IWineJScript`. `dispex_builtin_props_to_json` also looks questionable. In any case, I think that it's not a good timing to send things like this.
On Sun Jul 28 15:19:15 2024 +0000, Jacek Caban wrote:
It's not an object method. If anything, it would better fit `IWineJScript`. `dispex_builtin_props_to_json` also looks questionable. In any case, I think that it's not a good timing to send things like this.
Oh yeah, I forgot there's another interface now (I only had one on either jscript or mshtml side with everything to keep it simple).
BTW, what part of `dispex_builtin_props_to_json` is questionable? The fact it's generic? Should I hardcode the props list in each object instead, or? I tried to be thorough with tests to show that it's only the builtin props (and not functions, but props/accessors) that get placed in the JSON object, but if you have any ideas or think I missed something please let me know.
I made it generic to keep it simpler to avoid having to special case each object in turn.
On Sun Jul 28 19:45:40 2024 +0000, Gabriel Ivăncescu wrote:
Oh yeah, I forgot there's another interface now (I only had one on either jscript or mshtml side with everything to keep it simple). BTW, what part of `dispex_builtin_props_to_json` is questionable? The fact it's generic? Should I hardcode the props list in each object instead, or? I tried to be thorough with tests to show that it's only the builtin props (and not functions, but props/accessors) that get placed in the JSON object, but if you have any ideas or think I missed something please let me know. I made it generic to keep it simpler to avoid having to special case each object in turn.
Generic is fine, but you shouldn't need to call hooks directly here, we have other helpers.
On Mon Jul 29 21:43:08 2024 +0000, Jacek Caban wrote:
Generic is fine, but you shouldn't need to call hooks directly here, we have other helpers.
Those require looking it up via id (even though we already have the func_info by scanning through all of them), is that what you meant?