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