-- v4: mshtml: Implement toJSON() for PerformanceTiming. mshtml: Don't expose toString from Performance* objects' prototypes in mshtml: Expose toJSON only in IE9+ modes.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/omnavigator.c | 46 ++++++++++++++-------- dlls/mshtml/tests/documentmode.js | 63 +++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 15 deletions(-)
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 942bd5bbe70..1bd370bcffd 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"
@@ -1708,15 +1709,20 @@ static const dispex_static_data_vtbl_t HTMLPerformanceTiming_dispex_vtbl = { .unlink = HTMLPerformanceTiming_unlink };
-static const tid_t PerformanceTiming_iface_tids[] = { - IHTMLPerformanceTiming_tid, - 0 -}; +static void PerformanceTiming_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); +} + dispex_static_data_t PerformanceTiming_dispex = { .id = OBJID_PerformanceTiming, .vtbl = &HTMLPerformanceTiming_dispex_vtbl, .disp_tid = IHTMLPerformanceTiming_tid, - .iface_tids = PerformanceTiming_iface_tids, + .init_info = PerformanceTiming_init_dispex_info, };
typedef struct { @@ -1829,15 +1835,20 @@ static const dispex_static_data_vtbl_t HTMLPerformanceNavigation_dispex_vtbl = { .unlink = HTMLPerformanceNavigation_unlink };
-static const tid_t PerformanceNavigation_iface_tids[] = { - IHTMLPerformanceNavigation_tid, - 0 -}; +static void PerformanceNavigation_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); +} + dispex_static_data_t PerformanceNavigation_dispex = { .id = OBJID_PerformanceNavigation, .vtbl = &HTMLPerformanceNavigation_dispex_vtbl, .disp_tid = IHTMLPerformanceNavigation_tid, - .iface_tids = PerformanceNavigation_iface_tids, + .init_info = PerformanceNavigation_init_dispex_info, };
typedef struct { @@ -1992,15 +2003,20 @@ static const dispex_static_data_vtbl_t HTMLPerformance_dispex_vtbl = { .unlink = HTMLPerformance_unlink };
-static const tid_t Performance_iface_tids[] = { - IHTMLPerformance_tid, - 0 -}; +static void Performance_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); +} + dispex_static_data_t Performance_dispex = { .id = OBJID_Performance, .vtbl = &HTMLPerformance_dispex_vtbl, .disp_tid = IHTMLPerformance_tid, - .iface_tids = Performance_iface_tids, + .init_info = Performance_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 dd228ee1bae..bfec46b37d2 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1008,6 +1008,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();
@@ -4412,6 +4462,19 @@ sync_test("prototype props", function() { ]); if(v >= 11) check(PageTransitionEvent, [ "persisted" ]); + check(Performance, [ + "clearMarks", "clearMeasures", "clearResourceTimings", "getEntries", "getEntriesByName", "getEntriesByType", "getMarks", + "getMeasures", "mark", "measure", "navigation", ["now",10], "setResourceTimingBufferSize", "timing", "toJSON" + ], [ + "clearMarks", "clearMeasures", "clearResourceTimings", "getEntries", "getEntriesByName", "getEntriesByType", "getMarks", + "getMeasures", "mark", "measure", ["now",10], "setResourceTimingBufferSize", "toString" + ]); + check(PerformanceNavigation, [ "TYPE_BACK_FORWARD", "TYPE_NAVIGATE", "TYPE_RELOAD", "TYPE_RESERVED", "redirectCount", "toJSON", "type" ], [ "TYPE_BACK_FORWARD", "TYPE_NAVIGATE", "TYPE_RELOAD", "TYPE_RESERVED", "toString" ]); + check(PerformanceTiming, [ + "connectEnd", "connectStart", "domComplete", "domContentLoadedEventEnd", "domContentLoadedEventStart", "domInteractive", "domLoading", + "domainLookupEnd", "domainLookupStart", "fetchStart", "loadEventEnd", "loadEventStart", "msFirstPaint", "navigationStart", "redirectEnd", + "redirectStart", "requestStart", "responseEnd", "responseStart", "toJSON", "unloadEventEnd", "unloadEventStart" + ], [ "toString" ]); if(v >= 10) check(ProgressEvent, [ "initProgressEvent", "lengthComputable", "loaded", "total" ]); check(StorageEvent, [ "initStorageEvent", "key", "newValue", "oldValue", "storageArea", "url" ]);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/omnavigator.c | 18 +++++++++++++++--- dlls/mshtml/tests/documentmode.js | 6 +++--- 2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 1bd370bcffd..a49387f1ed0 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1715,7 +1715,11 @@ static void PerformanceTiming_init_dispex_info(dispex_data_t *info, compat_mode_ {DISPID_IHTMLPERFORMANCETIMING_TOJSON}, {DISPID_UNKNOWN} }; - dispex_info_add_interface(info, IHTMLPerformanceTiming_tid, mode < COMPAT_MODE_IE9 ? hooks : NULL); + static const dispex_hook_t ie9_hooks[] = { + {DISPID_IHTMLPERFORMANCETIMING_TOSTRING}, + {DISPID_UNKNOWN} + }; + dispex_info_add_interface(info, IHTMLPerformanceTiming_tid, mode < COMPAT_MODE_IE9 ? hooks : ie9_hooks); }
dispex_static_data_t PerformanceTiming_dispex = { @@ -1841,7 +1845,11 @@ static void PerformanceNavigation_init_dispex_info(dispex_data_t *info, compat_m {DISPID_IHTMLPERFORMANCENAVIGATION_TOJSON}, {DISPID_UNKNOWN} }; - dispex_info_add_interface(info, IHTMLPerformanceNavigation_tid, mode < COMPAT_MODE_IE9 ? hooks : NULL); + static const dispex_hook_t ie9_hooks[] = { + {DISPID_IHTMLPERFORMANCENAVIGATION_TOSTRING}, + {DISPID_UNKNOWN} + }; + dispex_info_add_interface(info, IHTMLPerformanceNavigation_tid, mode < COMPAT_MODE_IE9 ? hooks : ie9_hooks); }
dispex_static_data_t PerformanceNavigation_dispex = { @@ -2009,7 +2017,11 @@ static void Performance_init_dispex_info(dispex_data_t *info, compat_mode_t mode {DISPID_IHTMLPERFORMANCE_TOJSON}, {DISPID_UNKNOWN} }; - dispex_info_add_interface(info, IHTMLPerformance_tid, mode < COMPAT_MODE_IE9 ? hooks : NULL); + static const dispex_hook_t ie9_hooks[] = { + {DISPID_IHTMLPERFORMANCE_TOSTRING}, + {DISPID_UNKNOWN} + }; + dispex_info_add_interface(info, IHTMLPerformance_tid, mode < COMPAT_MODE_IE9 ? hooks : ie9_hooks); }
dispex_static_data_t Performance_dispex = { diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index bfec46b37d2..faac18c45a3 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4467,14 +4467,14 @@ sync_test("prototype props", function() { "getMeasures", "mark", "measure", "navigation", ["now",10], "setResourceTimingBufferSize", "timing", "toJSON" ], [ "clearMarks", "clearMeasures", "clearResourceTimings", "getEntries", "getEntriesByName", "getEntriesByType", "getMarks", - "getMeasures", "mark", "measure", ["now",10], "setResourceTimingBufferSize", "toString" + "getMeasures", "mark", "measure", ["now",10], "setResourceTimingBufferSize" ]); - check(PerformanceNavigation, [ "TYPE_BACK_FORWARD", "TYPE_NAVIGATE", "TYPE_RELOAD", "TYPE_RESERVED", "redirectCount", "toJSON", "type" ], [ "TYPE_BACK_FORWARD", "TYPE_NAVIGATE", "TYPE_RELOAD", "TYPE_RESERVED", "toString" ]); + check(PerformanceNavigation, [ "TYPE_BACK_FORWARD", "TYPE_NAVIGATE", "TYPE_RELOAD", "TYPE_RESERVED", "redirectCount", "toJSON", "type" ], [ "TYPE_BACK_FORWARD", "TYPE_NAVIGATE", "TYPE_RELOAD", "TYPE_RESERVED" ]); check(PerformanceTiming, [ "connectEnd", "connectStart", "domComplete", "domContentLoadedEventEnd", "domContentLoadedEventStart", "domInteractive", "domLoading", "domainLookupEnd", "domainLookupStart", "fetchStart", "loadEventEnd", "loadEventStart", "msFirstPaint", "navigationStart", "redirectEnd", "redirectStart", "requestStart", "responseEnd", "responseStart", "toJSON", "unloadEventEnd", "unloadEventStart" - ], [ "toString" ]); + ]); if(v >= 10) check(ProgressEvent, [ "initProgressEvent", "lengthComputable", "loaded", "total" ]); check(StorageEvent, [ "initStorageEvent", "key", "newValue", "oldValue", "storageArea", "url" ]);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/jscript.c | 13 ++++++++ dlls/jscript/jsdisp.idl | 1 + dlls/mshtml/dispex.c | 37 ++++++++++++++++++++++ dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/omnavigator.c | 6 ++-- dlls/mshtml/tests/dom.c | 60 ++++++++++++++++++++++++++++++++++++ dlls/mshtml/tests/es5.js | 48 +++++++++++++++++++++++++++++ 7 files changed, 164 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index a7f468a677a..b65b95b1e0f 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -1465,6 +1465,18 @@ static HRESULT WINAPI WineJScript_InitHostConstructor(IWineJScript *iface, IWine return init_host_constructor(This->ctx, constr, method_name, ret); }
+static HRESULT WINAPI WineJScript_CreateObject(IWineJScript *iface, IWineJSDispatch **ret) +{ + JScript *This = impl_from_IWineJScript(iface); + jsdisp_t *jsdisp; + HRESULT hres; + + hres = create_object(This->ctx, NULL, &jsdisp); + if(SUCCEEDED(hres)) + *ret = &jsdisp->IWineJSDispatch_iface; + return hres; +} + static HRESULT WINAPI WineJScript_FillGlobals(IWineJScript *iface, IWineJSDispatchHost *script_global) { JScript *This = impl_from_IWineJScript(iface); @@ -1477,6 +1489,7 @@ static const IWineJScriptVtbl WineJScriptVtbl = { WineJScript_Release, WineJScript_InitHostObject, WineJScript_InitHostConstructor, + WineJScript_CreateObject, WineJScript_FillGlobals, };
diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index abef1f32f61..22349ecb50c 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -87,5 +87,6 @@ interface IWineJScript : IUnknown { HRESULT InitHostObject(IWineJSDispatchHost *host_obj, IWineJSDispatch *prototype, UINT32 flags, IWineJSDispatch **ret); HRESULT InitHostConstructor(IWineJSDispatchHost *constr, const WCHAR *method_name, IWineJSDispatch **ret); + HRESULT CreateObject(IWineJSDispatch **ret); HRESULT FillGlobals(IWineJSDispatchHost *script_global); } diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index d281929e09e..cd256dba677 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2901,6 +2901,43 @@ static IWineJSDispatchHostVtbl JSDispatchHostVtbl = { JSDispatchHost_ToString, };
+HRESULT dispex_builtin_props_to_json(DispatchEx *dispex, HTMLInnerWindow *window, VARIANT *ret) +{ + func_info_t *func, *end; + IWineJSDispatch *json; + DISPPARAMS dp = { 0 }; + HRESULT hres; + VARIANT var; + + if(!window->jscript) + return E_UNEXPECTED; + + if(!ret) + return S_OK; + + hres = IWineJScript_CreateObject(window->jscript, &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; + hres = builtin_propget(dispex, func, &dp, &var, NULL, NULL); + if(SUCCEEDED(hres)) { + hres = IWineJSDispatch_DefineProperty(json, func->name, PROPF_WRITABLE | PROPF_ENUMERABLE | PROPF_CONFIGURABLE, &var); + VariantClear(&var); + } + if(FAILED(hres)) { + IWineJSDispatch_Release(json); + return hres; + } + } + + 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 7d61ba0d74f..d014c34ba7c 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -638,6 +638,7 @@ HRESULT remove_attribute(DispatchEx*,DISPID,VARIANT_BOOL*); BOOL is_builtin_attribute(DispatchEx*,DISPID); BOOL is_builtin_value(DispatchEx*,DISPID); HRESULT dispex_get_dynid(DispatchEx*,const WCHAR*,BOOL,DISPID*); +HRESULT dispex_builtin_props_to_json(DispatchEx*,HTMLInnerWindow*,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 a49387f1ed0..2316f539702 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1627,8 +1627,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, This->window, p); }
static const IHTMLPerformanceTimingVtbl HTMLPerformanceTimingVtbl = { diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 17b4f63711d..f93da5fc159 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>" @@ -12219,6 +12229,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;
@@ -13638,6 +13696,8 @@ START_TEST(dom) run_domtest(frameset_str, test_frameset); run_domtest(emptydiv_str, test_docfrag); run_domtest(doc_blank, test_replacechild_elems); + run_domtest(doc_blank, test_quirks_mode_perf_toJSON); + run_domtest(doc_blank_ie8, test_quirks_mode_perf_toJSON); run_domtest(doctype_str, test_doctype); run_domtest(case_insens_str, test_case_insens); if(is_ie9plus) { diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 3dfb6458655..62daa58a383 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2594,6 +2594,54 @@ sync_test("functions scope", function() { })(); });
+sync_test("perf toJSON", function() { + var json, objs = [ performance.timing ]; + var non_props = [ "constructor" ]; + + for(var i = 0; i < objs.length; i++) { + var desc, prop, proto = Object.getPrototypeOf(objs[i]), props = Object.getOwnPropertyNames(proto); + var name = Object.prototype.toString.call(objs[i]).slice(8, -1); + + Object.defineProperty(objs[i], "foobar", {writable: true, enumerable: true, configurable: true, value: 1}); + Object.defineProperty(proto, "barfoo", {writable: true, enumerable: true, configurable: true, value: 3}); + json = objs[i].toJSON(); + + ok(Object.getPrototypeOf(json) === Object.prototype, "prototype of " + name + ".toJSON() != Object.prototype"); + ok(typeof json === "object", "typeof " + name + ".toJSON() != object"); + + for(var j = 0; j < non_props.length; j++) { + var idx = props.indexOf(non_props[j]); + if(idx !== -1) + props.splice(idx, 1); + } + + for(var j = 0; j < props.length; j++) { + if(typeof(proto[props[j]]) === "function") + ok(!(props[j] in json), props[j] + " in " + name + ".toJSON()"); + else { + test_own_data_prop_desc(json, props[j], true, true, true); + prop = props[j]; + } + } + + for(var j = 0; j < non_props.length; j++) + ok(!json.hasOwnProperty(non_props[j]), non_props[j] + " in " + name + ".toJSON()"); + ok(!("foobar" in json), "foobar in " + name + ".toJSON()"); + ok(!("barfoo" in json), "barfoo in " + name + ".toJSON()"); + + delete objs[i].foobar; + delete proto.barfoo; + + // test delete a builtin from the prototype and toJSON after + desc = Object.getOwnPropertyDescriptor(proto, prop); + delete proto[prop]; + ok(!(prop in objs[i]), prop + " in " + name + " after delete"); + json = objs[i].toJSON(); + ok(json.hasOwnProperty(prop), name + ".toJSON() does not have " + prop + " after delete"); + Object.defineProperty(proto, prop, desc); + } +}); + sync_test("console", function() { var except