jscript: Added Object constructor object implementation.
diff --git a/dlls/jscript/Makefile.in b/dlls/jscript/Makefile.in index 0288b4c..183a09e 100644 --- a/dlls/jscript/Makefile.in +++ b/dlls/jscript/Makefile.in
@@ -15,7 +15,8 @@ jscript.c \ jscript_main.c \ jsutils.c \ - lex.c + lex.c \ + object.c IDL_TLB_SRCS = jsglobal.idl
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index ae32f1a..ad7b988 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c
@@ -715,8 +715,6 @@ HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype) { - static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0}; - TRACE("%p (%p)\n", dispex, prototype); dispex->lpIDispatchExVtbl = &DispatchExVtbl; @@ -731,7 +729,7 @@ if(prototype) IDispatchEx_AddRef(_IDispatchEx_(prototype)); - dispex->prop_cnt = 2; + dispex->prop_cnt = 1; dispex->props[0].name = NULL; dispex->props[0].flags = 0; if(builtin_info->value_prop.invoke) { @@ -741,20 +739,6 @@ dispex->props[0].type = PROP_DELETED; } - dispex->props[1].type = PROP_DELETED; - dispex->props[1].name = SysAllocString(prototypeW); - dispex->props[1].flags = 0; - - if(prototype) { - HRESULT hres; - - hres = jsdisp_set_prototype(dispex, prototype); - if(FAILED(hres)) { - IDispatchEx_Release(_IDispatchEx_(dispex)); - return hres; - } - } - script_addref(ctx); dispex->ctx = ctx; @@ -786,6 +770,39 @@ return S_OK; } +HRESULT init_dispex_from_constr(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *constr) +{ + DispatchEx *prot = NULL; + dispex_prop_t *prop; + HRESULT hres; + + static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0}; + + hres = find_prop_name_prot(constr, prototypeW, FALSE, &prop); + if(SUCCEEDED(hres) && prop) { + jsexcept_t jsexcept; + VARIANT var; + + V_VT(&var) = VT_EMPTY; + memset(&jsexcept, 0, sizeof(jsexcept)); + hres = prop_get(constr, prop, ctx->lcid, NULL, &var, &jsexcept, NULL/*FIXME*/); + if(FAILED(hres)) { + ERR("Could not get prototype\n"); + return hres; + } + + if(V_VT(&var) == VT_DISPATCH) + prot = iface_to_jsdisp((IUnknown*)V_DISPATCH(&var)); + VariantClear(&var); + } + + hres = init_dispex(dispex, ctx, builtin_info, prot); + + if(prot) + IDispatchEx_Release(_IDispatchEx_(prot)); + return hres; +} + DispatchEx *iface_to_jsdisp(IUnknown *iface) { DispatchEx *ret; @@ -798,6 +815,12 @@ return ret; } +HRESULT jsdisp_call_value(DispatchEx *disp, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, + jsexcept_t *ei, IServiceProvider *caller) +{ + return disp->builtin_info->value_prop.invoke(disp, lcid, flags, dp, retv, ei, caller); +} + HRESULT jsdisp_call(DispatchEx *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) {
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 96fbf78..a9c61e0 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c
@@ -34,6 +34,8 @@ DWORD length; } FunctionInstance; +static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0}; + static const WCHAR lengthW[] = {'l','e','n','g','t','h',0}; static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0}; @@ -176,7 +178,14 @@ function->length = flags & PROPF_ARGMASK; if(prototype) { - hres = jsdisp_set_prototype(&function->dispex, prototype); + jsexcept_t jsexcept; + VARIANT var; + + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype); + memset(&jsexcept, 0, sizeof(jsexcept)); + + hres = jsdisp_propput_name(&function->dispex, prototypeW, ctx->lcid, &var, &jsexcept, NULL/*FIXME*/); if(FAILED(hres)) { IDispatchEx_Release(_IDispatchEx_(&function->dispex)); return hres;
diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index b16ca8c..5ed7d1d 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c
@@ -53,6 +53,18 @@ static const WCHAR CollectGarbageW[] = {'C','o','l','l','e','c','t','G','a','r','b','a','g','e',0}; static const WCHAR MathW[] = {'M','a','t','h',0}; +static HRESULT constructor_call(DispatchEx *constr, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + if(flags != DISPATCH_PROPERTYGET) + return jsdisp_call_value(constr, lcid, flags, dp, retv, ei, sp); + + V_VT(retv) = VT_DISPATCH; + V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(constr); + IDispatchEx_AddRef(_IDispatchEx_(constr)); + return S_OK; +} + static HRESULT JSGlobal_NaN(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { @@ -105,8 +117,9 @@ static HRESULT JSGlobal_Object(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + return constructor_call(dispex->ctx->object_constr, lcid, flags, dp, retv, ei, sp); } static HRESULT JSGlobal_String(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, @@ -280,10 +293,27 @@ NULL }; +static HRESULT init_constructors(script_ctx_t *ctx) +{ + HRESULT hres; + + hres = create_object_constr(ctx, &ctx->object_constr); + if(FAILED(hres)) + return hres; + + return S_OK; +} + HRESULT init_global(script_ctx_t *ctx) { + HRESULT hres; + if(ctx->global) return S_OK; + hres = init_constructors(ctx); + if(FAILED(hres)) + return hres; + return create_dispex(ctx, &JSGlobal_info, NULL, &ctx->global); }
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 0144dbf..0deafc9 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h
@@ -50,7 +50,8 @@ typedef enum { JSCLASS_NONE, JSCLASS_FUNCTION, - JSCLASS_GLOBAL + JSCLASS_GLOBAL, + JSCLASS_OBJECT } jsclass_t; typedef HRESULT (*builtin_invoke_t)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); @@ -87,9 +88,18 @@ #define _IDispatchEx_(x) ((IDispatchEx*) &(x)->lpIDispatchExVtbl) +static inline void jsdisp_release(DispatchEx *jsdisp) +{ + IDispatchEx_Release(_IDispatchEx_(jsdisp)); +} + HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,DispatchEx*,DispatchEx**); HRESULT init_dispex(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*); +HRESULT init_dispex_from_constr(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*); +DispatchEx *iface_to_jsdisp(IUnknown*); + HRESULT disp_call(IDispatch*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); +HRESULT jsdisp_call_value(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT disp_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT disp_propput(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); @@ -117,6 +127,7 @@ DispatchEx *script_disp; DispatchEx *global; + DispatchEx *object_constr; }; void script_release(script_ctx_t*); @@ -128,6 +139,8 @@ HRESULT init_global(script_ctx_t*); +HRESULT create_object_constr(script_ctx_t*,DispatchEx**); + const char *debugstr_variant(const VARIANT*); HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**);
diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c new file mode 100644 index 0000000..2cca6e9 --- /dev/null +++ b/dlls/jscript/object.c
@@ -0,0 +1,125 @@ +/* + * Copyright 2008 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "jscript.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + +static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; +static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0}; +static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0}; +static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0}; +static const WCHAR propertyIsEnumerableW[] = + {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0}; +static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0}; + +static HRESULT Object_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Object_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Object_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Object_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Object_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Object_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Object_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static void Object_destructor(DispatchEx *dispex) +{ + heap_free(dispex); +} + +static const builtin_prop_t Object_props[] = { + {hasOwnPropertyW, Object_hasOwnProperty, PROPF_METHOD}, + {isPrototypeOfW, Object_isPrototypeOf, PROPF_METHOD}, + {propertyIsEnumerableW, Object_propertyIsEnumerable, PROPF_METHOD}, + {toLocaleStringW, Object_toLocaleString, PROPF_METHOD}, + {toStringW, Object_toString, PROPF_METHOD}, + {valueOfW, Object_valueOf, PROPF_METHOD} +}; + +static const builtin_info_t Object_info = { + JSCLASS_OBJECT, + {NULL, Object_value, 0}, + sizeof(Object_props)/sizeof(*Object_props), + Object_props, + Object_destructor, + NULL +}; + +static HRESULT ObjectConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +HRESULT create_object_constr(script_ctx_t *ctx, DispatchEx **ret) +{ + DispatchEx *object; + HRESULT hres; + + hres = create_dispex(ctx, &Object_info, NULL, &object); + if(FAILED(hres)) + return hres; + + hres = create_builtin_function(ctx, ObjectConstr_value, PROPF_CONSTR, object, ret); + + jsdisp_release(object); + return hres; +}
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 67ed686..ef3d4d5 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js
@@ -46,4 +46,7 @@ ok(testFunc1.length === 2, "testFunc1.length is not 2"); +ok(Object.prototype !== undefined, "Object.prototype is undefined"); +ok(Object.prototype.prototype === undefined, "Object.prototype is not undefined"); + reportSuccess();