d9a71dd26aedb5fc4f0e8f3c5dff0cc754a43d37
[profile/ivi/qtbase.git] / tests / auto / v8 / v8test.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "v8test.h"
43
44 using namespace v8;
45
46 #define BEGINTEST() bool _testPassed = true;
47 #define ENDTEST() return _testPassed;
48
49 #define VERIFY(expr) { \
50     if (!(expr)) { \
51         fprintf(stderr, "FAIL: %s:%d %s\n", __FILE__, __LINE__, # expr); \
52         _testPassed = false; \
53         goto cleanup; \
54     }  \
55 }
56
57 struct MyStringResource : public String::ExternalAsciiStringResource
58 {
59     static bool wasDestroyed;
60     virtual ~MyStringResource() { wasDestroyed = true; }
61     virtual const char* data() const { return "v8test"; }
62     virtual size_t length() const { return 6; }
63 };
64 bool MyStringResource::wasDestroyed = false;
65
66 struct MyResource : public Object::ExternalResource
67 {
68     static bool wasDestroyed;
69     virtual ~MyResource() { wasDestroyed = true; }
70 };
71 bool MyResource::wasDestroyed = false;
72
73 bool v8test_externalteardown()
74 {
75     BEGINTEST();
76
77     Isolate *isolate = v8::Isolate::New();
78     isolate->Enter();
79
80     {
81         HandleScope handle_scope;
82         Persistent<Context> context = Context::New();
83         Context::Scope context_scope(context);
84
85         Local<String> str = String::NewExternal(new MyStringResource);
86
87         Local<FunctionTemplate> ft = FunctionTemplate::New();
88         ft->InstanceTemplate()->SetHasExternalResource(true);
89
90         Local<Object> obj = ft->GetFunction()->NewInstance();
91         obj->SetExternalResource(new MyResource);
92
93         context.Dispose();
94     }
95
96     // while (!v8::V8::IdleNotification()) ;
97     isolate->Exit();
98     isolate->Dispose();
99
100     // ExternalString resources aren't guaranteed to be freed by v8 at this
101     // point. Uncommenting the IdleNotification() line above helps.
102 //    VERIFY(MyStringResource::wasDestroyed);
103
104     VERIFY(MyResource::wasDestroyed);
105
106 cleanup:
107
108     ENDTEST();
109 }
110
111 bool v8test_eval()
112 {
113     BEGINTEST();
114
115     HandleScope handle_scope;
116     Persistent<Context> context = Context::New();
117     Context::Scope context_scope(context);
118
119     Local<Object> qmlglobal = Object::New();
120     qmlglobal->Set(String::New("a"), Integer::New(1922));
121
122     Local<Script> script = Script::Compile(String::New("eval(\"a\")"), NULL, NULL,
123                                            Handle<String>(), Script::QmlMode);
124
125     TryCatch tc;
126     Local<Value> result = script->Run(qmlglobal);
127
128     VERIFY(!tc.HasCaught());
129     VERIFY(result->Int32Value() == 1922);
130
131 cleanup:
132     context.Dispose();
133
134     ENDTEST();
135 }
136
137 bool v8test_globalcall()
138 {
139     BEGINTEST();
140
141     HandleScope handle_scope;
142     Persistent<Context> context = Context::New();
143     Context::Scope context_scope(context);
144
145     Local<Object> qmlglobal = Object::New();
146
147 #define SOURCE "function func1() { return 1; }\n" \
148                "function func2() { var sum = 0; for (var ii = 0; ii < 10000000; ++ii) { sum += func1(); } return sum; }\n" \
149                "func2();"
150
151     Local<Script> script = Script::Compile(String::New(SOURCE), NULL, NULL,
152                                            Handle<String>(), Script::QmlMode);
153     Local<Value> result = script->Run(qmlglobal);
154     VERIFY(!result.IsEmpty());
155     VERIFY(result->IsInt32());
156     VERIFY(result->Int32Value() == 10000000);
157
158 #undef SOURCE
159
160 cleanup:
161     context.Dispose();
162
163     ENDTEST();
164 }
165
166 bool v8test_evalwithinwith()
167 {
168     BEGINTEST();
169
170     HandleScope handle_scope;
171     Persistent<Context> context = Context::New();
172     Context::Scope context_scope(context);
173
174     Local<Object> qmlglobal = Object::New();
175     qmlglobal->Set(String::New("a"), Integer::New(1922));
176     // There was a bug that the "eval" lookup would incorrectly resolve
177     // to the QML global object
178     qmlglobal->Set(String::New("eval"), Integer::New(1922));
179
180 #define SOURCE \
181     "(function() { " \
182     "    var b = { c: 10 }; " \
183     "    with (b) { " \
184     "        return eval(\"a\"); " \
185     "    } " \
186     "})"
187     Local<Script> script = Script::Compile(String::New(SOURCE), NULL, NULL, 
188                                            Handle<String>(), Script::QmlMode);
189 #undef SOURCE
190
191     TryCatch tc;
192     Local<Value> result = script->Run(qmlglobal);
193
194     VERIFY(!tc.HasCaught());
195     VERIFY(result->IsFunction());
196
197     {
198     Local<Value> fresult = Handle<Function>::Cast(result)->Call(context->Global(), 0, 0);
199     VERIFY(!tc.HasCaught());
200     VERIFY(fresult->Int32Value() == 1922);
201     }
202
203 cleanup:
204     context.Dispose();
205
206     ENDTEST();
207 }
208
209 static int userObjectComparisonCalled = 0;
210 static bool userObjectComparisonReturn = false;
211 static Local<Object> expectedLhs;
212 static Local<Object> expectedRhs;
213 static bool expectedObjectsCompared = false;
214
215 #define SET_EXPECTED(lhs, rhs) { \
216     expectedObjectsCompared = false; \
217     expectedLhs = lhs; \
218     expectedRhs = rhs; \
219 }
220
221 static bool UserObjectComparison(Local<Object> lhs, Local<Object> rhs)
222 {
223     userObjectComparisonCalled++;
224
225     expectedObjectsCompared = (lhs == expectedLhs && rhs == expectedRhs);
226
227     return userObjectComparisonReturn;
228 }
229
230 inline bool runscript(const char *source) {
231     Local<Script> script = Script::Compile(String::New(source));
232     Local<Value> result = script->Run();
233     return result->BooleanValue();
234 }
235
236 bool v8test_userobjectcompare()
237 {
238     BEGINTEST();
239
240     HandleScope handle_scope;
241     Persistent<Context> context = Context::New();
242     Context::Scope context_scope(context);
243
244     V8::SetUserObjectComparisonCallbackFunction(UserObjectComparison);
245
246     Local<ObjectTemplate> ot = ObjectTemplate::New();
247     ot->MarkAsUseUserObjectComparison();
248
249     Local<Object> uoc1 = ot->NewInstance();
250     Local<Object> uoc2 = ot->NewInstance();
251     context->Global()->Set(String::New("uoc1a"), uoc1);
252     context->Global()->Set(String::New("uoc1b"), uoc1);
253     context->Global()->Set(String::New("uoc2"), uoc2);
254     Local<Object> obj1 = Object::New();
255     context->Global()->Set(String::New("obj1a"), obj1);
256     context->Global()->Set(String::New("obj1b"), obj1);
257     context->Global()->Set(String::New("obj2"), Object::New());
258     Local<String> string1 = String::New("Hello World");
259     context->Global()->Set(String::New("string1a"), string1);
260     context->Global()->Set(String::New("string1b"), string1);
261     context->Global()->Set(String::New("string2"), v8::String::New("Goodbye World"));
262
263     // XXX Opportunity for optimization - don't invoke user callback if objects are
264     // equal.
265 #if 0
266     userObjectComparisonCalled = 0; userObjectComparisonReturn = false;
267     VERIFY(true == runscript("uoc1a == uoc1b"));
268     VERIFY(userObjectComparisonCalled == 0);
269 #endif
270
271     // Comparing two uoc objects invokes uoc
272     userObjectComparisonCalled = 0;
273     userObjectComparisonReturn = false;
274     VERIFY(false == runscript("uoc1a == uoc2"));
275     VERIFY(userObjectComparisonCalled == 1);
276
277     VERIFY(false == runscript("uoc2 == uoc1a"));
278     VERIFY(userObjectComparisonCalled == 2);
279     userObjectComparisonReturn = true;
280     VERIFY(true == runscript("uoc1a == uoc2"));
281     VERIFY(userObjectComparisonCalled == 3);
282     VERIFY(true == runscript("uoc2 == uoc1a"));
283     VERIFY(userObjectComparisonCalled == 4);
284
285     // != on two uoc object invokes uoc
286     userObjectComparisonCalled = 0;
287     userObjectComparisonReturn = false;
288     VERIFY(true == runscript("uoc1a != uoc2"));
289     VERIFY(userObjectComparisonCalled == 1);
290     VERIFY(true == runscript("uoc2 != uoc1a"));
291     VERIFY(userObjectComparisonCalled == 2);
292     userObjectComparisonReturn = true;
293     VERIFY(false == runscript("uoc1a != uoc2"));
294     VERIFY(userObjectComparisonCalled == 3);
295     VERIFY(false == runscript("uoc2 != uoc1a"));
296     VERIFY(userObjectComparisonCalled == 4);
297
298     // Comparison against a non-object doesn't invoke uoc
299     userObjectComparisonCalled = 0;
300     userObjectComparisonReturn = false;
301     VERIFY(false == runscript("uoc1a == string1a"));
302     VERIFY(userObjectComparisonCalled == 0);
303     VERIFY(false == runscript("string1a == uoc1a"));
304     VERIFY(userObjectComparisonCalled == 0);
305     VERIFY(false == runscript("2 == uoc1a"));
306     VERIFY(userObjectComparisonCalled == 0);
307     VERIFY(true == runscript("uoc1a != string1a"));
308     VERIFY(userObjectComparisonCalled == 0);
309     VERIFY(true == runscript("string1a != uoc1a"));
310     VERIFY(userObjectComparisonCalled == 0);
311     VERIFY(true == runscript("2 != uoc1a"));
312     VERIFY(userObjectComparisonCalled == 0);
313
314     // Comparison against a non-uoc-object still invokes uoc
315     userObjectComparisonCalled = 0;
316     userObjectComparisonReturn = false;
317     VERIFY(false == runscript("uoc1a == obj1a"));
318     VERIFY(userObjectComparisonCalled == 1);
319     VERIFY(false == runscript("obj1a == uoc1a"));
320     VERIFY(userObjectComparisonCalled == 2);
321     userObjectComparisonReturn = true;
322     VERIFY(true == runscript("uoc1a == obj1a"));
323     VERIFY(userObjectComparisonCalled == 3);
324     VERIFY(true == runscript("obj1a == uoc1a"));
325     VERIFY(userObjectComparisonCalled == 4);
326
327     // != comparison against a non-uoc-object still invokes uoc
328     userObjectComparisonCalled = 0;
329     userObjectComparisonReturn = false;
330     VERIFY(true == runscript("uoc1a != obj1a"));
331     VERIFY(userObjectComparisonCalled == 1);
332     VERIFY(true == runscript("obj1a != uoc1a"));
333     VERIFY(userObjectComparisonCalled == 2);
334     userObjectComparisonReturn = true;
335     VERIFY(false == runscript("uoc1a != obj1a"));
336     VERIFY(userObjectComparisonCalled == 3);
337     VERIFY(false == runscript("obj1a != uoc1a"));
338     VERIFY(userObjectComparisonCalled == 4);
339
340     // Comparing two non-uoc objects does not invoke uoc
341     userObjectComparisonCalled = 0;
342     userObjectComparisonReturn = false;
343     VERIFY(true == runscript("obj1a == obj1a"));
344     VERIFY(true == runscript("obj1a == obj1b"));
345     VERIFY(false == runscript("obj1a == obj2"));
346     VERIFY(false == runscript("obj1a == string1a"));
347     VERIFY(true == runscript("string1a == string1a"));
348     VERIFY(true == runscript("string1a == string1b"));
349     VERIFY(false == runscript("string1a == string2"));
350     VERIFY(userObjectComparisonCalled == 0);
351
352     // Correct lhs and rhs passed to uoc
353     userObjectComparisonCalled = 0;
354     userObjectComparisonReturn = false;
355     SET_EXPECTED(uoc1, uoc2);
356     VERIFY(false == runscript("uoc1a == uoc2"));
357     VERIFY(true == expectedObjectsCompared);
358     SET_EXPECTED(uoc2, uoc1);
359     VERIFY(false == runscript("uoc2 == uoc1a"));
360     VERIFY(true == expectedObjectsCompared);
361     SET_EXPECTED(uoc1, uoc2);
362     VERIFY(true == runscript("uoc1a != uoc2"));
363     VERIFY(true == expectedObjectsCompared);
364     SET_EXPECTED(uoc2, uoc1);
365     VERIFY(true == runscript("uoc2 != uoc1a"));
366     VERIFY(true == expectedObjectsCompared);
367     SET_EXPECTED(uoc1, obj1);
368     VERIFY(false == runscript("uoc1a == obj1a"));
369     VERIFY(true == expectedObjectsCompared);
370     SET_EXPECTED(obj1, uoc1);
371     VERIFY(false == runscript("obj1a == uoc1a"));
372     VERIFY(true == expectedObjectsCompared);
373
374 cleanup:
375     V8::SetUserObjectComparisonCallbackFunction(0);
376     context.Dispose();
377
378     ENDTEST();
379 }