From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/omnavigator.c | 66 ++++++++++++++++++++++++++++++++------- dlls/mshtml/tests/dom.c | 4 +++ dlls/mshtml/tests/es5.js | 8 ++++- 3 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 9706643f776..01f9f28001b 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1868,8 +1868,8 @@ typedef struct { IHTMLPerformance IHTMLPerformance_iface;
HTMLInnerWindow *window; - IHTMLPerformanceNavigation *navigation; - IHTMLPerformanceTiming *timing; + HTMLPerformanceNavigation *navigation; + HTMLPerformanceTiming *timing; } HTMLPerformance;
static inline HTMLPerformance *impl_from_IHTMLPerformance(IHTMLPerformance *iface) @@ -1900,10 +1900,10 @@ static HRESULT WINAPI HTMLPerformance_get_navigation(IHTMLPerformance *iface, init_dispatch(&navigation->dispex, &PerformanceNavigation_dispex, This->window, dispex_compat_mode(&This->dispex));
- This->navigation = &navigation->IHTMLPerformanceNavigation_iface; + This->navigation = navigation; }
- IHTMLPerformanceNavigation_AddRef(*p = This->navigation); + IHTMLPerformanceNavigation_AddRef(*p = &This->navigation->IHTMLPerformanceNavigation_iface); return S_OK; }
@@ -1927,10 +1927,10 @@ static HRESULT WINAPI HTMLPerformance_get_timing(IHTMLPerformance *iface, IHTMLP init_dispatch(&timing->dispex, &PerformanceTiming_dispex, This->window, dispex_compat_mode(&This->dispex));
- This->timing = &timing->IHTMLPerformanceTiming_iface; + This->timing = timing; }
- IHTMLPerformanceTiming_AddRef(*p = This->timing); + IHTMLPerformanceTiming_AddRef(*p = &This->timing->IHTMLPerformanceTiming_iface); return S_OK; }
@@ -1946,8 +1946,42 @@ 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; + IWineJSDispatch *json; + HRESULT hres; + VARIANT v; + + TRACE("(%p)->(%p)\n", This, var); + + if(!This->window->jscript) + return E_UNEXPECTED; + + if(!var) + return S_OK; + + hres = IWineJScript_CreateObject(This->window->jscript, &json); + if(FAILED(hres)) + return hres; + + hres = dispex_builtin_props_to_json(&This->navigation->dispex, This->window, &v); + if(SUCCEEDED(hres)) { + hres = IWineJSDispatch_DefineProperty(json, L"navigation", PROPF_WRITABLE | PROPF_ENUMERABLE | PROPF_CONFIGURABLE, &v); + VariantClear(&v); + if(SUCCEEDED(hres)) { + hres = dispex_builtin_props_to_json(&This->timing->dispex, This->window, &v); + if(SUCCEEDED(hres)) { + hres = IWineJSDispatch_DefineProperty(json, L"timing", PROPF_WRITABLE | PROPF_ENUMERABLE | PROPF_CONFIGURABLE, &v); + VariantClear(&v); + } + } + } + if(FAILED(hres)) { + IWineJSDispatch_Release(json); + return hres; + } + + V_VT(var) = VT_DISPATCH; + V_DISPATCH(var) = (IDispatch*)json; + return hres; }
static const IHTMLPerformanceVtbl HTMLPerformanceVtbl = { @@ -1985,9 +2019,9 @@ static void HTMLPerformance_traverse(DispatchEx *dispex, nsCycleCollectionTraver if(This->window) note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); if(This->navigation) - note_cc_edge((nsISupports*)This->navigation, "navigation", cb); + note_cc_edge((nsISupports*)&This->navigation->IHTMLPerformanceNavigation_iface, "navigation", cb); if(This->timing) - note_cc_edge((nsISupports*)This->timing, "timing", cb); + note_cc_edge((nsISupports*)&This->timing->IHTMLPerformanceTiming_iface, "timing", cb); }
static void HTMLPerformance_unlink(DispatchEx *dispex) @@ -1998,8 +2032,16 @@ static void HTMLPerformance_unlink(DispatchEx *dispex) This->window = NULL; IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); } - unlink_ref(&This->navigation); - unlink_ref(&This->timing); + if(This->navigation) { + HTMLPerformanceNavigation *navigation = This->navigation; + This->navigation = NULL; + IHTMLPerformanceNavigation_Release(&navigation->IHTMLPerformanceNavigation_iface); + } + if(This->timing) { + HTMLPerformanceTiming *timing = This->timing; + This->timing = NULL; + IHTMLPerformanceTiming_Release(&timing->IHTMLPerformanceTiming_iface); + } }
static void HTMLPerformance_destructor(DispatchEx *dispex) diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 9778a5b1ad8..7250ffea636 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -12266,6 +12266,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 347108e5810..6a3f24a265f 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2595,7 +2595,7 @@ sync_test("functions scope", function() { });
sync_test("perf toJSON", function() { - var json, objs = [ performance.navigation, performance.timing ]; + var json, objs = [ performance, performance.navigation, performance.timing ]; var non_props = [ "constructor", "TYPE_BACK_FORWARD", "TYPE_NAVIGATE", "TYPE_RELOAD", "TYPE_RESERVED" ];
for(var i = 0; i < objs.length; i++) { @@ -2640,6 +2640,12 @@ sync_test("perf toJSON", function() { ok(json.hasOwnProperty(prop), name + ".toJSON() does not have " + prop + " after delete"); Object.defineProperty(proto, prop, desc); } + + json = performance.toJSON(); + ok(typeof json.navigation === "object", "JSON'd performance's navigation type = " + typeof json.navigation); + ok(typeof json.navigation.redirectCount === "number", "JSON'd performance's navigation.redirectCount type = " + typeof json.navigation.redirectCount); + ok(Object.getPrototypeOf(json.navigation) === Object.prototype, "JSON'd performance's navigation prototype != Object.prototype"); + ok(!("toJSON" in json.navigation), "toJSON in JSON'd performance's navigation"); });
sync_test("console", function() {