From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 52 +++++++++++++++++++++---------- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/documentmode.js | 6 ++++ dlls/mshtml/tests/es5.js | 1 - 4 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index f69f1fe242c..69e947e0af9 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1895,10 +1895,15 @@ static void init_host_object(DispatchEx *dispex, HTMLInnerWindow *script_global, return; hres = IWineJScript_InitHostConstructor(script_global->jscript, &dispex->IWineJSDispatchHost_iface, prototype->jsdisp, &dispex->jsdisp); - }else + }else { + UINT32 js_flags = 0; + + if(dispex->info == dispex->info->desc->constructor_info[dispex->info->compat_mode - COMPAT_MODE_IE9]) + js_flags |= HOSTOBJ_CONSTRUCTOR; + hres = IWineJScript_InitHostObject(script_global->jscript, &dispex->IWineJSDispatchHost_iface, - prototype ? prototype->jsdisp : NULL, - dispex->info->desc->js_flags, &dispex->jsdisp); + prototype ? prototype->jsdisp : NULL, js_flags, &dispex->jsdisp); + } if(FAILED(hres)) ERR("Failed to initialize jsdisp: %08lx\n", hres); } @@ -3071,40 +3076,55 @@ static const dispex_static_data_vtbl_t constructor_dispex_vtbl = { .find_dispid = constructor_find_dispid, };
-static dispex_static_data_t constructor_dispex = { - .name = "Constructor", - .vtbl = &constructor_dispex_vtbl, - .js_flags = HOSTOBJ_CONSTRUCTOR, -}; +static dispex_static_data_t constructor_dispex = { 0 };
HRESULT get_constructor(HTMLInnerWindow *script_global, prototype_id_t id, DispatchEx **ret) { - dispex_static_data_t *info; + compat_mode_t compat_mode = script_global->doc->document_mode; + dispex_static_data_t *desc; + dispex_data_t *info;
- assert(script_global->doc->document_mode >= COMPAT_MODE_IE9); + assert(compat_mode >= COMPAT_MODE_IE9);
if(script_global->constructors[id]) { *ret = script_global->constructors[id]; return S_OK; }
- info = object_descriptors[id]; - if(info->init_constructor) { - HRESULT hres = info->init_constructor(script_global, &script_global->constructors[id]); + desc = object_descriptors[id]; + if(desc->init_constructor) { + HRESULT hres = desc->init_constructor(script_global, &script_global->constructors[id]); if(FAILED(hres)) return hres; }else { struct constructor *constr; + + info = desc->constructor_info[compat_mode - COMPAT_MODE_IE9]; + if(!info) { + EnterCriticalSection(&cs_dispex_static_data); + info = desc->constructor_info[compat_mode - COMPAT_MODE_IE9]; + if(!info) { + info = preprocess_dispex_data(&constructor_dispex, compat_mode, FALSE); + if(info) { + info->vtbl = &constructor_dispex_vtbl; + info->name = desc->name; + info->desc = desc; + desc->constructor_info[compat_mode - COMPAT_MODE_IE9] = info; + } + } + LeaveCriticalSection(&cs_dispex_static_data); + if(!info) + return E_OUTOFMEMORY; + } + if(!(constr = calloc(sizeof(*constr), 1))) return E_OUTOFMEMORY;
- init_dispatch(&constr->dispex, &constructor_dispex, script_global, - dispex_compat_mode(&script_global->event_target.dispex)); + init_dispatch_from_desc(&constr->dispex, info, script_global, NULL); constr->id = id; script_global->constructors[id] = &constr->dispex; }
*ret = script_global->constructors[id]; return S_OK; - } diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 11ee0afd3c7..9e5d7ba5240 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -514,6 +514,7 @@ typedef struct { HRESULT (*init_constructor)(HTMLInnerWindow*,DispatchEx**); dispex_data_t *info_cache[COMPAT_MODE_CNT]; dispex_data_t *prototype_info[COMPAT_MODE_CNT - COMPAT_MODE_IE9]; + dispex_data_t *constructor_info[COMPAT_MODE_CNT - COMPAT_MODE_IE9]; dispex_data_t *delayed_init_info; prototype_id_t id; prototype_id_t prototype_id; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 9f62ca68f1d..fea12ce1f1a 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -353,6 +353,12 @@ sync_test("builtin_toString", function() { test("SVGSVGElement", document.createElementNS(svg_ns, "svg"), "SVGSVGElement"); test("SVGCircleElement", document.createElementNS(svg_ns, "circle"), "SVGCircleElement"); test("SVGCircleElement", document.createElementNS(svg_ns, "tspan"), "SVGTSpanElement"); + + /* Non-function constructors */ + var props = Object.getOwnPropertyNames(window); + for(i = 0; i < props.length; i++) + if(typeof(window[props[i]]) === "object" && window[props[i]].hasOwnProperty("prototype")) + test(props[i] + " constructor", window[props[i]], props[i]); } });
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 0033a06fa3c..e15e3f379cd 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2907,7 +2907,6 @@ sync_test("prototypes", function() { test_own_data_prop_desc(window, "DOMImplementation", true, false, true); ok(Object.getPrototypeOf(DOMImplementation) === Object.prototype, "Object.getPrototypeOf(DOMImplementation) = " + Object.getPrototypeOf(DOMImplementation)); - todo_wine. ok(DOMImplementation == "[object DOMImplementation]", "DOMImplementation = " + DOMImplementation);
var proto = constr.prototype;