Update JSScript SPI based on feedback
[WebKit-https.git] / Source / JavaScriptCore / API / tests / testapi.c
1 /*
2  * Copyright (C) 2006-2017 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #define ASSERT_DISABLED 0
27 #include "config.h"
28
29 #if USE(CF)
30 #include "JavaScriptCore.h"
31 #else
32 #include "JavaScript.h"
33 #endif
34
35 #include "JSBasePrivate.h"
36 #include "JSContextRefPrivate.h"
37 #include "JSHeapFinalizerPrivate.h"
38 #include "JSMarkingConstraintPrivate.h"
39 #include "JSObjectRefPrivate.h"
40 #include "JSScriptRefPrivate.h"
41 #include "JSStringRefPrivate.h"
42 #include "JSWeakPrivate.h"
43 #if !OS(WINDOWS)
44 #include <libgen.h>
45 #endif
46 #include <limits.h>
47 #include <math.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <time.h>
52 #if !OS(WINDOWS)
53 #include <unistd.h>
54 #endif
55 #include <wtf/Assertions.h>
56
57 #if OS(WINDOWS)
58 #include <windows.h>
59 #endif
60
61 #include "CompareAndSwapTest.h"
62 #include "CustomGlobalObjectClassTest.h"
63 #include "ExecutionTimeLimitTest.h"
64 #include "FunctionOverridesTest.h"
65 #include "GlobalContextWithFinalizerTest.h"
66 #include "JSONParseTest.h"
67 #include "JSObjectGetProxyTargetTest.h"
68 #include "MultithreadedMultiVMExecutionTest.h"
69 #include "PingPongStackOverflowTest.h"
70 #include "TypedArrayCTest.h"
71
72 #if COMPILER(MSVC)
73 #pragma warning(disable:4204)
74 #endif
75
76 #if JSC_OBJC_API_ENABLED
77 void testObjectiveCAPI(const char*);
78 #endif
79
80 int testCAPIViaCpp(const char* filter);
81
82 bool assertTrue(bool value, const char* message);
83
84 static JSGlobalContextRef context;
85 int failed;
86 static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
87 {
88     if (JSValueToBoolean(context, value) != expectedValue) {
89         fprintf(stderr, "assertEqualsAsBoolean failed: %p, %d\n", value, expectedValue);
90         failed = 1;
91     }
92 }
93
94 static void assertEqualsAsNumber(JSValueRef value, double expectedValue)
95 {
96     double number = JSValueToNumber(context, value, NULL);
97
98     // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
99     // causing a build break with -Wshorten-64-to-32 enabled.  The issue is known by the appropriate team.
100     // After that's resolved, we can remove these casts
101     if (number != expectedValue && !(isnan((float)number) && isnan((float)expectedValue))) {
102         fprintf(stderr, "assertEqualsAsNumber failed: %p, %lf\n", value, expectedValue);
103         failed = 1;
104     }
105 }
106
107 static void assertEqualsAsUTF8String(JSValueRef value, const char* expectedValue)
108 {
109     JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
110
111     size_t jsSize = JSStringGetMaximumUTF8CStringSize(valueAsString);
112     char* jsBuffer = (char*)malloc(jsSize);
113     JSStringGetUTF8CString(valueAsString, jsBuffer, jsSize);
114
115     unsigned i;
116     for (i = 0; jsBuffer[i]; i++) {
117         if (jsBuffer[i] != expectedValue[i]) {
118             fprintf(stderr, "assertEqualsAsUTF8String failed at character %d: %c(%d) != %c(%d)\n", i, jsBuffer[i], jsBuffer[i], expectedValue[i], expectedValue[i]);
119             fprintf(stderr, "value: %s\n", jsBuffer);
120             fprintf(stderr, "expectedValue: %s\n", expectedValue);
121             failed = 1;
122         }
123     }
124
125     if (jsSize < strlen(jsBuffer) + 1) {
126         fprintf(stderr, "assertEqualsAsUTF8String failed: jsSize was too small\n");
127         failed = 1;
128     }
129
130     free(jsBuffer);
131     JSStringRelease(valueAsString);
132 }
133
134 static void assertEqualsAsCharactersPtr(JSValueRef value, const char* expectedValue)
135 {
136     JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
137
138 #if USE(CF)
139     size_t jsLength = JSStringGetLength(valueAsString);
140     const JSChar* jsBuffer = JSStringGetCharactersPtr(valueAsString);
141
142     CFStringRef expectedValueAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, 
143                                                                     expectedValue,
144                                                                     kCFStringEncodingUTF8);    
145     CFIndex cfLength = CFStringGetLength(expectedValueAsCFString);
146     UniChar* cfBuffer = (UniChar*)malloc(cfLength * sizeof(UniChar));
147     CFStringGetCharacters(expectedValueAsCFString, CFRangeMake(0, cfLength), cfBuffer);
148     CFRelease(expectedValueAsCFString);
149
150     if (memcmp(jsBuffer, cfBuffer, cfLength * sizeof(UniChar)) != 0) {
151         fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
152         failed = 1;
153     }
154     
155     if (jsLength != (size_t)cfLength) {
156 #if OS(WINDOWS)
157         fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%Iu) != cfLength(%Iu)\n", jsLength, (size_t)cfLength);
158 #else
159         fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%zu) != cfLength(%zu)\n", jsLength, (size_t)cfLength);
160 #endif
161         failed = 1;
162     }
163
164     free(cfBuffer);
165 #else
166     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(valueAsString);
167     char* buffer = (char*)malloc(bufferSize);
168     JSStringGetUTF8CString(valueAsString, buffer, bufferSize);
169
170     if (strcmp(buffer, expectedValue)) {
171         fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
172         failed = 1;
173     }
174
175     free(buffer);
176 #endif
177     JSStringRelease(valueAsString);
178 }
179
180 static bool timeZoneIsPST()
181 {
182     char timeZoneName[70];
183     struct tm gtm;
184     memset(&gtm, 0, sizeof(gtm));
185     strftime(timeZoneName, sizeof(timeZoneName), "%Z", &gtm);
186
187     return 0 == strcmp("PST", timeZoneName);
188 }
189
190 static JSValueRef jsGlobalValue; // non-stack value for testing JSValueProtect()
191
192 /* MyObject pseudo-class */
193
194 static bool MyObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
195 {
196     UNUSED_PARAM(context);
197     UNUSED_PARAM(object);
198
199     if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")
200         || JSStringIsEqualToUTF8CString(propertyName, "cantFind")
201         || JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")
202         || JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")
203         || JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")
204         || JSStringIsEqualToUTF8CString(propertyName, "0")) {
205         return true;
206     }
207     
208     return false;
209 }
210
211 static JSValueRef throwException(JSContextRef context, JSObjectRef object, JSValueRef* exception)
212 {
213     JSStringRef script = JSStringCreateWithUTF8CString("throw 'an exception'");
214     JSStringRef sourceURL = JSStringCreateWithUTF8CString("test script");
215     JSValueRef result = JSEvaluateScript(context, script, object, sourceURL, 1, exception);
216     JSStringRelease(script);
217     JSStringRelease(sourceURL);
218     return result;
219 }
220
221 static JSValueRef MyObject_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
222 {
223     UNUSED_PARAM(context);
224     UNUSED_PARAM(object);
225     
226     if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")) {
227         return JSValueMakeNumber(context, 1);
228     }
229     
230     if (JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")) {
231         return JSValueMakeNumber(context, 1);
232     }
233
234     if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
235         return JSValueMakeUndefined(context);
236     }
237     
238     if (JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")) {
239         return 0;
240     }
241
242     if (JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")) {
243         return throwException(context, object, exception);
244     }
245
246     if (JSStringIsEqualToUTF8CString(propertyName, "0")) {
247         *exception = JSValueMakeNumber(context, 1);
248         return JSValueMakeNumber(context, 1);
249     }
250     
251     return JSValueMakeNull(context);
252 }
253
254 static bool MyObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
255 {
256     UNUSED_PARAM(context);
257     UNUSED_PARAM(object);
258     UNUSED_PARAM(value);
259     UNUSED_PARAM(exception);
260
261     if (JSStringIsEqualToUTF8CString(propertyName, "cantSet"))
262         return true; // pretend we set the property in order to swallow it
263     
264     if (JSStringIsEqualToUTF8CString(propertyName, "throwOnSet")) {
265         throwException(context, object, exception);
266     }
267     
268     return false;
269 }
270
271 static bool MyObject_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
272 {
273     UNUSED_PARAM(context);
274     UNUSED_PARAM(object);
275     
276     if (JSStringIsEqualToUTF8CString(propertyName, "cantDelete"))
277         return true;
278     
279     if (JSStringIsEqualToUTF8CString(propertyName, "throwOnDelete")) {
280         throwException(context, object, exception);
281         return false;
282     }
283
284     return false;
285 }
286
287 static void MyObject_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
288 {
289     UNUSED_PARAM(context);
290     UNUSED_PARAM(object);
291     
292     JSStringRef propertyName;
293     
294     propertyName = JSStringCreateWithUTF8CString("alwaysOne");
295     JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
296     JSStringRelease(propertyName);
297     
298     propertyName = JSStringCreateWithUTF8CString("myPropertyName");
299     JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
300     JSStringRelease(propertyName);
301 }
302
303 static bool isValueEqualToString(JSContextRef context, JSValueRef value, const char* string)
304 {
305     if (!JSValueIsString(context, value))
306         return false;
307     JSStringRef valueString = JSValueToStringCopy(context, value, NULL);
308     if (!valueString)
309         return false;
310     bool isEqual = JSStringIsEqualToUTF8CString(valueString, string);
311     JSStringRelease(valueString);
312     return isEqual;
313 }
314
315 static JSValueRef MyObject_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
316 {
317     UNUSED_PARAM(context);
318     UNUSED_PARAM(object);
319     UNUSED_PARAM(thisObject);
320     UNUSED_PARAM(exception);
321
322     if (argumentCount > 0 && isValueEqualToString(context, arguments[0], "throwOnCall")) {
323         throwException(context, object, exception);
324         return JSValueMakeUndefined(context);
325     }
326
327     if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
328         return JSValueMakeNumber(context, 1);
329     
330     return JSValueMakeUndefined(context);
331 }
332
333 static JSObjectRef MyObject_callAsConstructor(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
334 {
335     UNUSED_PARAM(context);
336     UNUSED_PARAM(object);
337
338     if (argumentCount > 0 && isValueEqualToString(context, arguments[0], "throwOnConstruct")) {
339         throwException(context, object, exception);
340         return object;
341     }
342
343     if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
344         return JSValueToObject(context, JSValueMakeNumber(context, 1), exception);
345     
346     return JSValueToObject(context, JSValueMakeNumber(context, 0), exception);
347 }
348
349 static bool MyObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
350 {
351     UNUSED_PARAM(context);
352     UNUSED_PARAM(constructor);
353
354     if (isValueEqualToString(context, possibleValue, "throwOnHasInstance")) {
355         throwException(context, constructor, exception);
356         return false;
357     }
358
359     JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
360     JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString, exception), exception);
361     JSStringRelease(numberString);
362
363     return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor, exception);
364 }
365
366 static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
367 {
368     UNUSED_PARAM(object);
369     UNUSED_PARAM(exception);
370     
371     switch (type) {
372     case kJSTypeNumber:
373         return JSValueMakeNumber(context, 1);
374     case kJSTypeString:
375         {
376             JSStringRef string = JSStringCreateWithUTF8CString("MyObjectAsString");
377             JSValueRef result = JSValueMakeString(context, string);
378             JSStringRelease(string);
379             return result;
380         }
381     default:
382         break;
383     }
384
385     // string conversion -- forward to default object class
386     return JSValueMakeNull(context);
387 }
388
389 static JSValueRef MyObject_convertToTypeWrapper(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
390 {
391     UNUSED_PARAM(context);
392     UNUSED_PARAM(object);
393     UNUSED_PARAM(type);
394     UNUSED_PARAM(exception);
395     // Forward to default object class
396     return 0;
397 }
398
399 static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
400 {
401     UNUSED_PARAM(ctx);
402     UNUSED_PARAM(object);
403     UNUSED_PARAM(propertyName);
404     UNUSED_PARAM(value);
405     UNUSED_PARAM(exception);
406     return false; // Forward to parent class.
407 }
408
409 static JSStaticValue evilStaticValues[] = {
410     { "nullGetSet", 0, 0, kJSPropertyAttributeNone },
411     { "nullGetForwardSet", 0, MyObject_set_nullGetForwardSet, kJSPropertyAttributeNone },
412     { 0, 0, 0, 0 }
413 };
414
415 static JSStaticFunction evilStaticFunctions[] = {
416     { "nullCall", 0, kJSPropertyAttributeNone },
417     { 0, 0, 0 }
418 };
419
420 JSClassDefinition MyObject_definition = {
421     0,
422     kJSClassAttributeNone,
423     
424     "MyObject",
425     NULL,
426     
427     evilStaticValues,
428     evilStaticFunctions,
429     
430     NULL,
431     NULL,
432     MyObject_hasProperty,
433     MyObject_getProperty,
434     MyObject_setProperty,
435     MyObject_deleteProperty,
436     MyObject_getPropertyNames,
437     MyObject_callAsFunction,
438     MyObject_callAsConstructor,
439     MyObject_hasInstance,
440     MyObject_convertToType,
441 };
442
443 JSClassDefinition MyObject_convertToTypeWrapperDefinition = {
444     0,
445     kJSClassAttributeNone,
446     
447     "MyObject",
448     NULL,
449     
450     NULL,
451     NULL,
452     
453     NULL,
454     NULL,
455     NULL,
456     NULL,
457     NULL,
458     NULL,
459     NULL,
460     NULL,
461     NULL,
462     NULL,
463     MyObject_convertToTypeWrapper,
464 };
465
466 JSClassDefinition MyObject_nullWrapperDefinition = {
467     0,
468     kJSClassAttributeNone,
469     
470     "MyObject",
471     NULL,
472     
473     NULL,
474     NULL,
475     
476     NULL,
477     NULL,
478     NULL,
479     NULL,
480     NULL,
481     NULL,
482     NULL,
483     NULL,
484     NULL,
485     NULL,
486     NULL,
487 };
488
489 static JSClassRef MyObject_class(JSContextRef context)
490 {
491     UNUSED_PARAM(context);
492
493     static JSClassRef jsClass;
494     if (!jsClass) {
495         JSClassRef baseClass = JSClassCreate(&MyObject_definition);
496         MyObject_convertToTypeWrapperDefinition.parentClass = baseClass;
497         JSClassRef wrapperClass = JSClassCreate(&MyObject_convertToTypeWrapperDefinition);
498         MyObject_nullWrapperDefinition.parentClass = wrapperClass;
499         jsClass = JSClassCreate(&MyObject_nullWrapperDefinition);
500     }
501
502     return jsClass;
503 }
504
505 static JSValueRef PropertyCatchalls_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
506 {
507     UNUSED_PARAM(context);
508     UNUSED_PARAM(object);
509     UNUSED_PARAM(propertyName);
510     UNUSED_PARAM(exception);
511
512     if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
513         static size_t count;
514         if (count++ < 5)
515             return NULL;
516
517         // Swallow all .x gets after 5, returning null.
518         return JSValueMakeNull(context);
519     }
520
521     if (JSStringIsEqualToUTF8CString(propertyName, "y")) {
522         static size_t count;
523         if (count++ < 5)
524             return NULL;
525
526         // Swallow all .y gets after 5, returning null.
527         return JSValueMakeNull(context);
528     }
529     
530     if (JSStringIsEqualToUTF8CString(propertyName, "z")) {
531         static size_t count;
532         if (count++ < 5)
533             return NULL;
534
535         // Swallow all .y gets after 5, returning null.
536         return JSValueMakeNull(context);
537     }
538
539     return NULL;
540 }
541
542 static bool PropertyCatchalls_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
543 {
544     UNUSED_PARAM(context);
545     UNUSED_PARAM(object);
546     UNUSED_PARAM(propertyName);
547     UNUSED_PARAM(value);
548     UNUSED_PARAM(exception);
549
550     if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
551         static size_t count;
552         if (count++ < 5)
553             return false;
554
555         // Swallow all .x sets after 4.
556         return true;
557     }
558
559     if (JSStringIsEqualToUTF8CString(propertyName, "make_throw") || JSStringIsEqualToUTF8CString(propertyName, "0")) {
560         *exception = JSValueMakeNumber(context, 5);
561         return true;
562     }
563
564     return false;
565 }
566
567 static void PropertyCatchalls_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
568 {
569     UNUSED_PARAM(context);
570     UNUSED_PARAM(object);
571
572     static size_t count;
573     static const char* numbers[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
574     
575     // Provide a property of a different name every time.
576     JSStringRef propertyName = JSStringCreateWithUTF8CString(numbers[count++ % 10]);
577     JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
578     JSStringRelease(propertyName);
579 }
580
581 JSClassDefinition PropertyCatchalls_definition = {
582     0,
583     kJSClassAttributeNone,
584     
585     "PropertyCatchalls",
586     NULL,
587     
588     NULL,
589     NULL,
590     
591     NULL,
592     NULL,
593     NULL,
594     PropertyCatchalls_getProperty,
595     PropertyCatchalls_setProperty,
596     NULL,
597     PropertyCatchalls_getPropertyNames,
598     NULL,
599     NULL,
600     NULL,
601     NULL,
602 };
603
604 static JSClassRef PropertyCatchalls_class(JSContextRef context)
605 {
606     UNUSED_PARAM(context);
607
608     static JSClassRef jsClass;
609     if (!jsClass)
610         jsClass = JSClassCreate(&PropertyCatchalls_definition);
611     
612     return jsClass;
613 }
614
615 static bool EvilExceptionObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
616 {
617     UNUSED_PARAM(context);
618     UNUSED_PARAM(constructor);
619     
620     JSStringRef hasInstanceName = JSStringCreateWithUTF8CString("hasInstance");
621     JSValueRef hasInstance = JSObjectGetProperty(context, constructor, hasInstanceName, exception);
622     JSStringRelease(hasInstanceName);
623     if (!hasInstance)
624         return false;
625     JSObjectRef function = JSValueToObject(context, hasInstance, exception);
626     JSValueRef result = JSObjectCallAsFunction(context, function, constructor, 1, &possibleValue, exception);
627     return result && JSValueToBoolean(context, result);
628 }
629
630 static JSValueRef EvilExceptionObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
631 {
632     UNUSED_PARAM(object);
633     UNUSED_PARAM(exception);
634     JSStringRef funcName;
635     switch (type) {
636     case kJSTypeNumber:
637         funcName = JSStringCreateWithUTF8CString("toNumber");
638         break;
639     case kJSTypeString:
640         funcName = JSStringCreateWithUTF8CString("toStringExplicit");
641         break;
642     default:
643         return JSValueMakeNull(context);
644     }
645     
646     JSValueRef func = JSObjectGetProperty(context, object, funcName, exception);
647     JSStringRelease(funcName);    
648     JSObjectRef function = JSValueToObject(context, func, exception);
649     if (!function)
650         return JSValueMakeNull(context);
651     JSValueRef value = JSObjectCallAsFunction(context, function, object, 0, NULL, exception);
652     if (!value) {
653         JSStringRef errorString = JSStringCreateWithUTF8CString("convertToType failed"); 
654         JSValueRef errorStringRef = JSValueMakeString(context, errorString);
655         JSStringRelease(errorString);
656         return errorStringRef;
657     }
658     return value;
659 }
660
661 JSClassDefinition EvilExceptionObject_definition = {
662     0,
663     kJSClassAttributeNone,
664
665     "EvilExceptionObject",
666     NULL,
667
668     NULL,
669     NULL,
670
671     NULL,
672     NULL,
673     NULL,
674     NULL,
675     NULL,
676     NULL,
677     NULL,
678     NULL,
679     NULL,
680     EvilExceptionObject_hasInstance,
681     EvilExceptionObject_convertToType,
682 };
683
684 static JSClassRef EvilExceptionObject_class(JSContextRef context)
685 {
686     UNUSED_PARAM(context);
687     
688     static JSClassRef jsClass;
689     if (!jsClass)
690         jsClass = JSClassCreate(&EvilExceptionObject_definition);
691     
692     return jsClass;
693 }
694
695 JSClassDefinition EmptyObject_definition = {
696     0,
697     kJSClassAttributeNone,
698     
699     NULL,
700     NULL,
701     
702     NULL,
703     NULL,
704     
705     NULL,
706     NULL,
707     NULL,
708     NULL,
709     NULL,
710     NULL,
711     NULL,
712     NULL,
713     NULL,
714     NULL,
715     NULL,
716 };
717
718 static JSClassRef EmptyObject_class(JSContextRef context)
719 {
720     UNUSED_PARAM(context);
721     
722     static JSClassRef jsClass;
723     if (!jsClass)
724         jsClass = JSClassCreate(&EmptyObject_definition);
725     
726     return jsClass;
727 }
728
729
730 static JSValueRef Base_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
731 {
732     UNUSED_PARAM(object);
733     UNUSED_PARAM(propertyName);
734     UNUSED_PARAM(exception);
735
736     return JSValueMakeNumber(ctx, 1); // distinguish base get form derived get
737 }
738
739 static bool Base_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
740 {
741     UNUSED_PARAM(object);
742     UNUSED_PARAM(propertyName);
743     UNUSED_PARAM(value);
744
745     *exception = JSValueMakeNumber(ctx, 1); // distinguish base set from derived set
746     return true;
747 }
748
749 static JSValueRef Base_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
750 {
751     UNUSED_PARAM(function);
752     UNUSED_PARAM(thisObject);
753     UNUSED_PARAM(argumentCount);
754     UNUSED_PARAM(arguments);
755     UNUSED_PARAM(exception);
756     
757     return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call
758 }
759
760 static JSValueRef Base_returnHardNull(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
761 {
762     UNUSED_PARAM(ctx);
763     UNUSED_PARAM(function);
764     UNUSED_PARAM(thisObject);
765     UNUSED_PARAM(argumentCount);
766     UNUSED_PARAM(arguments);
767     UNUSED_PARAM(exception);
768     
769     return 0; // should convert to undefined!
770 }
771
772 static JSStaticFunction Base_staticFunctions[] = {
773     { "baseProtoDup", NULL, kJSPropertyAttributeNone },
774     { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone },
775     { "baseHardNull", Base_returnHardNull, kJSPropertyAttributeNone },
776     { 0, 0, 0 }
777 };
778
779 static JSStaticValue Base_staticValues[] = {
780     { "baseDup", Base_get, Base_set, kJSPropertyAttributeNone },
781     { "baseOnly", Base_get, Base_set, kJSPropertyAttributeNone },
782     { 0, 0, 0, 0 }
783 };
784
785 static bool TestInitializeFinalize;
786 static void Base_initialize(JSContextRef context, JSObjectRef object)
787 {
788     UNUSED_PARAM(context);
789
790     if (TestInitializeFinalize) {
791         ASSERT((void*)1 == JSObjectGetPrivate(object));
792         JSObjectSetPrivate(object, (void*)2);
793     }
794 }
795
796 static unsigned Base_didFinalize;
797 static void Base_finalize(JSObjectRef object)
798 {
799     UNUSED_PARAM(object);
800     if (TestInitializeFinalize) {
801         ASSERT((void*)4 == JSObjectGetPrivate(object));
802         Base_didFinalize = true;
803     }
804 }
805
806 static JSClassRef Base_class(JSContextRef context)
807 {
808     UNUSED_PARAM(context);
809
810     static JSClassRef jsClass;
811     if (!jsClass) {
812         JSClassDefinition definition = kJSClassDefinitionEmpty;
813         definition.staticValues = Base_staticValues;
814         definition.staticFunctions = Base_staticFunctions;
815         definition.initialize = Base_initialize;
816         definition.finalize = Base_finalize;
817         jsClass = JSClassCreate(&definition);
818     }
819     return jsClass;
820 }
821
822 static JSValueRef Derived_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
823 {
824     UNUSED_PARAM(object);
825     UNUSED_PARAM(propertyName);
826     UNUSED_PARAM(exception);
827
828     return JSValueMakeNumber(ctx, 2); // distinguish base get form derived get
829 }
830
831 static bool Derived_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
832 {
833     UNUSED_PARAM(ctx);
834     UNUSED_PARAM(object);
835     UNUSED_PARAM(propertyName);
836     UNUSED_PARAM(value);
837
838     *exception = JSValueMakeNumber(ctx, 2); // distinguish base set from derived set
839     return true;
840 }
841
842 static JSValueRef Derived_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
843 {
844     UNUSED_PARAM(function);
845     UNUSED_PARAM(thisObject);
846     UNUSED_PARAM(argumentCount);
847     UNUSED_PARAM(arguments);
848     UNUSED_PARAM(exception);
849     
850     return JSValueMakeNumber(ctx, 2); // distinguish base call from derived call
851 }
852
853 static JSStaticFunction Derived_staticFunctions[] = {
854     { "protoOnly", Derived_callAsFunction, kJSPropertyAttributeNone },
855     { "protoDup", NULL, kJSPropertyAttributeNone },
856     { "baseProtoDup", Derived_callAsFunction, kJSPropertyAttributeNone },
857     { 0, 0, 0 }
858 };
859
860 static JSStaticValue Derived_staticValues[] = {
861     { "derivedOnly", Derived_get, Derived_set, kJSPropertyAttributeNone },
862     { "protoDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
863     { "baseDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
864     { 0, 0, 0, 0 }
865 };
866
867 static void Derived_initialize(JSContextRef context, JSObjectRef object)
868 {
869     UNUSED_PARAM(context);
870
871     if (TestInitializeFinalize) {
872         ASSERT((void*)2 == JSObjectGetPrivate(object));
873         JSObjectSetPrivate(object, (void*)3);
874     }
875 }
876
877 static void Derived_finalize(JSObjectRef object)
878 {
879     if (TestInitializeFinalize) {
880         ASSERT((void*)3 == JSObjectGetPrivate(object));
881         JSObjectSetPrivate(object, (void*)4);
882     }
883 }
884
885 static JSClassRef Derived_class(JSContextRef context)
886 {
887     static JSClassRef jsClass;
888     if (!jsClass) {
889         JSClassDefinition definition = kJSClassDefinitionEmpty;
890         definition.parentClass = Base_class(context);
891         definition.staticValues = Derived_staticValues;
892         definition.staticFunctions = Derived_staticFunctions;
893         definition.initialize = Derived_initialize;
894         definition.finalize = Derived_finalize;
895         jsClass = JSClassCreate(&definition);
896     }
897     return jsClass;
898 }
899
900 static JSClassRef Derived2_class(JSContextRef context)
901 {
902     static JSClassRef jsClass;
903     if (!jsClass) {
904         JSClassDefinition definition = kJSClassDefinitionEmpty;
905         definition.parentClass = Derived_class(context);
906         jsClass = JSClassCreate(&definition);
907     }
908     return jsClass;
909 }
910
911 static JSValueRef print_callAsFunction(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
912 {
913     UNUSED_PARAM(functionObject);
914     UNUSED_PARAM(thisObject);
915     UNUSED_PARAM(exception);
916
917     ASSERT(JSContextGetGlobalContext(ctx) == context);
918     
919     if (argumentCount > 0) {
920         JSStringRef string = JSValueToStringCopy(ctx, arguments[0], NULL);
921         size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
922         char* stringUTF8 = (char*)malloc(sizeUTF8);
923         JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
924         printf("%s\n", stringUTF8);
925         free(stringUTF8);
926         JSStringRelease(string);
927     }
928     
929     return JSValueMakeUndefined(ctx);
930 }
931
932 static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
933 {
934     UNUSED_PARAM(constructorObject);
935     UNUSED_PARAM(exception);
936     
937     JSObjectRef result = JSObjectMake(context, NULL, NULL);
938     if (argumentCount > 0) {
939         JSStringRef value = JSStringCreateWithUTF8CString("value");
940         JSObjectSetProperty(context, result, value, arguments[0], kJSPropertyAttributeNone, NULL);
941         JSStringRelease(value);
942     }
943     
944     return result;
945 }
946
947 static JSObjectRef myBadConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
948 {
949     UNUSED_PARAM(context);
950     UNUSED_PARAM(constructorObject);
951     UNUSED_PARAM(argumentCount);
952     UNUSED_PARAM(arguments);
953     UNUSED_PARAM(exception);
954     
955     return 0;
956 }
957
958
959 static void globalObject_initialize(JSContextRef context, JSObjectRef object)
960 {
961     UNUSED_PARAM(object);
962     // Ensure that an execution context is passed in
963     ASSERT(context);
964
965     JSObjectRef globalObject = JSContextGetGlobalObject(context);
966     ASSERT(globalObject);
967
968     // Ensure that the standard global properties have been set on the global object
969     JSStringRef array = JSStringCreateWithUTF8CString("Array");
970     JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
971     JSStringRelease(array);
972
973     UNUSED_PARAM(arrayConstructor);
974     ASSERT(arrayConstructor);
975 }
976
977 static JSValueRef globalObject_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
978 {
979     UNUSED_PARAM(object);
980     UNUSED_PARAM(propertyName);
981     UNUSED_PARAM(exception);
982
983     return JSValueMakeNumber(ctx, 3);
984 }
985
986 static bool globalObject_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
987 {
988     UNUSED_PARAM(object);
989     UNUSED_PARAM(propertyName);
990     UNUSED_PARAM(value);
991
992     *exception = JSValueMakeNumber(ctx, 3);
993     return true;
994 }
995
996 static JSValueRef globalObject_call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
997 {
998     UNUSED_PARAM(function);
999     UNUSED_PARAM(thisObject);
1000     UNUSED_PARAM(argumentCount);
1001     UNUSED_PARAM(arguments);
1002     UNUSED_PARAM(exception);
1003
1004     return JSValueMakeNumber(ctx, 3);
1005 }
1006
1007 static JSValueRef functionGC(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1008 {
1009     UNUSED_PARAM(function);
1010     UNUSED_PARAM(thisObject);
1011     UNUSED_PARAM(argumentCount);
1012     UNUSED_PARAM(arguments);
1013     UNUSED_PARAM(exception);
1014     JSGarbageCollect(context);
1015     return JSValueMakeUndefined(context);
1016 }
1017
1018 static JSStaticValue globalObject_staticValues[] = {
1019     { "globalStaticValue", globalObject_get, globalObject_set, kJSPropertyAttributeNone },
1020     { 0, 0, 0, 0 }
1021 };
1022
1023 static JSStaticFunction globalObject_staticFunctions[] = {
1024     { "globalStaticFunction", globalObject_call, kJSPropertyAttributeNone },
1025     { "globalStaticFunction2", globalObject_call, kJSPropertyAttributeNone },
1026     { "gc", functionGC, kJSPropertyAttributeNone },
1027     { 0, 0, 0 }
1028 };
1029
1030 static char* createStringWithContentsOfFile(const char* fileName);
1031
1032 static void testInitializeFinalize()
1033 {
1034     JSObjectRef o = JSObjectMake(context, Derived_class(context), (void*)1);
1035     UNUSED_PARAM(o);
1036     ASSERT(JSObjectGetPrivate(o) == (void*)3);
1037 }
1038
1039 static JSValueRef jsNumberValue =  NULL;
1040
1041 static JSObjectRef aHeapRef = NULL;
1042
1043 static void makeGlobalNumberValue(JSContextRef context) {
1044     JSValueRef v = JSValueMakeNumber(context, 420);
1045     JSValueProtect(context, v);
1046     jsNumberValue = v;
1047     v = NULL;
1048 }
1049
1050 bool assertTrue(bool value, const char* message)
1051 {
1052     if (!value) {
1053         if (message)
1054             fprintf(stderr, "assertTrue failed: '%s'\n", message);
1055         else
1056             fprintf(stderr, "assertTrue failed.\n");
1057         failed = 1;
1058     }
1059     return value;
1060 }
1061
1062 static bool checkForCycleInPrototypeChain()
1063 {
1064     bool result = true;
1065     JSGlobalContextRef context = JSGlobalContextCreate(0);
1066     JSObjectRef object1 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
1067     JSObjectRef object2 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
1068     JSObjectRef object3 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
1069
1070     JSObjectSetPrototype(context, object1, JSValueMakeNull(context));
1071     ASSERT(JSValueIsNull(context, JSObjectGetPrototype(context, object1)));
1072
1073     // object1 -> object1
1074     JSObjectSetPrototype(context, object1, object1);
1075     result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to assign self as a prototype");
1076
1077     // object1 -> object2 -> object1
1078     JSObjectSetPrototype(context, object2, object1);
1079     ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object1));
1080     JSObjectSetPrototype(context, object1, object2);
1081     result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to close a prototype chain cycle");
1082
1083     // object1 -> object2 -> object3 -> object1
1084     JSObjectSetPrototype(context, object2, object3);
1085     ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object3));
1086     JSObjectSetPrototype(context, object1, object2);
1087     ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object1), object2));
1088     JSObjectSetPrototype(context, object3, object1);
1089     result &= assertTrue(!JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object3), object1), "It is possible to close a prototype chain cycle");
1090
1091     JSValueRef exception;
1092     JSStringRef code = JSStringCreateWithUTF8CString("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
1093     JSStringRef file = JSStringCreateWithUTF8CString("");
1094     result &= assertTrue(!JSEvaluateScript(context, code, /* thisObject*/ 0, file, 1, &exception)
1095                          , "An exception should be thrown");
1096
1097     JSStringRelease(code);
1098     JSStringRelease(file);
1099     JSGlobalContextRelease(context);
1100     return result;
1101 }
1102
1103 static JSValueRef valueToObjectExceptionCallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1104 {
1105     UNUSED_PARAM(function);
1106     UNUSED_PARAM(thisObject);
1107     UNUSED_PARAM(argumentCount);
1108     UNUSED_PARAM(arguments);
1109     JSValueRef jsUndefined = JSValueMakeUndefined(JSContextGetGlobalContext(ctx));
1110     JSValueToObject(JSContextGetGlobalContext(ctx), jsUndefined, exception);
1111     
1112     return JSValueMakeUndefined(ctx);
1113 }
1114 static bool valueToObjectExceptionTest()
1115 {
1116     JSGlobalContextRef testContext;
1117     JSClassDefinition globalObjectClassDefinition = kJSClassDefinitionEmpty;
1118     globalObjectClassDefinition.initialize = globalObject_initialize;
1119     globalObjectClassDefinition.staticValues = globalObject_staticValues;
1120     globalObjectClassDefinition.staticFunctions = globalObject_staticFunctions;
1121     globalObjectClassDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
1122     JSClassRef globalObjectClass = JSClassCreate(&globalObjectClassDefinition);
1123     testContext = JSGlobalContextCreateInGroup(NULL, globalObjectClass);
1124     JSObjectRef globalObject = JSContextGetGlobalObject(testContext);
1125
1126     JSStringRef valueToObject = JSStringCreateWithUTF8CString("valueToObject");
1127     JSObjectRef valueToObjectFunction = JSObjectMakeFunctionWithCallback(testContext, valueToObject, valueToObjectExceptionCallAsFunction);
1128     JSObjectSetProperty(testContext, globalObject, valueToObject, valueToObjectFunction, kJSPropertyAttributeNone, NULL);
1129     JSStringRelease(valueToObject);
1130
1131     JSStringRef test = JSStringCreateWithUTF8CString("valueToObject();");
1132     JSEvaluateScript(testContext, test, NULL, NULL, 1, NULL);
1133     
1134     JSStringRelease(test);
1135     JSClassRelease(globalObjectClass);
1136     JSGlobalContextRelease(testContext);
1137     
1138     return true;
1139 }
1140
1141 static bool globalContextNameTest()
1142 {
1143     bool result = true;
1144     JSGlobalContextRef context = JSGlobalContextCreate(0);
1145
1146     JSStringRef str = JSGlobalContextCopyName(context);
1147     result &= assertTrue(!str, "Default context name is NULL");
1148
1149     JSStringRef name1 = JSStringCreateWithUTF8CString("name1");
1150     JSStringRef name2 = JSStringCreateWithUTF8CString("name2");
1151
1152     JSGlobalContextSetName(context, name1);
1153     JSStringRef fetchName1 = JSGlobalContextCopyName(context);
1154     JSGlobalContextSetName(context, name2);
1155     JSStringRef fetchName2 = JSGlobalContextCopyName(context);
1156     JSGlobalContextSetName(context, NULL);
1157     JSStringRef fetchName3 = JSGlobalContextCopyName(context);
1158
1159     result &= assertTrue(JSStringIsEqual(name1, fetchName1), "Unexpected Context name");
1160     result &= assertTrue(JSStringIsEqual(name2, fetchName2), "Unexpected Context name");
1161     result &= assertTrue(!JSStringIsEqual(fetchName1, fetchName2), "Unexpected Context name");
1162     result &= assertTrue(!fetchName3, "Unexpected Context name");
1163
1164     JSStringRelease(name1);
1165     JSStringRelease(name2);
1166     JSStringRelease(fetchName1);
1167     JSStringRelease(fetchName2);
1168
1169     JSGlobalContextRelease(context);
1170
1171     return result;
1172 }
1173
1174 IGNORE_GCC_WARNINGS_BEGIN("unused-but-set-variable")
1175 static void checkConstnessInJSObjectNames()
1176 {
1177     JSStaticFunction fun;
1178     fun.name = "something";
1179     JSStaticValue val;
1180     val.name = "something";
1181 }
1182 IGNORE_GCC_WARNINGS_END
1183
1184 #ifdef __cplusplus
1185 extern "C" {
1186 #endif
1187 void JSSynchronousGarbageCollectForDebugging(JSContextRef);
1188 #ifdef __cplusplus
1189 }
1190 #endif
1191
1192 static const unsigned numWeakRefs = 10000;
1193
1194 static void markingConstraint(JSMarkerRef marker, void *userData)
1195 {
1196     JSWeakRef *weakRefs;
1197     unsigned i;
1198     
1199     weakRefs = (JSWeakRef*)userData;
1200     
1201     for (i = 0; i < numWeakRefs; i += 2) {
1202         JSWeakRef weakRef = weakRefs[i];
1203         if (weakRef) {
1204             JSObjectRef object = JSWeakGetObject(weakRefs[i]);
1205             marker->Mark(marker, object);
1206             assertTrue(marker->IsMarked(marker, object), "A marked object is marked");
1207         }
1208     }
1209 }
1210
1211 static bool didRunHeapFinalizer;
1212 static JSContextGroupRef expectedContextGroup;
1213
1214 static void heapFinalizer(JSContextGroupRef group, void *userData)
1215 {
1216     assertTrue((uintptr_t)userData == (uintptr_t)42, "Correct userData was passed");
1217     assertTrue(group == expectedContextGroup, "Correct context group");
1218     
1219     didRunHeapFinalizer = true;
1220 }
1221
1222 static void testMarkingConstraintsAndHeapFinalizers(void)
1223 {
1224     JSContextGroupRef group;
1225     JSWeakRef *weakRefs;
1226     unsigned i;
1227     unsigned deadCount;
1228     
1229     printf("Testing Marking Constraints.\n");
1230     
1231     group = JSContextGroupCreate();
1232     expectedContextGroup = group;
1233     
1234     JSGlobalContextRef context = JSGlobalContextCreateInGroup(group, NULL);
1235
1236     weakRefs = (JSWeakRef*)calloc(numWeakRefs, sizeof(JSWeakRef));
1237
1238     JSContextGroupAddMarkingConstraint(group, markingConstraint, (void*)weakRefs);
1239     JSContextGroupAddHeapFinalizer(group, heapFinalizer, (void*)(uintptr_t)42);
1240     
1241     for (i = numWeakRefs; i--;)
1242         weakRefs[i] = JSWeakCreate(group, JSObjectMakeArray(context, 0, NULL, NULL));
1243     
1244     JSSynchronousGarbageCollectForDebugging(context);
1245     assertTrue(didRunHeapFinalizer, "Did run heap finalizer");
1246     
1247     deadCount = 0;
1248     for (i = 0; i < numWeakRefs; i += 2) {
1249         assertTrue((bool)JSWeakGetObject(weakRefs[i]), "Marked objects stayed alive");
1250         if (!JSWeakGetObject(weakRefs[i + 1]))
1251             deadCount++;
1252     }
1253     
1254     assertTrue(deadCount != 0, "At least some objects died");
1255     
1256     for (i = numWeakRefs; i--;) {
1257         JSWeakRef weakRef = weakRefs[i];
1258         weakRefs[i] = NULL;
1259         JSWeakRelease(group, weakRef);
1260     }
1261     
1262     didRunHeapFinalizer = false;
1263     JSSynchronousGarbageCollectForDebugging(context);
1264     assertTrue(didRunHeapFinalizer, "Did run heap finalizer");
1265
1266     JSContextGroupRemoveHeapFinalizer(group, heapFinalizer, (void*)(uintptr_t)42);
1267
1268     didRunHeapFinalizer = false;
1269     JSSynchronousGarbageCollectForDebugging(context);
1270     assertTrue(!didRunHeapFinalizer, "Did not run heap finalizer");
1271
1272     JSGlobalContextRelease(context);
1273     JSContextGroupRelease(group);
1274
1275     printf("PASS: Marking Constraints and Heap Finalizers.\n");
1276 }
1277
1278 #if USE(CF)
1279 static void testCFStrings(void)
1280 {
1281     /* The assertion utility functions we use below expects to get the JSGlobalContextRef
1282        from the global context variable. */
1283     JSGlobalContextRef oldContext = context;
1284     context = JSGlobalContextCreate(0);
1285
1286     UniChar singleUniChar = 65; // Capital A
1287     CFMutableStringRef cfString = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault, &singleUniChar, 1, 1, kCFAllocatorNull);
1288
1289     JSStringRef jsCFIString = JSStringCreateWithCFString(cfString);
1290     JSValueRef jsCFString = JSValueMakeString(context, jsCFIString);
1291
1292     CFStringRef cfEmptyString = CFStringCreateWithCString(kCFAllocatorDefault, "", kCFStringEncodingUTF8);
1293
1294     JSStringRef jsCFEmptyIString = JSStringCreateWithCFString(cfEmptyString);
1295     JSValueRef jsCFEmptyString = JSValueMakeString(context, jsCFEmptyIString);
1296
1297     CFIndex cfStringLength = CFStringGetLength(cfString);
1298     UniChar* buffer = (UniChar*)malloc(cfStringLength * sizeof(UniChar));
1299     CFStringGetCharacters(cfString, CFRangeMake(0, cfStringLength), buffer);
1300     JSStringRef jsCFIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, cfStringLength);
1301     JSValueRef jsCFStringWithCharacters = JSValueMakeString(context, jsCFIStringWithCharacters);
1302
1303     JSStringRef jsCFEmptyIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, CFStringGetLength(cfEmptyString));
1304     free(buffer);
1305     JSValueRef jsCFEmptyStringWithCharacters = JSValueMakeString(context, jsCFEmptyIStringWithCharacters);
1306
1307     ASSERT(JSValueGetType(context, jsCFString) == kJSTypeString);
1308     ASSERT(JSValueGetType(context, jsCFStringWithCharacters) == kJSTypeString);
1309     ASSERT(JSValueGetType(context, jsCFEmptyString) == kJSTypeString);
1310     ASSERT(JSValueGetType(context, jsCFEmptyStringWithCharacters) == kJSTypeString);
1311
1312     JSStringRef emptyString = JSStringCreateWithCFString(CFSTR(""));
1313     const JSChar* characters = JSStringGetCharactersPtr(emptyString);
1314     if (!characters) {
1315         printf("FAIL: Returned null when accessing character pointer of an empty String.\n");
1316         failed = 1;
1317     } else
1318         printf("PASS: returned empty when accessing character pointer of an empty String.\n");
1319
1320     size_t length = JSStringGetLength(emptyString);
1321     if (length) {
1322         printf("FAIL: Didn't return 0 length for empty String.\n");
1323         failed = 1;
1324     } else
1325         printf("PASS: returned 0 length for empty String.\n");
1326     JSStringRelease(emptyString);
1327
1328     assertEqualsAsBoolean(jsCFString, true);
1329     assertEqualsAsBoolean(jsCFStringWithCharacters, true);
1330     assertEqualsAsBoolean(jsCFEmptyString, false);
1331     assertEqualsAsBoolean(jsCFEmptyStringWithCharacters, false);
1332
1333     assertEqualsAsNumber(jsCFString, nan(""));
1334     assertEqualsAsNumber(jsCFStringWithCharacters, nan(""));
1335     assertEqualsAsNumber(jsCFEmptyString, 0);
1336     assertEqualsAsNumber(jsCFEmptyStringWithCharacters, 0);
1337     ASSERT(sizeof(JSChar) == sizeof(UniChar));
1338
1339     assertEqualsAsCharactersPtr(jsCFString, "A");
1340     assertEqualsAsCharactersPtr(jsCFStringWithCharacters, "A");
1341     assertEqualsAsCharactersPtr(jsCFEmptyString, "");
1342     assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters, "");
1343
1344     assertEqualsAsUTF8String(jsCFString, "A");
1345     assertEqualsAsUTF8String(jsCFStringWithCharacters, "A");
1346     assertEqualsAsUTF8String(jsCFEmptyString, "");
1347     assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
1348
1349     CFStringRef cfJSString = JSStringCopyCFString(kCFAllocatorDefault, jsCFIString);
1350     CFStringRef cfJSEmptyString = JSStringCopyCFString(kCFAllocatorDefault, jsCFEmptyIString);
1351     ASSERT(CFEqual(cfJSString, cfString));
1352     ASSERT(CFEqual(cfJSEmptyString, cfEmptyString));
1353     CFRelease(cfJSString);
1354     CFRelease(cfJSEmptyString);
1355
1356     JSObjectRef o = JSObjectMake(context, NULL, NULL);
1357     JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
1358     JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeNone, NULL);
1359     JSObjectSetProperty(context, o, jsCFIString,  JSValueMakeNumber(context, 1), kJSPropertyAttributeDontEnum, NULL);
1360     JSPropertyNameArrayRef nameArray = JSObjectCopyPropertyNames(context, o);
1361     size_t expectedCount = JSPropertyNameArrayGetCount(nameArray);
1362     size_t count;
1363     for (count = 0; count < expectedCount; ++count)
1364         JSPropertyNameArrayGetNameAtIndex(nameArray, count);
1365     JSPropertyNameArrayRelease(nameArray);
1366     ASSERT(count == 1); // jsCFString should not be enumerated
1367
1368     JSStringRelease(jsOneIString);
1369     JSStringRelease(jsCFIString);
1370     JSStringRelease(jsCFEmptyIString);
1371     JSStringRelease(jsCFIStringWithCharacters);
1372     JSStringRelease(jsCFEmptyIStringWithCharacters);
1373     CFRelease(cfString);
1374     CFRelease(cfEmptyString);
1375
1376     JSGlobalContextRelease(context);
1377     context = oldContext;
1378 }
1379 #endif
1380
1381 int main(int argc, char* argv[])
1382 {
1383 #if OS(WINDOWS)
1384     // Cygwin calls SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1385     // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1386     // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1387     SetErrorMode(0);
1388 #endif
1389
1390 #if !OS(WINDOWS)
1391     char resolvedPath[PATH_MAX];
1392     realpath(argv[0], resolvedPath); 
1393     char* newCWD = dirname(resolvedPath);
1394     if (chdir(newCWD))
1395         fprintf(stdout, "Could not chdir to: %s\n", newCWD);
1396 #endif
1397
1398     const char* filter = argc > 1 ? argv[1] : NULL;
1399 #if JSC_OBJC_API_ENABLED
1400     testObjectiveCAPI(filter);
1401 #endif
1402
1403     RELEASE_ASSERT(!testCAPIViaCpp(filter));
1404     if (filter)
1405         return 0;
1406
1407     testCompareAndSwap();
1408     startMultithreadedMultiVMExecutionTest();
1409     
1410     // Test garbage collection with a fresh context
1411     context = JSGlobalContextCreateInGroup(NULL, NULL);
1412     TestInitializeFinalize = true;
1413     testInitializeFinalize();
1414     JSGlobalContextRelease(context);
1415     TestInitializeFinalize = false;
1416
1417     ASSERT(Base_didFinalize);
1418
1419     testMarkingConstraintsAndHeapFinalizers();
1420
1421 #if USE(CF)
1422     testCFStrings();
1423 #endif
1424
1425     JSClassDefinition globalObjectClassDefinition = kJSClassDefinitionEmpty;
1426     globalObjectClassDefinition.initialize = globalObject_initialize;
1427     globalObjectClassDefinition.staticValues = globalObject_staticValues;
1428     globalObjectClassDefinition.staticFunctions = globalObject_staticFunctions;
1429     globalObjectClassDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
1430     JSClassRef globalObjectClass = JSClassCreate(&globalObjectClassDefinition);
1431     context = JSGlobalContextCreateInGroup(NULL, globalObjectClass);
1432
1433     JSContextGroupRef contextGroup = JSContextGetGroup(context);
1434     
1435     JSGlobalContextRetain(context);
1436     JSGlobalContextRelease(context);
1437     ASSERT(JSContextGetGlobalContext(context) == context);
1438     
1439     JSReportExtraMemoryCost(context, 0);
1440     JSReportExtraMemoryCost(context, 1);
1441     JSReportExtraMemoryCost(context, 1024);
1442
1443     JSObjectRef globalObject = JSContextGetGlobalObject(context);
1444     ASSERT(JSValueIsObject(context, globalObject));
1445     
1446     JSValueRef jsUndefined = JSValueMakeUndefined(context);
1447     JSValueRef jsNull = JSValueMakeNull(context);
1448     JSValueRef jsTrue = JSValueMakeBoolean(context, true);
1449     JSValueRef jsFalse = JSValueMakeBoolean(context, false);
1450     JSValueRef jsZero = JSValueMakeNumber(context, 0);
1451     JSValueRef jsOne = JSValueMakeNumber(context, 1);
1452     JSValueRef jsOneThird = JSValueMakeNumber(context, 1.0 / 3.0);
1453     JSObjectRef jsObjectNoProto = JSObjectMake(context, NULL, NULL);
1454     JSObjectSetPrototype(context, jsObjectNoProto, JSValueMakeNull(context));
1455
1456     JSObjectSetPrivate(globalObject, (void*)123);
1457     if (JSObjectGetPrivate(globalObject) != (void*)123) {
1458         printf("FAIL: Didn't return private data when set by JSObjectSetPrivate().\n");
1459         failed = 1;
1460     } else
1461         printf("PASS: returned private data when set by JSObjectSetPrivate().\n");
1462
1463     // FIXME: test funny utf8 characters
1464     JSStringRef jsEmptyIString = JSStringCreateWithUTF8CString("");
1465     JSValueRef jsEmptyString = JSValueMakeString(context, jsEmptyIString);
1466     
1467     JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
1468     JSValueRef jsOneString = JSValueMakeString(context, jsOneIString);
1469
1470     JSChar constantString[] = { 'H', 'e', 'l', 'l', 'o', };
1471     JSStringRef constantStringRef = JSStringCreateWithCharactersNoCopy(constantString, sizeof(constantString) / sizeof(constantString[0]));
1472     ASSERT(JSStringGetCharactersPtr(constantStringRef) == constantString);
1473     JSStringRelease(constantStringRef);
1474
1475     ASSERT(JSValueGetType(context, NULL) == kJSTypeNull);
1476     ASSERT(JSValueGetType(context, jsUndefined) == kJSTypeUndefined);
1477     ASSERT(JSValueGetType(context, jsNull) == kJSTypeNull);
1478     ASSERT(JSValueGetType(context, jsTrue) == kJSTypeBoolean);
1479     ASSERT(JSValueGetType(context, jsFalse) == kJSTypeBoolean);
1480     ASSERT(JSValueGetType(context, jsZero) == kJSTypeNumber);
1481     ASSERT(JSValueGetType(context, jsOne) == kJSTypeNumber);
1482     ASSERT(JSValueGetType(context, jsOneThird) == kJSTypeNumber);
1483     ASSERT(JSValueGetType(context, jsEmptyString) == kJSTypeString);
1484     ASSERT(JSValueGetType(context, jsOneString) == kJSTypeString);
1485
1486     ASSERT(!JSValueIsBoolean(context, NULL));
1487     ASSERT(!JSValueIsObject(context, NULL));
1488     ASSERT(!JSValueIsArray(context, NULL));
1489     ASSERT(!JSValueIsDate(context, NULL));
1490     ASSERT(!JSValueIsString(context, NULL));
1491     ASSERT(!JSValueIsNumber(context, NULL));
1492     ASSERT(!JSValueIsUndefined(context, NULL));
1493     ASSERT(JSValueIsNull(context, NULL));
1494     ASSERT(!JSObjectCallAsFunction(context, NULL, NULL, 0, NULL, NULL));
1495     ASSERT(!JSObjectCallAsConstructor(context, NULL, 0, NULL, NULL));
1496     ASSERT(!JSObjectIsConstructor(context, NULL));
1497     ASSERT(!JSObjectIsFunction(context, NULL));
1498
1499     JSStringRef nullString = JSStringCreateWithUTF8CString(0);
1500     const JSChar* characters = JSStringGetCharactersPtr(nullString);
1501     if (characters) {
1502         printf("FAIL: Didn't return null when accessing character pointer of a null String.\n");
1503         failed = 1;
1504     } else
1505         printf("PASS: returned null when accessing character pointer of a null String.\n");
1506
1507     size_t length = JSStringGetLength(nullString);
1508     if (length) {
1509         printf("FAIL: Didn't return 0 length for null String.\n");
1510         failed = 1;
1511     } else
1512         printf("PASS: returned 0 length for null String.\n");
1513     JSStringRelease(nullString);
1514
1515     JSObjectRef propertyCatchalls = JSObjectMake(context, PropertyCatchalls_class(context), NULL);
1516     JSStringRef propertyCatchallsString = JSStringCreateWithUTF8CString("PropertyCatchalls");
1517     JSObjectSetProperty(context, globalObject, propertyCatchallsString, propertyCatchalls, kJSPropertyAttributeNone, NULL);
1518     JSStringRelease(propertyCatchallsString);
1519
1520     JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
1521     JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
1522     JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
1523     JSStringRelease(myObjectIString);
1524     
1525     JSObjectRef EvilExceptionObject = JSObjectMake(context, EvilExceptionObject_class(context), NULL);
1526     JSStringRef EvilExceptionObjectIString = JSStringCreateWithUTF8CString("EvilExceptionObject");
1527     JSObjectSetProperty(context, globalObject, EvilExceptionObjectIString, EvilExceptionObject, kJSPropertyAttributeNone, NULL);
1528     JSStringRelease(EvilExceptionObjectIString);
1529     
1530     JSObjectRef EmptyObject = JSObjectMake(context, EmptyObject_class(context), NULL);
1531     JSStringRef EmptyObjectIString = JSStringCreateWithUTF8CString("EmptyObject");
1532     JSObjectSetProperty(context, globalObject, EmptyObjectIString, EmptyObject, kJSPropertyAttributeNone, NULL);
1533     JSStringRelease(EmptyObjectIString);
1534     
1535     JSStringRef lengthStr = JSStringCreateWithUTF8CString("length");
1536     JSObjectRef aStackRef = JSObjectMakeArray(context, 0, 0, 0);
1537     aHeapRef = aStackRef;
1538     JSObjectSetProperty(context, aHeapRef, lengthStr, JSValueMakeNumber(context, 10), 0, 0);
1539     JSStringRef privatePropertyName = JSStringCreateWithUTF8CString("privateProperty");
1540     if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, aHeapRef)) {
1541         printf("FAIL: Could not set private property.\n");
1542         failed = 1;
1543     } else
1544         printf("PASS: Set private property.\n");
1545     aStackRef = 0;
1546     if (JSObjectSetPrivateProperty(context, aHeapRef, privatePropertyName, aHeapRef)) {
1547         printf("FAIL: JSObjectSetPrivateProperty should fail on non-API objects.\n");
1548         failed = 1;
1549     } else
1550         printf("PASS: Did not allow JSObjectSetPrivateProperty on a non-API object.\n");
1551     if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName) != aHeapRef) {
1552         printf("FAIL: Could not retrieve private property.\n");
1553         failed = 1;
1554     } else
1555         printf("PASS: Retrieved private property.\n");
1556     if (JSObjectGetPrivateProperty(context, aHeapRef, privatePropertyName)) {
1557         printf("FAIL: JSObjectGetPrivateProperty should return NULL when called on a non-API object.\n");
1558         failed = 1;
1559     } else
1560         printf("PASS: JSObjectGetPrivateProperty return NULL.\n");
1561
1562     if (JSObjectGetProperty(context, myObject, privatePropertyName, 0) == aHeapRef) {
1563         printf("FAIL: Accessed private property through ordinary property lookup.\n");
1564         failed = 1;
1565     } else
1566         printf("PASS: Cannot access private property through ordinary property lookup.\n");
1567
1568     JSGarbageCollect(context);
1569
1570     int i;
1571     for (i = 0; i < 10000; i++)
1572         JSObjectMake(context, 0, 0);
1573
1574     aHeapRef = JSValueToObject(context, JSObjectGetPrivateProperty(context, myObject, privatePropertyName), 0);
1575     if (JSValueToNumber(context, JSObjectGetProperty(context, aHeapRef, lengthStr, 0), 0) != 10) {
1576         printf("FAIL: Private property has been collected.\n");
1577         failed = 1;
1578     } else
1579         printf("PASS: Private property does not appear to have been collected.\n");
1580     JSStringRelease(lengthStr);
1581
1582     if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, 0)) {
1583         printf("FAIL: Could not set private property to NULL.\n");
1584         failed = 1;
1585     } else
1586         printf("PASS: Set private property to NULL.\n");
1587     if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName)) {
1588         printf("FAIL: Could not retrieve private property.\n");
1589         failed = 1;
1590     } else
1591         printf("PASS: Retrieved private property.\n");
1592
1593     JSStringRef nullJSON = JSStringCreateWithUTF8CString(0);
1594     JSValueRef nullJSONObject = JSValueMakeFromJSONString(context, nullJSON);
1595     if (nullJSONObject) {
1596         printf("FAIL: Did not parse null String as JSON correctly\n");
1597         failed = 1;
1598     } else
1599         printf("PASS: Parsed null String as JSON correctly.\n");
1600     JSStringRelease(nullJSON);
1601
1602     JSStringRef validJSON = JSStringCreateWithUTF8CString("{\"aProperty\":true}");
1603     JSValueRef jsonObject = JSValueMakeFromJSONString(context, validJSON);
1604     JSStringRelease(validJSON);
1605     if (!JSValueIsObject(context, jsonObject)) {
1606         printf("FAIL: Did not parse valid JSON correctly\n");
1607         failed = 1;
1608     } else
1609         printf("PASS: Parsed valid JSON string.\n");
1610     JSStringRef propertyName = JSStringCreateWithUTF8CString("aProperty");
1611     assertEqualsAsBoolean(JSObjectGetProperty(context, JSValueToObject(context, jsonObject, 0), propertyName, 0), true);
1612     JSStringRelease(propertyName);
1613     JSStringRef invalidJSON = JSStringCreateWithUTF8CString("fail!");
1614     if (JSValueMakeFromJSONString(context, invalidJSON)) {
1615         printf("FAIL: Should return null for invalid JSON data\n");
1616         failed = 1;
1617     } else
1618         printf("PASS: Correctly returned null for invalid JSON data.\n");
1619     JSValueRef exception;
1620     JSStringRef str = JSValueCreateJSONString(context, jsonObject, 0, 0);
1621     if (!JSStringIsEqualToUTF8CString(str, "{\"aProperty\":true}")) {
1622         printf("FAIL: Did not correctly serialise with indent of 0.\n");
1623         failed = 1;
1624     } else
1625         printf("PASS: Correctly serialised with indent of 0.\n");
1626     JSStringRelease(str);
1627
1628     str = JSValueCreateJSONString(context, jsonObject, 4, 0);
1629     if (!JSStringIsEqualToUTF8CString(str, "{\n    \"aProperty\": true\n}")) {
1630         printf("FAIL: Did not correctly serialise with indent of 4.\n");
1631         failed = 1;
1632     } else
1633         printf("PASS: Correctly serialised with indent of 4.\n");
1634     JSStringRelease(str);
1635
1636     str = JSStringCreateWithUTF8CString("({get a(){ throw '';}})");
1637     JSValueRef unstringifiableObj = JSEvaluateScript(context, str, NULL, NULL, 1, NULL);
1638     JSStringRelease(str);
1639     
1640     str = JSValueCreateJSONString(context, unstringifiableObj, 4, 0);
1641     if (str) {
1642         printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
1643         JSStringRelease(str);
1644         failed = 1;
1645     } else
1646         printf("PASS: returned null when attempting to serialize unserializable value.\n");
1647     
1648     str = JSValueCreateJSONString(context, unstringifiableObj, 4, &exception);
1649     if (str) {
1650         printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
1651         JSStringRelease(str);
1652         failed = 1;
1653     } else
1654         printf("PASS: returned null when attempting to serialize unserializable value.\n");
1655     if (!exception) {
1656         printf("FAIL: Did not set exception on serialisation error\n");
1657         failed = 1;
1658     } else
1659         printf("PASS: set exception on serialisation error\n");
1660     // Conversions that throw exceptions
1661     exception = NULL;
1662     ASSERT(NULL == JSValueToObject(context, jsNull, &exception));
1663     ASSERT(exception);
1664     
1665     exception = NULL;
1666     // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
1667     // causing a build break with -Wshorten-64-to-32 enabled.  The issue is known by the appropriate team.
1668     // After that's resolved, we can remove these casts
1669     ASSERT(isnan((float)JSValueToNumber(context, jsObjectNoProto, &exception)));
1670     ASSERT(exception);
1671
1672     exception = NULL;
1673     ASSERT(!JSValueToStringCopy(context, jsObjectNoProto, &exception));
1674     ASSERT(exception);
1675     
1676     ASSERT(JSValueToBoolean(context, myObject));
1677     
1678     exception = NULL;
1679     ASSERT(!JSValueIsEqual(context, jsObjectNoProto, JSValueMakeNumber(context, 1), &exception));
1680     ASSERT(exception);
1681     
1682     exception = NULL;
1683     JSObjectGetPropertyAtIndex(context, myObject, 0, &exception);
1684     ASSERT(1 == JSValueToNumber(context, exception, NULL));
1685
1686     assertEqualsAsBoolean(jsUndefined, false);
1687     assertEqualsAsBoolean(jsNull, false);
1688     assertEqualsAsBoolean(jsTrue, true);
1689     assertEqualsAsBoolean(jsFalse, false);
1690     assertEqualsAsBoolean(jsZero, false);
1691     assertEqualsAsBoolean(jsOne, true);
1692     assertEqualsAsBoolean(jsOneThird, true);
1693     assertEqualsAsBoolean(jsEmptyString, false);
1694     assertEqualsAsBoolean(jsOneString, true);
1695     
1696     assertEqualsAsNumber(jsUndefined, nan(""));
1697     assertEqualsAsNumber(jsNull, 0);
1698     assertEqualsAsNumber(jsTrue, 1);
1699     assertEqualsAsNumber(jsFalse, 0);
1700     assertEqualsAsNumber(jsZero, 0);
1701     assertEqualsAsNumber(jsOne, 1);
1702     assertEqualsAsNumber(jsOneThird, 1.0 / 3.0);
1703     assertEqualsAsNumber(jsEmptyString, 0);
1704     assertEqualsAsNumber(jsOneString, 1);
1705     
1706     assertEqualsAsCharactersPtr(jsUndefined, "undefined");
1707     assertEqualsAsCharactersPtr(jsNull, "null");
1708     assertEqualsAsCharactersPtr(jsTrue, "true");
1709     assertEqualsAsCharactersPtr(jsFalse, "false");
1710     assertEqualsAsCharactersPtr(jsZero, "0");
1711     assertEqualsAsCharactersPtr(jsOne, "1");
1712     assertEqualsAsCharactersPtr(jsOneThird, "0.3333333333333333");
1713     assertEqualsAsCharactersPtr(jsEmptyString, "");
1714     assertEqualsAsCharactersPtr(jsOneString, "1");
1715     
1716     assertEqualsAsUTF8String(jsUndefined, "undefined");
1717     assertEqualsAsUTF8String(jsNull, "null");
1718     assertEqualsAsUTF8String(jsTrue, "true");
1719     assertEqualsAsUTF8String(jsFalse, "false");
1720     assertEqualsAsUTF8String(jsZero, "0");
1721     assertEqualsAsUTF8String(jsOne, "1");
1722     assertEqualsAsUTF8String(jsOneThird, "0.3333333333333333");
1723     assertEqualsAsUTF8String(jsEmptyString, "");
1724     assertEqualsAsUTF8String(jsOneString, "1");
1725     
1726     checkConstnessInJSObjectNames();
1727     
1728     ASSERT(JSValueIsStrictEqual(context, jsTrue, jsTrue));
1729     ASSERT(!JSValueIsStrictEqual(context, jsOne, jsOneString));
1730
1731     ASSERT(JSValueIsEqual(context, jsOne, jsOneString, NULL));
1732     ASSERT(!JSValueIsEqual(context, jsTrue, jsFalse, NULL));
1733     
1734     jsGlobalValue = JSObjectMake(context, NULL, NULL);
1735     makeGlobalNumberValue(context);
1736     JSValueProtect(context, jsGlobalValue);
1737     JSGarbageCollect(context);
1738     ASSERT(JSValueIsObject(context, jsGlobalValue));
1739     JSValueUnprotect(context, jsGlobalValue);
1740     JSValueUnprotect(context, jsNumberValue);
1741
1742     JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
1743     const char* badSyntaxConstant = "x := 1;";
1744     JSStringRef badSyntax = JSStringCreateWithUTF8CString(badSyntaxConstant);
1745     ASSERT(JSCheckScriptSyntax(context, goodSyntax, NULL, 0, NULL));
1746     ASSERT(!JSCheckScriptSyntax(context, badSyntax, NULL, 0, NULL));
1747     ASSERT(!JSScriptCreateFromString(contextGroup, 0, 0, badSyntax, 0, 0));
1748     ASSERT(!JSScriptCreateReferencingImmortalASCIIText(contextGroup, 0, 0, badSyntaxConstant, strlen(badSyntaxConstant), 0, 0));
1749
1750     JSValueRef result;
1751     JSValueRef v;
1752     JSObjectRef o;
1753     JSStringRef string;
1754
1755     result = JSEvaluateScript(context, goodSyntax, NULL, NULL, 1, NULL);
1756     ASSERT(result);
1757     ASSERT(JSValueIsEqual(context, result, jsOne, NULL));
1758
1759     exception = NULL;
1760     result = JSEvaluateScript(context, badSyntax, NULL, NULL, 1, &exception);
1761     ASSERT(!result);
1762     ASSERT(JSValueIsObject(context, exception));
1763     
1764     JSStringRef array = JSStringCreateWithUTF8CString("Array");
1765     JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
1766     JSStringRelease(array);
1767     result = JSObjectCallAsConstructor(context, arrayConstructor, 0, NULL, NULL);
1768     ASSERT(result);
1769     ASSERT(JSValueIsObject(context, result));
1770     ASSERT(JSValueIsInstanceOfConstructor(context, result, arrayConstructor, NULL));
1771     ASSERT(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(context), arrayConstructor, NULL));
1772
1773     o = JSValueToObject(context, result, NULL);
1774     exception = NULL;
1775     ASSERT(JSValueIsUndefined(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception)));
1776     ASSERT(!exception);
1777     
1778     JSObjectSetPropertyAtIndex(context, o, 0, JSValueMakeNumber(context, 1), &exception);
1779     ASSERT(!exception);
1780     
1781     exception = NULL;
1782     ASSERT(1 == JSValueToNumber(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception), &exception));
1783     ASSERT(!exception);
1784
1785     JSStringRef functionBody;
1786     JSObjectRef function;
1787     
1788     exception = NULL;
1789     functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
1790     JSStringRef line = JSStringCreateWithUTF8CString("line");
1791     ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception));
1792     ASSERT(JSValueIsObject(context, exception));
1793     v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
1794     assertEqualsAsNumber(v, 2);
1795     JSStringRelease(functionBody);
1796     JSStringRelease(line);
1797
1798     exception = NULL;
1799     functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
1800     line = JSStringCreateWithUTF8CString("line");
1801     ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, -42, &exception));
1802     ASSERT(JSValueIsObject(context, exception));
1803     v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
1804     assertEqualsAsNumber(v, 2);
1805     JSStringRelease(functionBody);
1806     JSStringRelease(line);
1807
1808     exception = NULL;
1809     functionBody = JSStringCreateWithUTF8CString("// Line one.\nrreturn Array;");
1810     line = JSStringCreateWithUTF8CString("line");
1811     ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception));
1812     ASSERT(JSValueIsObject(context, exception));
1813     v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
1814     assertEqualsAsNumber(v, 3);
1815     JSStringRelease(functionBody);
1816     JSStringRelease(line);
1817
1818     exception = NULL;
1819     functionBody = JSStringCreateWithUTF8CString("return Array;");
1820     function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception);
1821     JSStringRelease(functionBody);
1822     ASSERT(!exception);
1823     ASSERT(JSObjectIsFunction(context, function));
1824     v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
1825     ASSERT(v);
1826     ASSERT(JSValueIsEqual(context, v, arrayConstructor, NULL));
1827     
1828     exception = NULL;
1829     function = JSObjectMakeFunction(context, NULL, 0, NULL, jsEmptyIString, NULL, 0, &exception);
1830     ASSERT(!exception);
1831     v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, &exception);
1832     ASSERT(v && !exception);
1833     ASSERT(JSValueIsUndefined(context, v));
1834     
1835     exception = NULL;
1836     v = NULL;
1837     JSStringRef foo = JSStringCreateWithUTF8CString("foo");
1838     JSStringRef argumentNames[] = { foo };
1839     functionBody = JSStringCreateWithUTF8CString("return foo;");
1840     function = JSObjectMakeFunction(context, foo, 1, argumentNames, functionBody, NULL, 1, &exception);
1841     ASSERT(function && !exception);
1842     JSValueRef arguments[] = { JSValueMakeNumber(context, 2) };
1843     JSObjectCallAsFunction(context, function, NULL, 1, arguments, &exception);
1844     JSStringRelease(foo);
1845     JSStringRelease(functionBody);
1846     
1847     string = JSValueToStringCopy(context, function, NULL);
1848     assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) {\nreturn foo;\n}");
1849     JSStringRelease(string);
1850
1851     JSStringRef print = JSStringCreateWithUTF8CString("print");
1852     JSObjectRef printFunction = JSObjectMakeFunctionWithCallback(context, print, print_callAsFunction);
1853     JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone, NULL); 
1854     JSStringRelease(print);
1855     
1856     ASSERT(!JSObjectSetPrivate(printFunction, (void*)1));
1857     ASSERT(!JSObjectGetPrivate(printFunction));
1858
1859     JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyConstructor");
1860     JSObjectRef myConstructor = JSObjectMakeConstructor(context, NULL, myConstructor_callAsConstructor);
1861     JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
1862     JSStringRelease(myConstructorIString);
1863     
1864     JSStringRef myBadConstructorIString = JSStringCreateWithUTF8CString("MyBadConstructor");
1865     JSObjectRef myBadConstructor = JSObjectMakeConstructor(context, NULL, myBadConstructor_callAsConstructor);
1866     JSObjectSetProperty(context, globalObject, myBadConstructorIString, myBadConstructor, kJSPropertyAttributeNone, NULL);
1867     JSStringRelease(myBadConstructorIString);
1868     
1869     ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
1870     ASSERT(!JSObjectGetPrivate(myConstructor));
1871     
1872     string = JSStringCreateWithUTF8CString("Base");
1873     JSObjectRef baseConstructor = JSObjectMakeConstructor(context, Base_class(context), NULL);
1874     JSObjectSetProperty(context, globalObject, string, baseConstructor, kJSPropertyAttributeNone, NULL);
1875     JSStringRelease(string);
1876     
1877     string = JSStringCreateWithUTF8CString("Derived");
1878     JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL);
1879     JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL);
1880     JSStringRelease(string);
1881     
1882     string = JSStringCreateWithUTF8CString("Derived2");
1883     JSObjectRef derived2Constructor = JSObjectMakeConstructor(context, Derived2_class(context), NULL);
1884     JSObjectSetProperty(context, globalObject, string, derived2Constructor, kJSPropertyAttributeNone, NULL);
1885     JSStringRelease(string);
1886
1887     JSValueRef argumentsArrayValues[] = { JSValueMakeNumber(context, 10), JSValueMakeNumber(context, 20) };
1888     o = JSObjectMakeArray(context, sizeof(argumentsArrayValues) / sizeof(JSValueRef), argumentsArrayValues, NULL);
1889     string = JSStringCreateWithUTF8CString("length");
1890     v = JSObjectGetProperty(context, o, string, NULL);
1891     assertEqualsAsNumber(v, 2);
1892     v = JSObjectGetPropertyAtIndex(context, o, 0, NULL);
1893     assertEqualsAsNumber(v, 10);
1894     v = JSObjectGetPropertyAtIndex(context, o, 1, NULL);
1895     assertEqualsAsNumber(v, 20);
1896
1897     o = JSObjectMakeArray(context, 0, NULL, NULL);
1898     v = JSObjectGetProperty(context, o, string, NULL);
1899     assertEqualsAsNumber(v, 0);
1900     JSStringRelease(string);
1901
1902     JSValueRef argumentsDateValues[] = { JSValueMakeNumber(context, 0) };
1903     o = JSObjectMakeDate(context, 1, argumentsDateValues, NULL);
1904     if (timeZoneIsPST())
1905         assertEqualsAsUTF8String(o, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
1906
1907     string = JSStringCreateWithUTF8CString("an error message");
1908     JSValueRef argumentsErrorValues[] = { JSValueMakeString(context, string) };
1909     o = JSObjectMakeError(context, 1, argumentsErrorValues, NULL);
1910     assertEqualsAsUTF8String(o, "Error: an error message");
1911     JSStringRelease(string);
1912
1913     string = JSStringCreateWithUTF8CString("foo");
1914     JSStringRef string2 = JSStringCreateWithUTF8CString("gi");
1915     JSValueRef argumentsRegExpValues[] = { JSValueMakeString(context, string), JSValueMakeString(context, string2) };
1916     o = JSObjectMakeRegExp(context, 2, argumentsRegExpValues, NULL);
1917     assertEqualsAsUTF8String(o, "/foo/gi");
1918     JSStringRelease(string);
1919     JSStringRelease(string2);
1920
1921     JSClassDefinition nullDefinition = kJSClassDefinitionEmpty;
1922     nullDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
1923     JSClassRef nullClass = JSClassCreate(&nullDefinition);
1924     JSClassRelease(nullClass);
1925     
1926     nullDefinition = kJSClassDefinitionEmpty;
1927     nullClass = JSClassCreate(&nullDefinition);
1928     JSClassRelease(nullClass);
1929
1930     functionBody = JSStringCreateWithUTF8CString("return this;");
1931     function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
1932     JSStringRelease(functionBody);
1933     v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
1934     ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1935     v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
1936     ASSERT(JSValueIsEqual(context, v, o, NULL));
1937
1938     functionBody = JSStringCreateWithUTF8CString("return eval(\"this\");");
1939     function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
1940     JSStringRelease(functionBody);
1941     v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
1942     ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1943     v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
1944     ASSERT(JSValueIsEqual(context, v, o, NULL));
1945
1946     const char* thisScript = "this;";
1947     JSStringRef script = JSStringCreateWithUTF8CString(thisScript);
1948     v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
1949     ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1950     v = JSEvaluateScript(context, script, o, NULL, 1, NULL);
1951     ASSERT(JSValueIsEqual(context, v, o, NULL));
1952     JSStringRelease(script);
1953
1954     JSScriptRef scriptObject = JSScriptCreateReferencingImmortalASCIIText(contextGroup, 0, 0, thisScript, strlen(thisScript), 0, 0);
1955     v = JSScriptEvaluate(context, scriptObject, NULL, NULL);
1956     ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1957     v = JSScriptEvaluate(context, scriptObject, o, NULL);
1958     ASSERT(JSValueIsEqual(context, v, o, NULL));
1959     JSScriptRelease(scriptObject);
1960
1961     script = JSStringCreateWithUTF8CString("eval(this);");
1962     v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
1963     ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1964     v = JSEvaluateScript(context, script, o, NULL, 1, NULL);
1965     ASSERT(JSValueIsEqual(context, v, o, NULL));
1966     JSStringRelease(script);
1967
1968     script = JSStringCreateWithUTF8CString("[ ]");
1969     v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
1970     ASSERT(JSValueIsArray(context, v));
1971     JSStringRelease(script);
1972
1973     script = JSStringCreateWithUTF8CString("new Date");
1974     v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
1975     ASSERT(JSValueIsDate(context, v));
1976     JSStringRelease(script);
1977
1978     exception = NULL;
1979     script = JSStringCreateWithUTF8CString("rreturn Array;");
1980     JSStringRef sourceURL = JSStringCreateWithUTF8CString("file:///foo/bar.js");
1981     JSStringRef sourceURLKey = JSStringCreateWithUTF8CString("sourceURL");
1982     JSEvaluateScript(context, script, NULL, sourceURL, 1, &exception);
1983     ASSERT(exception);
1984     v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), sourceURLKey, NULL);
1985     assertEqualsAsUTF8String(v, "file:///foo/bar.js");
1986     JSStringRelease(script);
1987     JSStringRelease(sourceURL);
1988     JSStringRelease(sourceURLKey);
1989
1990     // Verify that creating a constructor for a class with no static functions does not trigger
1991     // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
1992     nullDefinition = kJSClassDefinitionEmpty;
1993     nullClass = JSClassCreate(&nullDefinition);
1994     JSObjectMakeConstructor(context, nullClass, 0);
1995     JSClassRelease(nullClass);
1996
1997     const char* scriptPath = "./testapiScripts/testapi.js";
1998     char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
1999     if (!scriptUTF8) {
2000         printf("FAIL: Test script could not be loaded.\n");
2001         failed = 1;
2002     } else {
2003         JSStringRef url = JSStringCreateWithUTF8CString(scriptPath);
2004         JSStringRef script = JSStringCreateWithUTF8CString(scriptUTF8);
2005         JSStringRef errorMessage = 0;
2006         int errorLine = 0;
2007         JSScriptRef scriptObject = JSScriptCreateFromString(contextGroup, url, 1, script, &errorMessage, &errorLine);
2008         ASSERT((!scriptObject) != (!errorMessage));
2009         if (!scriptObject) {
2010             printf("FAIL: Test script did not parse\n\t%s:%d\n\t", scriptPath, errorLine);
2011 #if USE(CF)
2012             CFStringRef errorCF = JSStringCopyCFString(kCFAllocatorDefault, errorMessage);
2013             CFShow(errorCF);
2014             CFRelease(errorCF);
2015 #endif
2016             JSStringRelease(errorMessage);
2017             failed = 1;
2018         }
2019
2020         JSStringRelease(script);
2021         exception = NULL;
2022         result = scriptObject ? JSScriptEvaluate(context, scriptObject, 0, &exception) : 0;
2023         if (result && JSValueIsUndefined(context, result))
2024             printf("PASS: Test script executed successfully.\n");
2025         else {
2026             printf("FAIL: Test script returned unexpected value:\n");
2027             JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
2028 #if USE(CF)
2029             CFStringRef exceptionCF = JSStringCopyCFString(kCFAllocatorDefault, exceptionIString);
2030             CFShow(exceptionCF);
2031             CFRelease(exceptionCF);
2032 #endif
2033             JSStringRelease(exceptionIString);
2034             failed = 1;
2035         }
2036         JSScriptRelease(scriptObject);
2037         free(scriptUTF8);
2038     }
2039
2040     // Check Promise is not exposed.
2041     {
2042         JSObjectRef globalObject = JSContextGetGlobalObject(context);
2043         {
2044             JSStringRef promiseProperty = JSStringCreateWithUTF8CString("Promise");
2045             ASSERT(JSObjectHasProperty(context, globalObject, promiseProperty));
2046             JSStringRelease(promiseProperty);
2047         }
2048         {
2049             JSStringRef script = JSStringCreateWithUTF8CString("typeof Promise");
2050             JSStringRef function = JSStringCreateWithUTF8CString("function");
2051             JSValueRef value = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
2052             ASSERT(JSValueIsString(context, value));
2053             JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
2054             ASSERT(JSStringIsEqual(valueAsString, function));
2055             JSStringRelease(valueAsString);
2056             JSStringRelease(function);
2057             JSStringRelease(script);
2058         }
2059         printf("PASS: Promise is exposed under JSContext API.\n");
2060     }
2061
2062     // Check microtasks.
2063     {
2064         JSGlobalContextRef context = JSGlobalContextCreateInGroup(NULL, NULL);
2065         {
2066             JSObjectRef globalObject = JSContextGetGlobalObject(context);
2067             JSValueRef exception;
2068             JSStringRef code = JSStringCreateWithUTF8CString("result = 0; Promise.resolve(42).then(function (value) { result = value; });");
2069             JSStringRef file = JSStringCreateWithUTF8CString("");
2070             assertTrue((bool)JSEvaluateScript(context, code, globalObject, file, 1, &exception), "An exception should not be thrown");
2071             JSStringRelease(code);
2072             JSStringRelease(file);
2073
2074             JSStringRef resultProperty = JSStringCreateWithUTF8CString("result");
2075             ASSERT(JSObjectHasProperty(context, globalObject, resultProperty));
2076
2077             JSValueRef resultValue = JSObjectGetProperty(context, globalObject, resultProperty, &exception);
2078             assertEqualsAsNumber(resultValue, 42);
2079             JSStringRelease(resultProperty);
2080         }
2081         JSGlobalContextRelease(context);
2082     }
2083
2084     // Check JSObjectGetGlobalContext
2085     {
2086         JSGlobalContextRef context = JSGlobalContextCreateInGroup(NULL, NULL);
2087         {
2088             JSObjectRef globalObject = JSContextGetGlobalObject(context);
2089             assertTrue(JSObjectGetGlobalContext(globalObject) == context, "global object context is correct");
2090             JSObjectRef object = JSObjectMake(context, NULL, NULL);
2091             assertTrue(JSObjectGetGlobalContext(object) == context, "regular object context is correct");
2092             JSStringRef returnFunctionSource = JSStringCreateWithUTF8CString("return this;");
2093             JSObjectRef theFunction = JSObjectMakeFunction(context, NULL, 0, NULL, returnFunctionSource, NULL, 1, NULL);
2094             assertTrue(JSObjectGetGlobalContext(theFunction) == context, "function object context is correct");
2095             assertTrue(JSObjectGetGlobalContext(NULL) == NULL, "NULL object context is NULL");
2096             JSStringRelease(returnFunctionSource);
2097         }
2098         JSGlobalContextRelease(context);
2099     }
2100     failed |= testTypedArrayCAPI();
2101     failed |= testExecutionTimeLimit();
2102     failed |= testFunctionOverrides();
2103     failed |= testGlobalContextWithFinalizer();
2104     failed |= testPingPongStackOverflow();
2105     failed |= testJSONParse();
2106     failed |= testJSObjectGetProxyTarget();
2107
2108     // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
2109     function = NULL;
2110     v = NULL;
2111     o = NULL;
2112     globalObject = NULL;
2113     myConstructor = NULL;
2114
2115     JSStringRelease(jsEmptyIString);
2116     JSStringRelease(jsOneIString);
2117     JSStringRelease(goodSyntax);
2118     JSStringRelease(badSyntax);
2119
2120     JSGlobalContextRelease(context);
2121     JSClassRelease(globalObjectClass);
2122
2123     // Test for an infinite prototype chain that used to be created. This test
2124     // passes if the call to JSObjectHasProperty() does not hang.
2125
2126     JSClassDefinition prototypeLoopClassDefinition = kJSClassDefinitionEmpty;
2127     prototypeLoopClassDefinition.staticFunctions = globalObject_staticFunctions;
2128     JSClassRef prototypeLoopClass = JSClassCreate(&prototypeLoopClassDefinition);
2129     JSGlobalContextRef prototypeLoopContext = JSGlobalContextCreateInGroup(NULL, prototypeLoopClass);
2130
2131     JSStringRef nameProperty = JSStringCreateWithUTF8CString("name");
2132     JSObjectHasProperty(prototypeLoopContext, JSContextGetGlobalObject(prototypeLoopContext), nameProperty);
2133
2134     JSGlobalContextRelease(prototypeLoopContext);
2135     JSClassRelease(prototypeLoopClass);
2136
2137     printf("PASS: Infinite prototype chain does not occur.\n");
2138
2139     if (checkForCycleInPrototypeChain())
2140         printf("PASS: A cycle in a prototype chain can't be created.\n");
2141     else {
2142         printf("FAIL: A cycle in a prototype chain can be created.\n");
2143         failed = true;
2144     }
2145     if (valueToObjectExceptionTest())
2146         printf("PASS: throwException did not crash when handling an error with appendMessageToError set and no codeBlock available.\n");
2147
2148     if (globalContextNameTest())
2149         printf("PASS: global context name behaves as expected.\n");
2150
2151     customGlobalObjectClassTest();
2152     globalObjectSetPrototypeTest();
2153     globalObjectPrivatePropertyTest();
2154
2155     failed = finalizeMultithreadedMultiVMExecutionTest() || failed;
2156
2157     if (failed) {
2158         printf("FAIL: Some tests failed.\n");
2159         return 1;
2160     }
2161
2162     printf("PASS: Program exited normally.\n");
2163     return 0;
2164 }
2165
2166 static char* createStringWithContentsOfFile(const char* fileName)
2167 {
2168     char* buffer;
2169     
2170     size_t buffer_size = 0;
2171     size_t buffer_capacity = 1024;
2172     buffer = (char*)malloc(buffer_capacity);
2173     
2174     FILE* f = fopen(fileName, "r");
2175     if (!f) {
2176         fprintf(stderr, "Could not open file: %s\n", fileName);
2177         free(buffer);
2178         return 0;
2179     }
2180     
2181     while (!feof(f) && !ferror(f)) {
2182         buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
2183         if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
2184             buffer_capacity *= 2;
2185             buffer = (char*)realloc(buffer, buffer_capacity);
2186             ASSERT(buffer);
2187         }
2188         
2189         ASSERT(buffer_size < buffer_capacity);
2190     }
2191     fclose(f);
2192     buffer[buffer_size] = '\0';
2193     
2194     return buffer;
2195 }
2196
2197 #if OS(WINDOWS)
2198 __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, char* argv[])
2199 {
2200     return main(argc, argv);
2201 }
2202 #endif