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();