jscript: Added Object constructor object implementation.
[wine] / dlls / jscript / function.c
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "jscript.h"
20 #include "engine.h"
21
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
25
26 typedef struct {
27     DispatchEx dispex;
28     builtin_invoke_t value_proc;
29     DWORD flags;
30     source_elements_t *source;
31     parameter_t *parameters;
32     scope_chain_t *scope_chain;
33     parser_ctx_t *parser;
34     DWORD length;
35 } FunctionInstance;
36
37 static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
38
39 static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
40 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
41 static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
42 static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
43 static const WCHAR applyW[] = {'a','p','p','l','y',0};
44 static const WCHAR callW[] = {'c','a','l','l',0};
45 static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
46 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};
47 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
48
49 static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
50         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
51 {
52     FunctionInstance *This = (FunctionInstance*)dispex;
53
54     TRACE("%p %d\n", This, This->length);
55
56     switch(flags) {
57     case DISPATCH_PROPERTYGET:
58         V_VT(retv) = VT_I4;
59         V_I4(retv) = This->length;
60         break;
61     default:
62         FIXME("unimplemented flags %x\n", flags);
63         return E_NOTIMPL;
64     }
65
66     return S_OK;
67 }
68
69 static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
70         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
71 {
72     FIXME("\n");
73     return E_NOTIMPL;
74 }
75
76 static HRESULT Function_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
77         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
78 {
79     FIXME("\n");
80     return E_NOTIMPL;
81 }
82
83 static HRESULT Function_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
84         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
85 {
86     FIXME("\n");
87     return E_NOTIMPL;
88 }
89
90 static HRESULT Function_apply(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
91         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
92 {
93     FIXME("\n");
94     return E_NOTIMPL;
95 }
96
97 static HRESULT Function_call(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
98         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
99 {
100     FIXME("\n");
101     return E_NOTIMPL;
102 }
103
104 static HRESULT Function_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
105         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
106 {
107     FIXME("\n");
108     return E_NOTIMPL;
109 }
110
111 static HRESULT Function_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
112         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
113 {
114     FIXME("\n");
115     return E_NOTIMPL;
116 }
117
118 static HRESULT Function_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
119         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
120 {
121     FIXME("\n");
122     return E_NOTIMPL;
123 }
124
125 static HRESULT Function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
126         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
127 {
128     FIXME("\n");
129     return E_NOTIMPL;
130 }
131
132 static void Function_destructor(DispatchEx *dispex)
133 {
134     FunctionInstance *This = (FunctionInstance*)dispex;
135
136     if(This->parser)
137         parser_release(This->parser);
138     if(This->scope_chain)
139         scope_release(This->scope_chain);
140     heap_free(This);
141 }
142
143 static const builtin_prop_t Function_props[] = {
144     {applyW,                 Function_apply,                 PROPF_METHOD},
145     {callW,                  Function_call,                  PROPF_METHOD},
146     {hasOwnPropertyW,        Function_hasOwnProperty,        PROPF_METHOD},
147     {isPrototypeOfW,         Function_isPrototypeOf,         PROPF_METHOD},
148     {lengthW,                Function_length,                0},
149     {propertyIsEnumerableW,  Function_propertyIsEnumerable,  PROPF_METHOD},
150     {toLocaleStringW,        Function_toLocaleString,        PROPF_METHOD},
151     {toStringW,              Function_toString,              PROPF_METHOD},
152     {valueOfW,               Function_valueOf,               PROPF_METHOD}
153 };
154
155 static const builtin_info_t Function_info = {
156     JSCLASS_FUNCTION,
157     {NULL, Function_value, 0},
158     sizeof(Function_props)/sizeof(*Function_props),
159     Function_props,
160     Function_destructor,
161     NULL
162 };
163
164 static HRESULT create_function(script_ctx_t *ctx, DWORD flags, DispatchEx *prototype, FunctionInstance **ret)
165 {
166     FunctionInstance *function;
167     HRESULT hres;
168
169     function = heap_alloc_zero(sizeof(FunctionInstance));
170     if(!function)
171         return E_OUTOFMEMORY;
172
173     hres = init_dispex(&function->dispex, ctx, &Function_info, NULL);
174     if(FAILED(hres))
175         return hres;
176
177     function->flags = flags;
178     function->length = flags & PROPF_ARGMASK;
179
180     if(prototype) {
181         jsexcept_t jsexcept;
182         VARIANT var;
183
184         V_VT(&var) = VT_DISPATCH;
185         V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype);
186         memset(&jsexcept, 0, sizeof(jsexcept));
187
188         hres = jsdisp_propput_name(&function->dispex, prototypeW, ctx->lcid, &var, &jsexcept, NULL/*FIXME*/);
189         if(FAILED(hres)) {
190             IDispatchEx_Release(_IDispatchEx_(&function->dispex));
191             return hres;
192         }
193     }
194
195     *ret = function;
196     return S_OK;
197 }
198
199 HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, DWORD flags,
200         DispatchEx *prototype, DispatchEx **ret)
201 {
202     FunctionInstance *function;
203     HRESULT hres;
204
205     hres = create_function(ctx, flags, prototype, &function);
206     if(FAILED(hres))
207         return hres;
208
209     function->value_proc = value_proc;
210
211     *ret = &function->dispex;
212     return S_OK;
213 }
214
215 HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, source_elements_t *source,
216         scope_chain_t *scope_chain, DispatchEx **ret)
217 {
218     FunctionInstance *function;
219     parameter_t *iter;
220     DWORD length = 0;
221     HRESULT hres;
222
223     hres = create_function(ctx->script, PROPF_CONSTR, NULL, &function);
224     if(FAILED(hres))
225         return hres;
226
227     function->source = source;
228     function->parameters = parameters;
229
230     if(scope_chain) {
231         scope_addref(scope_chain);
232         function->scope_chain = scope_chain;
233     }
234
235     parser_addref(ctx);
236     function->parser = ctx;
237
238     for(iter = parameters; iter; iter = iter->next)
239         length++;
240     function->length = length;
241
242     *ret = &function->dispex;
243     return S_OK;
244 }