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