jscript: Added Function.length 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
21 #include "wine/debug.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
24
25 typedef struct {
26     DispatchEx dispex;
27     builtin_invoke_t value_proc;
28     DWORD flags;
29     DWORD length;
30 } FunctionInstance;
31
32 static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
33 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
34 static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
35 static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
36 static const WCHAR applyW[] = {'a','p','p','l','y',0};
37 static const WCHAR callW[] = {'c','a','l','l',0};
38 static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
39 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};
40 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
41
42 static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
43         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
44 {
45     FunctionInstance *This = (FunctionInstance*)dispex;
46
47     TRACE("%p %d\n", This, This->length);
48
49     switch(flags) {
50     case DISPATCH_PROPERTYGET:
51         V_VT(retv) = VT_I4;
52         V_I4(retv) = This->length;
53         break;
54     default:
55         FIXME("unimplemented flags %x\n", flags);
56         return E_NOTIMPL;
57     }
58
59     return S_OK;
60 }
61
62 static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
63         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
64 {
65     FIXME("\n");
66     return E_NOTIMPL;
67 }
68
69 static HRESULT Function_toLocaleString(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_valueOf(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_apply(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_call(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_hasOwnProperty(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_propertyIsEnumerable(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_isPrototypeOf(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_value(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 void Function_destructor(DispatchEx *dispex)
126 {
127     FunctionInstance *This = (FunctionInstance*)dispex;
128
129     heap_free(This);
130 }
131
132 static const builtin_prop_t Function_props[] = {
133     {applyW,                 Function_apply,                 PROPF_METHOD},
134     {callW,                  Function_call,                  PROPF_METHOD},
135     {hasOwnPropertyW,        Function_hasOwnProperty,        PROPF_METHOD},
136     {isPrototypeOfW,         Function_isPrototypeOf,         PROPF_METHOD},
137     {lengthW,                Function_length,                0},
138     {propertyIsEnumerableW,  Function_propertyIsEnumerable,  PROPF_METHOD},
139     {toLocaleStringW,        Function_toLocaleString,        PROPF_METHOD},
140     {toStringW,              Function_toString,              PROPF_METHOD},
141     {valueOfW,               Function_valueOf,               PROPF_METHOD}
142 };
143
144 static const builtin_info_t Function_info = {
145     JSCLASS_FUNCTION,
146     {NULL, Function_value, 0},
147     sizeof(Function_props)/sizeof(*Function_props),
148     Function_props,
149     Function_destructor,
150     NULL
151 };
152
153 static HRESULT create_function(script_ctx_t *ctx, DWORD flags, DispatchEx *prototype, FunctionInstance **ret)
154 {
155     FunctionInstance *function;
156     HRESULT hres;
157
158     function = heap_alloc_zero(sizeof(FunctionInstance));
159     if(!function)
160         return E_OUTOFMEMORY;
161
162     hres = init_dispex(&function->dispex, ctx, &Function_info, NULL);
163     if(FAILED(hres))
164         return hres;
165
166     function->flags = flags;
167     function->length = flags & PROPF_ARGMASK;
168
169     if(prototype) {
170         hres = jsdisp_set_prototype(&function->dispex, prototype);
171         if(FAILED(hres)) {
172             IDispatchEx_Release(_IDispatchEx_(&function->dispex));
173             return hres;
174         }
175     }
176
177     *ret = function;
178     return S_OK;
179 }
180
181 HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, DWORD flags,
182         DispatchEx *prototype, DispatchEx **ret)
183 {
184     FunctionInstance *function;
185     HRESULT hres;
186
187     hres = create_function(ctx, flags, prototype, &function);
188     if(FAILED(hres))
189         return hres;
190
191     function->value_proc = value_proc;
192
193     *ret = &function->dispex;
194     return S_OK;
195 }