jscript: Added Global.encodeURIComponent implementation.
[wine] / dlls / jscript / tests / run.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 <stdio.h>
20
21 #define COBJMACROS
22 #define CONST_VTABLE
23
24 #include <ole2.h>
25 #include <dispex.h>
26 #include <activscp.h>
27
28 #include "wine/test.h"
29
30 static const CLSID CLSID_JScript =
31     {0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}};
32
33 #define DEFINE_EXPECT(func) \
34     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
35
36 #define SET_EXPECT(func) \
37     expect_ ## func = TRUE
38
39 #define SET_CALLED(func) \
40     called_ ## func = TRUE
41
42 #define CHECK_EXPECT2(func) \
43     do { \
44         ok(expect_ ##func, "unexpected call " #func "\n"); \
45         called_ ## func = TRUE; \
46     }while(0)
47
48 #define CHECK_EXPECT(func) \
49     do { \
50         CHECK_EXPECT2(func); \
51         expect_ ## func = FALSE; \
52     }while(0)
53
54 #define CHECK_CALLED(func) \
55     do { \
56         ok(called_ ## func, "expected " #func "\n"); \
57         expect_ ## func = called_ ## func = FALSE; \
58     }while(0)
59
60 DEFINE_EXPECT(global_propget_d);
61 DEFINE_EXPECT(global_propget_i);
62 DEFINE_EXPECT(global_propput_d);
63 DEFINE_EXPECT(global_propput_i);
64 DEFINE_EXPECT(global_success_d);
65 DEFINE_EXPECT(global_success_i);
66 DEFINE_EXPECT(global_notexists_d);
67 DEFINE_EXPECT(testobj_delete);
68 DEFINE_EXPECT(testobj_value);
69 DEFINE_EXPECT(testobj_prop_d);
70 DEFINE_EXPECT(testobj_noprop_d);
71 DEFINE_EXPECT(GetItemInfo_testVal);
72
73 #define DISPID_GLOBAL_TESTPROPGET   0x1000
74 #define DISPID_GLOBAL_TESTPROPPUT   0x1001
75 #define DISPID_GLOBAL_REPORTSUCCESS 0x1002
76 #define DISPID_GLOBAL_TRACE         0x1003
77 #define DISPID_GLOBAL_OK            0x1004
78 #define DISPID_GLOBAL_GETVT         0x1005
79 #define DISPID_GLOBAL_TESTOBJ       0x1006
80 #define DISPID_GLOBAL_NULL_BSTR     0x1007
81 #define DISPID_GLOBAL_NULL_DISP     0x1008
82 #define DISPID_GLOBAL_TESTTHIS      0x1009
83 #define DISPID_GLOBAL_TESTTHIS2     0x100a
84
85 #define DISPID_TESTOBJ_PROP         0x2000
86
87 static const WCHAR testW[] = {'t','e','s','t',0};
88 static const CHAR testA[] = "test";
89 static const WCHAR test_valW[] = {'t','e','s','t','V','a','l',0};
90 static const CHAR test_valA[] = "testVal";
91
92 static BOOL strict_dispid_check;
93 static const char *test_name = "(null)";
94 static IDispatch *script_disp;
95
96 static BSTR a2bstr(const char *str)
97 {
98     BSTR ret;
99     int len;
100
101     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
102     ret = SysAllocStringLen(NULL, len-1);
103     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
104
105     return ret;
106 }
107
108 static int strcmp_wa(LPCWSTR strw, const char *stra)
109 {
110     CHAR buf[512];
111     WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), 0, 0);
112     return lstrcmpA(buf, stra);
113 }
114
115 static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
116 {
117     *ppv = NULL;
118
119     if(IsEqualGUID(riid, &IID_IUnknown)
120        || IsEqualGUID(riid, &IID_IDispatch)
121        || IsEqualGUID(riid, &IID_IDispatchEx))
122         *ppv = iface;
123     else
124         return E_NOINTERFACE;
125
126     return S_OK;
127 }
128
129 static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
130 {
131     return 2;
132 }
133
134 static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
135 {
136     return 1;
137 }
138
139 static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
140 {
141     ok(0, "unexpected call\n");
142     return E_NOTIMPL;
143 }
144
145 static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
146                                               LCID lcid, ITypeInfo **ppTInfo)
147 {
148     ok(0, "unexpected call\n");
149     return E_NOTIMPL;
150 }
151
152 static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
153                                                 LPOLESTR *rgszNames, UINT cNames,
154                                                 LCID lcid, DISPID *rgDispId)
155 {
156     ok(0, "unexpected call\n");
157     return E_NOTIMPL;
158 }
159
160 static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
161                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
162                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
163 {
164     ok(0, "unexpected call\n");
165     return E_NOTIMPL;
166 }
167
168 static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
169 {
170     ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex);
171     return E_NOTIMPL;
172 }
173
174 static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
175 {
176     ok(0, "unexpected call\n");
177     return E_NOTIMPL;
178 }
179
180 static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
181 {
182     ok(0, "unexpected call\n");
183     return E_NOTIMPL;
184 }
185
186 static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
187 {
188     ok(0, "unexpected call\n");
189     return E_NOTIMPL;
190 }
191
192 static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
193 {
194     ok(0, "unexpected call\n");
195     return E_NOTIMPL;
196 }
197
198 static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
199 {
200     ok(0, "unexpected call\n");
201     return E_NOTIMPL;
202 }
203
204 static HRESULT WINAPI testObj_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
205 {
206     if(!strcmp_wa(bstrName, "prop")) {
207         CHECK_EXPECT(testobj_prop_d);
208         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
209         *pid = DISPID_TESTOBJ_PROP;
210         return S_OK;
211     }
212     if(!strcmp_wa(bstrName, "noprop")) {
213         CHECK_EXPECT(testobj_noprop_d);
214         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
215         return DISP_E_UNKNOWNNAME;
216     }
217
218     ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName));
219     return E_NOTIMPL;
220 }
221
222 static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
223         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
224 {
225     switch(id) {
226     case DISPID_VALUE:
227         CHECK_EXPECT(testobj_value);
228
229         ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
230         ok(pdp != NULL, "pdp == NULL\n");
231         ok(!pdp->rgvarg, "rgvarg != NULL\n");
232         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
233         ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs);
234         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
235         ok(pvarRes != NULL, "pvarRes == NULL\n");
236         ok(V_VT(pvarRes) ==  VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
237         ok(pei != NULL, "pei == NULL\n");
238
239         V_VT(pvarRes) = VT_I4;
240         V_I4(pvarRes) = 1;
241         return S_OK;
242     }
243
244     ok(0, "unexpected call %x\n", id);
245     return DISP_E_MEMBERNOTFOUND;
246 }
247
248 static HRESULT WINAPI testObj_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
249 {
250     CHECK_EXPECT(testobj_delete);
251
252     ok(!strcmp_wa(bstrName, "deleteTest"), "unexpected name %s\n", wine_dbgstr_w(bstrName));
253     ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
254     return S_OK;
255 }
256
257 static IDispatchExVtbl testObjVtbl = {
258     DispatchEx_QueryInterface,
259     DispatchEx_AddRef,
260     DispatchEx_Release,
261     DispatchEx_GetTypeInfoCount,
262     DispatchEx_GetTypeInfo,
263     DispatchEx_GetIDsOfNames,
264     DispatchEx_Invoke,
265     testObj_GetDispID,
266     testObj_InvokeEx,
267     testObj_DeleteMemberByName,
268     DispatchEx_DeleteMemberByDispID,
269     DispatchEx_GetMemberProperties,
270     DispatchEx_GetMemberName,
271     DispatchEx_GetNextDispID,
272     DispatchEx_GetNameSpaceParent
273 };
274
275 static IDispatchEx testObj = { &testObjVtbl };
276
277 static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
278 {
279     if(!strcmp_wa(bstrName, "ok")) {
280         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
281         *pid = DISPID_GLOBAL_OK;
282         return S_OK;
283     }
284     if(!strcmp_wa(bstrName, "trace")) {
285         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
286         *pid = DISPID_GLOBAL_TRACE;
287         return S_OK;
288     }
289     if(!strcmp_wa(bstrName, "reportSuccess")) {
290         CHECK_EXPECT(global_success_d);
291         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
292         *pid = DISPID_GLOBAL_REPORTSUCCESS;
293         return S_OK;
294     }
295     if(!strcmp_wa(bstrName, "testPropGet")) {
296         CHECK_EXPECT(global_propget_d);
297         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
298         *pid = DISPID_GLOBAL_TESTPROPGET;
299         return S_OK;
300     }
301     if(!strcmp_wa(bstrName, "testPropPut")) {
302         CHECK_EXPECT(global_propput_d);
303         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
304         *pid = DISPID_GLOBAL_TESTPROPPUT;
305         return S_OK;
306     }
307     if(!strcmp_wa(bstrName, "getVT")) {
308         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
309         *pid = DISPID_GLOBAL_GETVT;
310         return S_OK;
311     }
312     if(!strcmp_wa(bstrName, "testObj")) {
313         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
314         *pid = DISPID_GLOBAL_TESTOBJ;
315         return S_OK;
316     }
317     if(!strcmp_wa(bstrName, "createNullBSTR")) {
318         *pid = DISPID_GLOBAL_NULL_BSTR;
319         return S_OK;
320     }
321     if(!strcmp_wa(bstrName, "nullDisp")) {
322         *pid = DISPID_GLOBAL_NULL_DISP;
323         return S_OK;
324     }
325     if(!strcmp_wa(bstrName, "notExists")) {
326         CHECK_EXPECT(global_notexists_d);
327         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
328         return DISP_E_UNKNOWNNAME;
329     }
330
331     if(!strcmp_wa(bstrName, "testThis")) {
332         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
333         *pid = DISPID_GLOBAL_TESTTHIS;
334         return S_OK;
335     }
336
337     if(!strcmp_wa(bstrName, "testThis2")) {
338         ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
339         *pid = DISPID_GLOBAL_TESTTHIS2;
340         return S_OK;
341     }
342
343     if(strict_dispid_check)
344         ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName));
345     return DISP_E_UNKNOWNNAME;
346 }
347
348 static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
349         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
350 {
351     switch(id) {
352     case DISPID_GLOBAL_OK:
353         ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags);
354         ok(pdp != NULL, "pdp == NULL\n");
355         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
356         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
357         ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs);
358         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
359         if(wFlags & INVOKE_PROPERTYGET)
360             ok(pvarRes != NULL, "pvarRes == NULL\n");
361         else
362             ok(!pvarRes, "pvarRes != NULL\n");
363         ok(pei != NULL, "pei == NULL\n");
364
365         ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
366         ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg));
367         ok(V_BOOL(pdp->rgvarg+1), "%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
368
369         return S_OK;
370
371      case DISPID_GLOBAL_TRACE:
372         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
373         ok(pdp != NULL, "pdp == NULL\n");
374         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
375         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
376         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
377         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
378         ok(!pvarRes, "pvarRes != NULL\n");
379         ok(pei != NULL, "pei == NULL\n");
380
381         ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
382         if(V_VT(pdp->rgvarg) == VT_BSTR)
383             trace("%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
384
385         return S_OK;
386
387     case DISPID_GLOBAL_REPORTSUCCESS:
388         CHECK_EXPECT(global_success_i);
389
390         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
391         ok(pdp != NULL, "pdp == NULL\n");
392         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
393         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
394         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
395         ok(!pvarRes, "pvarRes != NULL\n");
396         ok(pei != NULL, "pei == NULL\n");
397
398         return S_OK;
399
400      case DISPID_GLOBAL_TESTPROPGET:
401         CHECK_EXPECT(global_propget_i);
402
403         ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
404         ok(pdp != NULL, "pdp == NULL\n");
405         ok(!pdp->rgvarg, "rgvarg != NULL\n");
406         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
407         ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs);
408         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
409         ok(pvarRes != NULL, "pvarRes == NULL\n");
410         ok(V_VT(pvarRes) ==  VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
411         ok(pei != NULL, "pei == NULL\n");
412
413         V_VT(pvarRes) = VT_I4;
414         V_I4(pvarRes) = 1;
415
416         return S_OK;
417
418     case DISPID_GLOBAL_TESTPROPPUT:
419         CHECK_EXPECT(global_propput_i);
420
421         ok(wFlags == INVOKE_PROPERTYPUT, "wFlags = %x\n", wFlags);
422         ok(pdp != NULL, "pdp == NULL\n");
423         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
424         ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n");
425         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
426         ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs);
427         ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]);
428         ok(!pvarRes, "pvarRes != NULL\n");
429
430         ok(V_VT(pdp->rgvarg) == VT_I4, "V_VT(pdp->rgvarg)=%d\n", V_VT(pdp->rgvarg));
431         ok(V_I4(pdp->rgvarg) == 1, "V_I4(pdp->rgvarg)=%d\n", V_I4(pdp->rgvarg));
432         return S_OK;
433
434      case DISPID_GLOBAL_GETVT:
435         ok(pdp != NULL, "pdp == NULL\n");
436         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
437         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
438         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
439         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
440         ok(pvarRes != NULL, "pvarRes == NULL\n");
441         ok(V_VT(pvarRes) ==  VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
442         ok(pei != NULL, "pei == NULL\n");
443
444         V_VT(pvarRes) = VT_BSTR;
445         switch(V_VT(pdp->rgvarg)) {
446         case VT_EMPTY:
447             V_BSTR(pvarRes) = a2bstr("VT_EMPTY");
448             break;
449         case VT_NULL:
450             V_BSTR(pvarRes) = a2bstr("VT_NULL");
451             break;
452         case VT_I4:
453             V_BSTR(pvarRes) = a2bstr("VT_I4");
454             break;
455         case VT_R8:
456             V_BSTR(pvarRes) = a2bstr("VT_R8");
457             break;
458         case VT_BSTR:
459             V_BSTR(pvarRes) = a2bstr("VT_BSTR");
460             break;
461         case VT_DISPATCH:
462             V_BSTR(pvarRes) = a2bstr("VT_DISPATCH");
463             break;
464         case VT_BOOL:
465             V_BSTR(pvarRes) = a2bstr("VT_BOOL");
466             break;
467         default:
468             ok(0, "unknown vt %d\n", V_VT(pdp->rgvarg));
469             return E_FAIL;
470         }
471
472         return S_OK;
473
474     case DISPID_GLOBAL_TESTOBJ:
475         ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
476         ok(pdp != NULL, "pdp == NULL\n");
477         ok(!pdp->rgvarg, "rgvarg != NULL\n");
478         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
479         ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs);
480         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
481         ok(pvarRes != NULL, "pvarRes == NULL\n");
482         ok(V_VT(pvarRes) ==  VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
483         ok(pei != NULL, "pei == NULL\n");
484
485         V_VT(pvarRes) = VT_DISPATCH;
486         V_DISPATCH(pvarRes) = (IDispatch*)&testObj;
487         return S_OK;
488
489     case DISPID_GLOBAL_NULL_BSTR:
490         if(pvarRes) {
491             V_VT(pvarRes) = VT_BSTR;
492             V_BSTR(pvarRes) = NULL;
493         }
494         return S_OK;
495
496     case DISPID_GLOBAL_NULL_DISP:
497         ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
498         ok(pdp != NULL, "pdp == NULL\n");
499         ok(!pdp->rgvarg, "rgvarg != NULL\n");
500         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
501         ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs);
502         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
503         ok(pvarRes != NULL, "pvarRes == NULL\n");
504         ok(V_VT(pvarRes) ==  VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
505         ok(pei != NULL, "pei == NULL\n");
506
507         V_VT(pvarRes) = VT_DISPATCH;
508         V_DISPATCH(pvarRes) = NULL;
509         return S_OK;
510
511     case DISPID_GLOBAL_TESTTHIS:
512         ok(pdp != NULL, "pdp == NULL\n");
513         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
514         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
515         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
516         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
517         ok(pvarRes == NULL, "pvarRes != NULL\n");
518         ok(pei != NULL, "pei == NULL\n");
519
520         ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(arg) = %d\n", V_VT(pdp->rgvarg));
521         ok(V_DISPATCH(pdp->rgvarg) == (IDispatch*)iface, "disp != iface\n");
522
523         return S_OK;
524
525     case DISPID_GLOBAL_TESTTHIS2:
526         ok(pdp != NULL, "pdp == NULL\n");
527         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
528         ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
529         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
530         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
531         ok(pvarRes == NULL, "pvarRes != NULL\n");
532         ok(pei != NULL, "pei == NULL\n");
533
534         ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(arg) = %d\n", V_VT(pdp->rgvarg));
535         ok(V_DISPATCH(pdp->rgvarg) != (IDispatch*)iface, "disp == iface\n");
536         ok(V_DISPATCH(pdp->rgvarg) == script_disp, "disp != script_disp\n");
537
538         return S_OK;
539     }
540
541     ok(0, "unexpected call %x\n", id);
542     return DISP_E_MEMBERNOTFOUND;
543 }
544
545 static IDispatchExVtbl GlobalVtbl = {
546     DispatchEx_QueryInterface,
547     DispatchEx_AddRef,
548     DispatchEx_Release,
549     DispatchEx_GetTypeInfoCount,
550     DispatchEx_GetTypeInfo,
551     DispatchEx_GetIDsOfNames,
552     DispatchEx_Invoke,
553     Global_GetDispID,
554     Global_InvokeEx,
555     DispatchEx_DeleteMemberByName,
556     DispatchEx_DeleteMemberByDispID,
557     DispatchEx_GetMemberProperties,
558     DispatchEx_GetMemberName,
559     DispatchEx_GetNextDispID,
560     DispatchEx_GetNameSpaceParent
561 };
562
563 static IDispatchEx Global = { &GlobalVtbl };
564
565 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
566 {
567     *ppv = NULL;
568
569     if(IsEqualGUID(&IID_IUnknown, riid))
570         *ppv = iface;
571     else if(IsEqualGUID(&IID_IActiveScriptSite, riid))
572         *ppv = iface;
573     else
574         return E_NOINTERFACE;
575
576     IUnknown_AddRef((IUnknown*)*ppv);
577     return S_OK;
578 }
579
580 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
581 {
582     return 2;
583 }
584
585 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
586 {
587     return 1;
588 }
589
590 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid)
591 {
592     *plcid = GetUserDefaultLCID();
593     return S_OK;
594 }
595
596 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName,
597         DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti)
598 {
599     ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "unexpected dwReturnMask %x\n", dwReturnMask);
600     ok(!ppti, "ppti != NULL\n");
601
602     if(!strcmp_wa(pstrName, test_valA))
603         CHECK_EXPECT(GetItemInfo_testVal);
604     else if(strcmp_wa(pstrName, testA))
605         ok(0, "unexpected pstrName %s\n", wine_dbgstr_w(pstrName));
606
607     *ppiunkItem = (IUnknown*)&Global;
608     return S_OK;
609 }
610
611 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion)
612 {
613     return E_NOTIMPL;
614 }
615
616 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface,
617         const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo)
618 {
619     return E_NOTIMPL;
620 }
621
622 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState)
623 {
624     return E_NOTIMPL;
625 }
626
627 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror)
628 {
629     return E_NOTIMPL;
630 }
631
632 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
633 {
634     return E_NOTIMPL;
635 }
636
637 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
638 {
639     return E_NOTIMPL;
640 }
641
642 #undef ACTSCPSITE_THIS
643
644 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = {
645     ActiveScriptSite_QueryInterface,
646     ActiveScriptSite_AddRef,
647     ActiveScriptSite_Release,
648     ActiveScriptSite_GetLCID,
649     ActiveScriptSite_GetItemInfo,
650     ActiveScriptSite_GetDocVersionString,
651     ActiveScriptSite_OnScriptTerminate,
652     ActiveScriptSite_OnStateChange,
653     ActiveScriptSite_OnScriptError,
654     ActiveScriptSite_OnEnterScript,
655     ActiveScriptSite_OnLeaveScript
656 };
657
658 static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl };
659
660 static IActiveScript *create_script(void)
661 {
662     IActiveScript *script;
663     HRESULT hres;
664
665     hres = CoCreateInstance(&CLSID_JScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
666             &IID_IActiveScript, (void**)&script);
667     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
668
669     return script;
670 }
671
672 static void parse_script(DWORD flags, BSTR script_str)
673 {
674     IActiveScriptParse *parser;
675     IActiveScript *engine;
676     HRESULT hres;
677
678     engine = create_script();
679     if(!engine)
680         return;
681
682     hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser);
683     ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres);
684     if (FAILED(hres))
685     {
686         IActiveScript_Release(engine);
687         return;
688     }
689
690     hres = IActiveScriptParse64_InitNew(parser);
691     ok(hres == S_OK, "InitNew failed: %08x\n", hres);
692
693     hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite);
694     ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres);
695
696     hres = IActiveScript_AddNamedItem(engine, testW,
697             SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|flags);
698     ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres);
699
700     hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED);
701     ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres);
702
703     hres = IActiveScript_GetScriptDispatch(engine, NULL, &script_disp);
704     ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres);
705     ok(script_disp != NULL, "script_disp == NULL\n");
706     ok(script_disp != (IDispatch*)&Global, "script_disp == Global\n");
707
708     hres = IActiveScriptParse64_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
709     ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
710
711     IDispatch_Release(script_disp);
712     IActiveScript_Release(engine);
713     IUnknown_Release(parser);
714 }
715
716 static HRESULT parse_htmlscript(BSTR script_str)
717 {
718     IActiveScriptParse *parser;
719     IActiveScript *engine;
720     HRESULT hres;
721     BSTR tmp = a2bstr("</SCRIPT>");
722
723     engine = create_script();
724     if(!engine)
725         return E_FAIL;
726
727     hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser);
728     ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres);
729     if (FAILED(hres))
730     {
731         IActiveScript_Release(engine);
732         return E_FAIL;
733     }
734
735     hres = IActiveScriptParse64_InitNew(parser);
736     ok(hres == S_OK, "InitNew failed: %08x\n", hres);
737
738     hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite);
739     ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres);
740
741     hres = IActiveScript_AddNamedItem(engine, testW,
742             SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS);
743     ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres);
744
745     hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED);
746     ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres);
747
748     hres = IActiveScriptParse64_ParseScriptText(parser, script_str, NULL, NULL, tmp, 0, 0, 0, NULL, NULL);
749
750     IActiveScript_Release(engine);
751     IUnknown_Release(parser);
752     SysFreeString(tmp);
753
754     return hres;
755 }
756
757 static void parse_script_af(DWORD flags, const char *src)
758 {
759     BSTR tmp = a2bstr(src);
760     parse_script(flags, tmp);
761     SysFreeString(tmp);
762 }
763
764 static void parse_script_a(const char *src)
765 {
766     parse_script_af(SCRIPTITEM_GLOBALMEMBERS, src);
767 }
768
769 static HRESULT parse_htmlscript_a(const char *src)
770 {
771     HRESULT hres;
772     BSTR tmp = a2bstr(src);
773     hres = parse_htmlscript(tmp);
774     SysFreeString(tmp);
775
776     return hres;
777 }
778
779 static BSTR get_script_from_file(const char *filename)
780 {
781     DWORD size, len;
782     HANDLE file, map;
783     const char *file_map;
784     BSTR ret;
785
786     file = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
787     if(file == INVALID_HANDLE_VALUE) {
788         trace("Could not open file: %u\n", GetLastError());
789         return NULL;
790     }
791
792     size = GetFileSize(file, NULL);
793
794     map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
795     CloseHandle(file);
796     if(map == INVALID_HANDLE_VALUE) {
797         trace("Could not create file mapping: %u\n", GetLastError());
798         return NULL;
799     }
800
801     file_map = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
802     CloseHandle(map);
803     if(!file_map) {
804         trace("MapViewOfFile failed: %u\n", GetLastError());
805         return NULL;
806     }
807
808     len = MultiByteToWideChar(CP_ACP, 0, file_map, size, NULL, 0);
809     ret = SysAllocStringLen(NULL, len);
810     MultiByteToWideChar(CP_ACP, 0, file_map, size, ret, len);
811
812     UnmapViewOfFile(file_map);
813
814     return ret;
815 }
816
817 static void run_from_file(const char *filename)
818 {
819     BSTR script_str = get_script_from_file(filename);
820
821     strict_dispid_check = FALSE;
822
823     if(script_str)
824         parse_script(SCRIPTITEM_GLOBALMEMBERS, script_str);
825
826     SysFreeString(script_str);
827 }
828
829 static void run_from_res(const char *name)
830 {
831     const char *data;
832     DWORD size, len;
833     BSTR str;
834     HRSRC src;
835
836     strict_dispid_check = FALSE;
837     test_name = name;
838
839     src = FindResourceA(NULL, name, (LPCSTR)40);
840     ok(src != NULL, "Could not find resource %s\n", name);
841
842     size = SizeofResource(NULL, src);
843     data = LoadResource(NULL, src);
844
845     len = MultiByteToWideChar(CP_ACP, 0, data, size, NULL, 0);
846     str = SysAllocStringLen(NULL, len);
847     len = MultiByteToWideChar(CP_ACP, 0, data, size, str, len);
848
849     SET_EXPECT(global_success_d);
850     SET_EXPECT(global_success_i);
851     parse_script(SCRIPTITEM_GLOBALMEMBERS, str);
852     CHECK_CALLED(global_success_d);
853     CHECK_CALLED(global_success_i);
854
855     SysFreeString(str);
856 }
857
858 static void test_isvisible(BOOL global_members)
859 {
860     IActiveScriptParse *parser;
861     IActiveScript *engine;
862     HRESULT hres;
863
864     static const WCHAR script_textW[] =
865         {'v','a','r',' ','v',' ','=',' ','t','e','s','t','V','a','l',';',0};
866
867     engine = create_script();
868     if(!engine)
869         return;
870
871     hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser);
872     ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres);
873     if (FAILED(hres))
874     {
875         IActiveScript_Release(engine);
876         return;
877     }
878
879     hres = IActiveScriptParse64_InitNew(parser);
880     ok(hres == S_OK, "InitNew failed: %08x\n", hres);
881
882     hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite);
883     ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres);
884
885     if(global_members)
886         SET_EXPECT(GetItemInfo_testVal);
887     hres = IActiveScript_AddNamedItem(engine, test_valW,
888             SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|
889             (global_members ? SCRIPTITEM_GLOBALMEMBERS : 0));
890     ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres);
891     if(global_members)
892         CHECK_CALLED(GetItemInfo_testVal);
893
894     hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED);
895     ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres);
896
897     if(!global_members)
898         SET_EXPECT(GetItemInfo_testVal);
899     hres = IActiveScriptParse64_ParseScriptText(parser, script_textW, NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
900     ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
901     if(!global_members)
902         CHECK_CALLED(GetItemInfo_testVal);
903
904     hres = IActiveScriptParse64_ParseScriptText(parser, script_textW, NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
905     ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
906
907     IActiveScript_Release(engine);
908     IUnknown_Release(parser);
909 }
910
911 static void run_tests(void)
912 {
913     HRESULT hres;
914
915     strict_dispid_check = TRUE;
916
917     parse_script_a("");
918     parse_script_a("/* empty */ ;");
919
920     SET_EXPECT(global_propget_d);
921     SET_EXPECT(global_propget_i);
922     parse_script_a("testPropGet;");
923     CHECK_CALLED(global_propget_d);
924     CHECK_CALLED(global_propget_i);
925
926     SET_EXPECT(global_propput_d);
927     SET_EXPECT(global_propput_i);
928     parse_script_a("testPropPut = 1;");
929     CHECK_CALLED(global_propput_d);
930     CHECK_CALLED(global_propput_i);
931
932     SET_EXPECT(global_success_d);
933     SET_EXPECT(global_success_i);
934     parse_script_a("reportSuccess();");
935     CHECK_CALLED(global_success_d);
936     CHECK_CALLED(global_success_i);
937
938     SET_EXPECT(testobj_delete);
939     parse_script_a("delete testObj.deleteTest;");
940     CHECK_CALLED(testobj_delete);
941
942     parse_script_a("ok(typeof(test) === 'object', \"typeof(test) != 'object'\");");
943
944     parse_script_a("function reportSuccess() {}; reportSuccess();");
945
946     SET_EXPECT(global_propget_d);
947     parse_script_a("var testPropGet");
948     CHECK_CALLED(global_propget_d);
949
950     SET_EXPECT(global_notexists_d);
951     parse_script_a("var notExists; notExists = 1;");
952     CHECK_CALLED(global_notexists_d);
953
954     parse_script_a("function f() { var testPropGet; }");
955
956     parse_script_a("ok((testObj instanceof Object) === false, 'testObj is instance of Object');");
957
958     SET_EXPECT(testobj_prop_d);
959     parse_script_a("ok(('prop' in testObj) === true, 'prop is not in testObj');");
960     CHECK_CALLED(testobj_prop_d);
961
962     SET_EXPECT(testobj_noprop_d);
963     parse_script_a("ok(('noprop' in testObj) === false, 'noprop is in testObj');");
964     CHECK_CALLED(testobj_noprop_d);
965
966     SET_EXPECT(testobj_value);
967     parse_script_a("ok(String(testObj) === '1', 'wrong testObj value');");
968     CHECK_CALLED(testobj_value);
969
970     SET_EXPECT(testobj_value);
971     parse_script_a("ok(String.prototype.concat.call(testObj, ' OK') === '1 OK', 'wrong concat result');");
972     CHECK_CALLED(testobj_value);
973
974     SET_EXPECT(global_propget_d);
975     SET_EXPECT(global_propget_i);
976     parse_script_a("this.testPropGet;");
977     CHECK_CALLED(global_propget_d);
978     CHECK_CALLED(global_propget_i);
979
980     SET_EXPECT(global_propget_d);
981     SET_EXPECT(global_propget_i);
982     parse_script_a("(function () { this.testPropGet; })();");
983     CHECK_CALLED(global_propget_d);
984     CHECK_CALLED(global_propget_i);
985
986     parse_script_a("testThis(this);");
987     parse_script_a("(function () { testThis(this); })();");
988
989     run_from_res("lang.js");
990     run_from_res("api.js");
991     run_from_res("regexp.js");
992
993     test_isvisible(FALSE);
994     test_isvisible(TRUE);
995
996     parse_script_af(0, "test.testThis2(this);");
997     parse_script_af(0, "(function () { test.testThis2(this); })();");
998
999     hres = parse_htmlscript_a("<!--");
1000     ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
1001     hres = parse_htmlscript_a("-->");
1002     ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
1003     hres = parse_htmlscript_a("<!--\nvar a=1;\n-->\n");
1004     ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
1005     hres = parse_htmlscript_a("<!--\n<!-- ignore this\n-->\n");
1006     ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
1007     hres = parse_htmlscript_a("var a=1;\nif(a-->0) a=5;\n");
1008     ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
1009     hres = parse_htmlscript_a("var a=1;\nif(a\n-->0) a=5;\n");
1010     ok(hres != S_OK, "ParseScriptText have not failed\n");
1011 }
1012
1013 START_TEST(run)
1014 {
1015     int argc;
1016     char **argv;
1017
1018     argc = winetest_get_mainargs(&argv);
1019
1020     CoInitialize(NULL);
1021
1022     if(argc > 2)
1023         run_from_file(argv[2]);
1024     else
1025         run_tests();
1026
1027     CoUninitialize();
1028 }