From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/function.c | 90 ++++++++++++++++++++++++++----- dlls/mshtml/tests/documentmode.js | 15 ++++++ 2 files changed, 93 insertions(+), 12 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 9f1f53a96ae..52a96c9f69a 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -76,6 +76,11 @@ typedef struct { IWineJSDispatchHost *host_iface; } HostConstructor;
+typedef struct { + FunctionInstance function; + HostConstructor *constr; +} HostConstructor_create; + typedef struct { jsdisp_t jsdisp; jsval_t *buf; @@ -1102,14 +1107,6 @@ static ULONG HostConstructor_release(jsdisp_t *jsdisp) return IWineJSDispatchHost_Release(constr->host_iface); }
-static HRESULT HostConstructor_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, unsigned flags, struct property_info *desc) -{ - HostConstructor *constr = (HostConstructor*)jsdisp; - HRESULT hres = IWineJSDispatchHost_LookupProperty(constr->host_iface, name, flags, desc); - assert(hres != S_OK || (desc->flags & PROPF_METHOD)); /* external properties are not allowed */ - return hres; -} - static const builtin_info_t HostConstructor_info = { .class = JSCLASS_FUNCTION, .addref = HostConstructor_addref, @@ -1117,7 +1114,6 @@ static const builtin_info_t HostConstructor_info = { .call = Function_value, .destructor = Function_destructor, .gc_traverse = Function_gc_traverse, - .lookup_prop = HostConstructor_lookup_prop, };
static HRESULT HostConstructor_call(script_ctx_t *ctx, FunctionInstance *func, jsval_t vthis, unsigned flags, @@ -1187,9 +1183,55 @@ static const function_vtbl_t HostConstructorVtbl = { HostConstructor_gc_traverse };
+static HRESULT HostConstructor_create_call(script_ctx_t *ctx, FunctionInstance *func, jsval_t vthis, unsigned flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + HostConstructor_create *function = (HostConstructor_create*)func; + + /* only allow calls since it's a method */ + if(!(flags & DISPATCH_METHOD)) + return E_UNEXPECTED; + + return HostConstructor_call(ctx, &function->constr->function, vthis, DISPATCH_CONSTRUCT, argc, argv, r); +} + +static HRESULT HostConstructor_create_toString(FunctionInstance *func, jsstr_t **ret) +{ + return native_function_string(L"create", ret); +} + +static function_code_t *HostConstructor_create_get_code(FunctionInstance *function) +{ + return NULL; +} + +static void HostConstructor_create_destructor(FunctionInstance *func) +{ + HostConstructor_create *function = (HostConstructor_create*)func; + + if(function->constr) + jsdisp_release(&function->constr->function.dispex); +} + +static HRESULT HostConstructor_create_gc_traverse(struct gc_ctx *gc_ctx, enum gc_traverse_op op, FunctionInstance *func) +{ + HostConstructor_create *function = (HostConstructor_create*)func; + + return gc_process_linked_obj(gc_ctx, op, &function->function.dispex, &function->constr->function.dispex, (void**)&function->constr); +} + +static const function_vtbl_t HostConstructor_create_vtbl = { + HostConstructor_create_call, + HostConstructor_create_toString, + HostConstructor_create_get_code, + HostConstructor_create_destructor, + HostConstructor_create_gc_traverse +}; + HRESULT init_host_constructor(script_ctx_t *ctx, IWineJSDispatchHost *host_constr, IWineJSDispatch *prototype, IWineJSDispatch **ret) { + struct property_info desc; HostConstructor *function; HRESULT hres;
@@ -1201,13 +1243,37 @@ HRESULT init_host_constructor(script_ctx_t *ctx, IWineJSDispatchHost *host_const
hres = jsdisp_define_data_property(&function->function.dispex, L"prototype", PROPF_WRITABLE | PROPF_CONFIGURABLE, jsval_disp((IDispatch *)prototype)); - if(FAILED(hres)) { - IWineJSDispatch_Free(&function->function.dispex.IWineJSDispatch_iface); - return hres; + if(FAILED(hres)) + goto fail; + + hres = IWineJSDispatchHost_LookupProperty(host_constr, L"create", fdexNameCaseSensitive, &desc); + if(SUCCEEDED(hres)) { + HostConstructor_create *create; + + assert(desc.flags & PROPF_METHOD); + + hres = create_function(ctx, &HostFunction_info, &HostConstructor_create_vtbl, sizeof(*create), + PROPF_METHOD, NULL, (void**)&create); + if(FAILED(hres)) + goto fail; + + create->constr = function; + jsdisp_addref(&function->function.dispex); + + hres = jsdisp_define_data_property(&function->function.dispex, L"create", desc.flags & PROPF_ALL, jsval_obj(&create->function.dispex)); + jsdisp_release(&create->function.dispex); + if(FAILED(hres)) + goto fail; + }else if(hres != DISP_E_UNKNOWNNAME) { + goto fail; }
*ret = &function->function.dispex.IWineJSDispatch_iface; return S_OK; + +fail: + IWineJSDispatch_Free(&function->function.dispex.IWineJSDispatch_iface); + return hres; }
static HRESULT BindFunction_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index bb53a1a010f..33d000fc35f 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3996,3 +3996,18 @@ sync_test("prototype props", function() { check(Text, [ "removeNode", "replaceNode", "replaceWholeText", "splitText", "swapNode", "wholeText" ], [ "replaceWholeText", "wholeText" ]); check(UIEvent, [ "detail", "initUIEvent", "view" ], null, [ "deviceSessionId" ]); }); + +sync_test("constructors", function() { + var v = document.documentMode; + if(v < 9) + return; + + ok(XMLHttpRequest.create() instanceof XMLHttpRequest, "XMLHttpRequest.create did not return XMLHttpRequest instance"); + ok(XMLHttpRequest.create.call(Object) instanceof XMLHttpRequest, "XMLHttpRequest.create with Object 'this' did not return XMLHttpRequest instance"); + try { + new XMLHttpRequest.create(); + ok(false, "new XMLHttpRequest.create() did not throw"); + }catch(e) { + ok(e.number === 0x0ffff - 0x80000000, "new XMLHttpRequest.create() threw " + e.number); + } +});