2 * Copyright (C) 2006 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #include <wtf/Platform.h>
28 #include "JavaScriptCore.h"
29 #include "JSBasePrivate.h"
30 #include "JSContextRefPrivate.h"
31 #include "JSObjectRefPrivate.h"
32 #include "JSScriptRefPrivate.h"
33 #include "JSStringRefPrivate.h"
35 #define ASSERT_DISABLED 0
36 #include <wtf/Assertions.h>
39 #include <mach/mach.h>
40 #include <mach/mach_time.h>
48 #include "CustomGlobalObjectClassTest.h"
50 #if JSC_OBJC_API_ENABLED
51 void testObjectiveCAPI(void);
54 bool assertTrue(bool value
, const char* message
);
55 extern void JSSynchronousGarbageCollectForDebugging(JSContextRef
);
57 static JSGlobalContextRef context
;
59 static void assertEqualsAsBoolean(JSValueRef value
, bool expectedValue
)
61 if (JSValueToBoolean(context
, value
) != expectedValue
) {
62 fprintf(stderr
, "assertEqualsAsBoolean failed: %p, %d\n", value
, expectedValue
);
67 static void assertEqualsAsNumber(JSValueRef value
, double expectedValue
)
69 double number
= JSValueToNumber(context
, value
, NULL
);
71 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
72 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
73 // After that's resolved, we can remove these casts
74 if (number
!= expectedValue
&& !(isnan((float)number
) && isnan((float)expectedValue
))) {
75 fprintf(stderr
, "assertEqualsAsNumber failed: %p, %lf\n", value
, expectedValue
);
80 static void assertEqualsAsUTF8String(JSValueRef value
, const char* expectedValue
)
82 JSStringRef valueAsString
= JSValueToStringCopy(context
, value
, NULL
);
84 size_t jsSize
= JSStringGetMaximumUTF8CStringSize(valueAsString
);
85 char* jsBuffer
= (char*)malloc(jsSize
);
86 JSStringGetUTF8CString(valueAsString
, jsBuffer
, jsSize
);
89 for (i
= 0; jsBuffer
[i
]; i
++) {
90 if (jsBuffer
[i
] != expectedValue
[i
]) {
91 fprintf(stderr
, "assertEqualsAsUTF8String failed at character %d: %c(%d) != %c(%d)\n", i
, jsBuffer
[i
], jsBuffer
[i
], expectedValue
[i
], expectedValue
[i
]);
96 if (jsSize
< strlen(jsBuffer
) + 1) {
97 fprintf(stderr
, "assertEqualsAsUTF8String failed: jsSize was too small\n");
102 JSStringRelease(valueAsString
);
105 static void assertEqualsAsCharactersPtr(JSValueRef value
, const char* expectedValue
)
107 JSStringRef valueAsString
= JSValueToStringCopy(context
, value
, NULL
);
109 size_t jsLength
= JSStringGetLength(valueAsString
);
110 const JSChar
* jsBuffer
= JSStringGetCharactersPtr(valueAsString
);
112 CFStringRef expectedValueAsCFString
= CFStringCreateWithCString(kCFAllocatorDefault
,
114 kCFStringEncodingUTF8
);
115 CFIndex cfLength
= CFStringGetLength(expectedValueAsCFString
);
116 UniChar
* cfBuffer
= (UniChar
*)malloc(cfLength
* sizeof(UniChar
));
117 CFStringGetCharacters(expectedValueAsCFString
, CFRangeMake(0, cfLength
), cfBuffer
);
118 CFRelease(expectedValueAsCFString
);
120 if (memcmp(jsBuffer
, cfBuffer
, cfLength
* sizeof(UniChar
)) != 0) {
121 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
125 if (jsLength
!= (size_t)cfLength
) {
126 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength
, cfLength
);
131 JSStringRelease(valueAsString
);
134 static bool timeZoneIsPST()
136 char timeZoneName
[70];
138 memset(>m
, 0, sizeof(gtm
));
139 strftime(timeZoneName
, sizeof(timeZoneName
), "%Z", >m
);
141 return 0 == strcmp("PST", timeZoneName
);
144 static JSValueRef jsGlobalValue
; // non-stack value for testing JSValueProtect()
146 /* MyObject pseudo-class */
148 static bool MyObject_hasProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
)
150 UNUSED_PARAM(context
);
151 UNUSED_PARAM(object
);
153 if (JSStringIsEqualToUTF8CString(propertyName
, "alwaysOne")
154 || JSStringIsEqualToUTF8CString(propertyName
, "cantFind")
155 || JSStringIsEqualToUTF8CString(propertyName
, "throwOnGet")
156 || JSStringIsEqualToUTF8CString(propertyName
, "myPropertyName")
157 || JSStringIsEqualToUTF8CString(propertyName
, "hasPropertyLie")
158 || JSStringIsEqualToUTF8CString(propertyName
, "0")) {
165 static JSValueRef
MyObject_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
167 UNUSED_PARAM(context
);
168 UNUSED_PARAM(object
);
170 if (JSStringIsEqualToUTF8CString(propertyName
, "alwaysOne")) {
171 return JSValueMakeNumber(context
, 1);
174 if (JSStringIsEqualToUTF8CString(propertyName
, "myPropertyName")) {
175 return JSValueMakeNumber(context
, 1);
178 if (JSStringIsEqualToUTF8CString(propertyName
, "cantFind")) {
179 return JSValueMakeUndefined(context
);
182 if (JSStringIsEqualToUTF8CString(propertyName
, "hasPropertyLie")) {
186 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnGet")) {
187 return JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
190 if (JSStringIsEqualToUTF8CString(propertyName
, "0")) {
191 *exception
= JSValueMakeNumber(context
, 1);
192 return JSValueMakeNumber(context
, 1);
195 return JSValueMakeNull(context
);
198 static bool MyObject_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
200 UNUSED_PARAM(context
);
201 UNUSED_PARAM(object
);
203 UNUSED_PARAM(exception
);
205 if (JSStringIsEqualToUTF8CString(propertyName
, "cantSet"))
206 return true; // pretend we set the property in order to swallow it
208 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnSet")) {
209 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
215 static bool MyObject_deleteProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
217 UNUSED_PARAM(context
);
218 UNUSED_PARAM(object
);
220 if (JSStringIsEqualToUTF8CString(propertyName
, "cantDelete"))
223 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnDelete")) {
224 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
231 static void MyObject_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef propertyNames
)
233 UNUSED_PARAM(context
);
234 UNUSED_PARAM(object
);
236 JSStringRef propertyName
;
238 propertyName
= JSStringCreateWithUTF8CString("alwaysOne");
239 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
240 JSStringRelease(propertyName
);
242 propertyName
= JSStringCreateWithUTF8CString("myPropertyName");
243 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
244 JSStringRelease(propertyName
);
247 static JSValueRef
MyObject_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
249 UNUSED_PARAM(context
);
250 UNUSED_PARAM(object
);
251 UNUSED_PARAM(thisObject
);
252 UNUSED_PARAM(exception
);
254 if (argumentCount
> 0 && JSValueIsString(context
, arguments
[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, arguments
[0], 0), "throwOnCall")) {
255 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
256 return JSValueMakeUndefined(context
);
259 if (argumentCount
> 0 && JSValueIsStrictEqual(context
, arguments
[0], JSValueMakeNumber(context
, 0)))
260 return JSValueMakeNumber(context
, 1);
262 return JSValueMakeUndefined(context
);
265 static JSObjectRef
MyObject_callAsConstructor(JSContextRef context
, JSObjectRef object
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
267 UNUSED_PARAM(context
);
268 UNUSED_PARAM(object
);
270 if (argumentCount
> 0 && JSValueIsString(context
, arguments
[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, arguments
[0], 0), "throwOnConstruct")) {
271 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
275 if (argumentCount
> 0 && JSValueIsStrictEqual(context
, arguments
[0], JSValueMakeNumber(context
, 0)))
276 return JSValueToObject(context
, JSValueMakeNumber(context
, 1), exception
);
278 return JSValueToObject(context
, JSValueMakeNumber(context
, 0), exception
);
281 static bool MyObject_hasInstance(JSContextRef context
, JSObjectRef constructor
, JSValueRef possibleValue
, JSValueRef
* exception
)
283 UNUSED_PARAM(context
);
284 UNUSED_PARAM(constructor
);
286 if (JSValueIsString(context
, possibleValue
) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, possibleValue
, 0), "throwOnHasInstance")) {
287 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), constructor
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
291 JSStringRef numberString
= JSStringCreateWithUTF8CString("Number");
292 JSObjectRef numberConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, JSContextGetGlobalObject(context
), numberString
, exception
), exception
);
293 JSStringRelease(numberString
);
295 return JSValueIsInstanceOfConstructor(context
, possibleValue
, numberConstructor
, exception
);
298 static JSValueRef
MyObject_convertToType(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
300 UNUSED_PARAM(object
);
301 UNUSED_PARAM(exception
);
305 return JSValueMakeNumber(context
, 1);
308 JSStringRef string
= JSStringCreateWithUTF8CString("MyObjectAsString");
309 JSValueRef result
= JSValueMakeString(context
, string
);
310 JSStringRelease(string
);
317 // string conversion -- forward to default object class
318 return JSValueMakeNull(context
);
321 static JSValueRef
MyObject_convertToTypeWrapper(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
323 UNUSED_PARAM(context
);
324 UNUSED_PARAM(object
);
326 UNUSED_PARAM(exception
);
327 // Forward to default object class
331 static bool MyObject_set_nullGetForwardSet(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
334 UNUSED_PARAM(object
);
335 UNUSED_PARAM(propertyName
);
337 UNUSED_PARAM(exception
);
338 return false; // Forward to parent class.
341 static JSStaticValue evilStaticValues
[] = {
342 { "nullGetSet", 0, 0, kJSPropertyAttributeNone
},
343 { "nullGetForwardSet", 0, MyObject_set_nullGetForwardSet
, kJSPropertyAttributeNone
},
347 static JSStaticFunction evilStaticFunctions
[] = {
348 { "nullCall", 0, kJSPropertyAttributeNone
},
352 JSClassDefinition MyObject_definition
= {
354 kJSClassAttributeNone
,
364 MyObject_hasProperty
,
365 MyObject_getProperty
,
366 MyObject_setProperty
,
367 MyObject_deleteProperty
,
368 MyObject_getPropertyNames
,
369 MyObject_callAsFunction
,
370 MyObject_callAsConstructor
,
371 MyObject_hasInstance
,
372 MyObject_convertToType
,
375 JSClassDefinition MyObject_convertToTypeWrapperDefinition
= {
377 kJSClassAttributeNone
,
395 MyObject_convertToTypeWrapper
,
398 JSClassDefinition MyObject_nullWrapperDefinition
= {
400 kJSClassAttributeNone
,
421 static JSClassRef
MyObject_class(JSContextRef context
)
423 UNUSED_PARAM(context
);
425 static JSClassRef jsClass
;
427 JSClassRef baseClass
= JSClassCreate(&MyObject_definition
);
428 MyObject_convertToTypeWrapperDefinition
.parentClass
= baseClass
;
429 JSClassRef wrapperClass
= JSClassCreate(&MyObject_convertToTypeWrapperDefinition
);
430 MyObject_nullWrapperDefinition
.parentClass
= wrapperClass
;
431 jsClass
= JSClassCreate(&MyObject_nullWrapperDefinition
);
437 static JSValueRef
PropertyCatchalls_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
439 UNUSED_PARAM(context
);
440 UNUSED_PARAM(object
);
441 UNUSED_PARAM(propertyName
);
442 UNUSED_PARAM(exception
);
444 if (JSStringIsEqualToUTF8CString(propertyName
, "x")) {
449 // Swallow all .x gets after 5, returning null.
450 return JSValueMakeNull(context
);
453 if (JSStringIsEqualToUTF8CString(propertyName
, "y")) {
458 // Swallow all .y gets after 5, returning null.
459 return JSValueMakeNull(context
);
462 if (JSStringIsEqualToUTF8CString(propertyName
, "z")) {
467 // Swallow all .y gets after 5, returning null.
468 return JSValueMakeNull(context
);
474 static bool PropertyCatchalls_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
476 UNUSED_PARAM(context
);
477 UNUSED_PARAM(object
);
478 UNUSED_PARAM(propertyName
);
480 UNUSED_PARAM(exception
);
482 if (JSStringIsEqualToUTF8CString(propertyName
, "x")) {
487 // Swallow all .x sets after 4.
491 if (JSStringIsEqualToUTF8CString(propertyName
, "make_throw") || JSStringIsEqualToUTF8CString(propertyName
, "0")) {
492 *exception
= JSValueMakeNumber(context
, 5);
499 static void PropertyCatchalls_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef propertyNames
)
501 UNUSED_PARAM(context
);
502 UNUSED_PARAM(object
);
505 static const char* numbers
[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
507 // Provide a property of a different name every time.
508 JSStringRef propertyName
= JSStringCreateWithUTF8CString(numbers
[count
++ % 10]);
509 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
510 JSStringRelease(propertyName
);
513 JSClassDefinition PropertyCatchalls_definition
= {
515 kJSClassAttributeNone
,
526 PropertyCatchalls_getProperty
,
527 PropertyCatchalls_setProperty
,
529 PropertyCatchalls_getPropertyNames
,
536 static JSClassRef
PropertyCatchalls_class(JSContextRef context
)
538 UNUSED_PARAM(context
);
540 static JSClassRef jsClass
;
542 jsClass
= JSClassCreate(&PropertyCatchalls_definition
);
547 static bool EvilExceptionObject_hasInstance(JSContextRef context
, JSObjectRef constructor
, JSValueRef possibleValue
, JSValueRef
* exception
)
549 UNUSED_PARAM(context
);
550 UNUSED_PARAM(constructor
);
552 JSStringRef hasInstanceName
= JSStringCreateWithUTF8CString("hasInstance");
553 JSValueRef hasInstance
= JSObjectGetProperty(context
, constructor
, hasInstanceName
, exception
);
554 JSStringRelease(hasInstanceName
);
557 JSObjectRef function
= JSValueToObject(context
, hasInstance
, exception
);
558 JSValueRef result
= JSObjectCallAsFunction(context
, function
, constructor
, 1, &possibleValue
, exception
);
559 return result
&& JSValueToBoolean(context
, result
);
562 static JSValueRef
EvilExceptionObject_convertToType(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
564 UNUSED_PARAM(object
);
565 UNUSED_PARAM(exception
);
566 JSStringRef funcName
;
569 funcName
= JSStringCreateWithUTF8CString("toNumber");
572 funcName
= JSStringCreateWithUTF8CString("toStringExplicit");
575 return JSValueMakeNull(context
);
578 JSValueRef func
= JSObjectGetProperty(context
, object
, funcName
, exception
);
579 JSStringRelease(funcName
);
580 JSObjectRef function
= JSValueToObject(context
, func
, exception
);
582 return JSValueMakeNull(context
);
583 JSValueRef value
= JSObjectCallAsFunction(context
, function
, object
, 0, NULL
, exception
);
585 JSStringRef errorString
= JSStringCreateWithUTF8CString("convertToType failed");
586 JSValueRef errorStringRef
= JSValueMakeString(context
, errorString
);
587 JSStringRelease(errorString
);
588 return errorStringRef
;
593 JSClassDefinition EvilExceptionObject_definition
= {
595 kJSClassAttributeNone
,
597 "EvilExceptionObject",
612 EvilExceptionObject_hasInstance
,
613 EvilExceptionObject_convertToType
,
616 static JSClassRef
EvilExceptionObject_class(JSContextRef context
)
618 UNUSED_PARAM(context
);
620 static JSClassRef jsClass
;
622 jsClass
= JSClassCreate(&EvilExceptionObject_definition
);
627 JSClassDefinition EmptyObject_definition
= {
629 kJSClassAttributeNone
,
650 static JSClassRef
EmptyObject_class(JSContextRef context
)
652 UNUSED_PARAM(context
);
654 static JSClassRef jsClass
;
656 jsClass
= JSClassCreate(&EmptyObject_definition
);
662 static JSValueRef
Base_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
664 UNUSED_PARAM(object
);
665 UNUSED_PARAM(propertyName
);
666 UNUSED_PARAM(exception
);
668 return JSValueMakeNumber(ctx
, 1); // distinguish base get form derived get
671 static bool Base_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
673 UNUSED_PARAM(object
);
674 UNUSED_PARAM(propertyName
);
677 *exception
= JSValueMakeNumber(ctx
, 1); // distinguish base set from derived set
681 static JSValueRef
Base_callAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
683 UNUSED_PARAM(function
);
684 UNUSED_PARAM(thisObject
);
685 UNUSED_PARAM(argumentCount
);
686 UNUSED_PARAM(arguments
);
687 UNUSED_PARAM(exception
);
689 return JSValueMakeNumber(ctx
, 1); // distinguish base call from derived call
692 static JSValueRef
Base_returnHardNull(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
695 UNUSED_PARAM(function
);
696 UNUSED_PARAM(thisObject
);
697 UNUSED_PARAM(argumentCount
);
698 UNUSED_PARAM(arguments
);
699 UNUSED_PARAM(exception
);
701 return 0; // should convert to undefined!
704 static JSStaticFunction Base_staticFunctions
[] = {
705 { "baseProtoDup", NULL
, kJSPropertyAttributeNone
},
706 { "baseProto", Base_callAsFunction
, kJSPropertyAttributeNone
},
707 { "baseHardNull", Base_returnHardNull
, kJSPropertyAttributeNone
},
711 static JSStaticValue Base_staticValues
[] = {
712 { "baseDup", Base_get
, Base_set
, kJSPropertyAttributeNone
},
713 { "baseOnly", Base_get
, Base_set
, kJSPropertyAttributeNone
},
717 static bool TestInitializeFinalize
;
718 static void Base_initialize(JSContextRef context
, JSObjectRef object
)
720 UNUSED_PARAM(context
);
722 if (TestInitializeFinalize
) {
723 ASSERT((void*)1 == JSObjectGetPrivate(object
));
724 JSObjectSetPrivate(object
, (void*)2);
728 static unsigned Base_didFinalize
;
729 static void Base_finalize(JSObjectRef object
)
731 UNUSED_PARAM(object
);
732 if (TestInitializeFinalize
) {
733 ASSERT((void*)4 == JSObjectGetPrivate(object
));
734 Base_didFinalize
= true;
738 static JSClassRef
Base_class(JSContextRef context
)
740 UNUSED_PARAM(context
);
742 static JSClassRef jsClass
;
744 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
745 definition
.staticValues
= Base_staticValues
;
746 definition
.staticFunctions
= Base_staticFunctions
;
747 definition
.initialize
= Base_initialize
;
748 definition
.finalize
= Base_finalize
;
749 jsClass
= JSClassCreate(&definition
);
754 static JSValueRef
Derived_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
756 UNUSED_PARAM(object
);
757 UNUSED_PARAM(propertyName
);
758 UNUSED_PARAM(exception
);
760 return JSValueMakeNumber(ctx
, 2); // distinguish base get form derived get
763 static bool Derived_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
766 UNUSED_PARAM(object
);
767 UNUSED_PARAM(propertyName
);
770 *exception
= JSValueMakeNumber(ctx
, 2); // distinguish base set from derived set
774 static JSValueRef
Derived_callAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
776 UNUSED_PARAM(function
);
777 UNUSED_PARAM(thisObject
);
778 UNUSED_PARAM(argumentCount
);
779 UNUSED_PARAM(arguments
);
780 UNUSED_PARAM(exception
);
782 return JSValueMakeNumber(ctx
, 2); // distinguish base call from derived call
785 static JSStaticFunction Derived_staticFunctions
[] = {
786 { "protoOnly", Derived_callAsFunction
, kJSPropertyAttributeNone
},
787 { "protoDup", NULL
, kJSPropertyAttributeNone
},
788 { "baseProtoDup", Derived_callAsFunction
, kJSPropertyAttributeNone
},
792 static JSStaticValue Derived_staticValues
[] = {
793 { "derivedOnly", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
794 { "protoDup", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
795 { "baseDup", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
799 static void Derived_initialize(JSContextRef context
, JSObjectRef object
)
801 UNUSED_PARAM(context
);
803 if (TestInitializeFinalize
) {
804 ASSERT((void*)2 == JSObjectGetPrivate(object
));
805 JSObjectSetPrivate(object
, (void*)3);
809 static void Derived_finalize(JSObjectRef object
)
811 if (TestInitializeFinalize
) {
812 ASSERT((void*)3 == JSObjectGetPrivate(object
));
813 JSObjectSetPrivate(object
, (void*)4);
817 static JSClassRef
Derived_class(JSContextRef context
)
819 static JSClassRef jsClass
;
821 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
822 definition
.parentClass
= Base_class(context
);
823 definition
.staticValues
= Derived_staticValues
;
824 definition
.staticFunctions
= Derived_staticFunctions
;
825 definition
.initialize
= Derived_initialize
;
826 definition
.finalize
= Derived_finalize
;
827 jsClass
= JSClassCreate(&definition
);
832 static JSClassRef
Derived2_class(JSContextRef context
)
834 static JSClassRef jsClass
;
836 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
837 definition
.parentClass
= Derived_class(context
);
838 jsClass
= JSClassCreate(&definition
);
843 static JSValueRef
print_callAsFunction(JSContextRef ctx
, JSObjectRef functionObject
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
845 UNUSED_PARAM(functionObject
);
846 UNUSED_PARAM(thisObject
);
847 UNUSED_PARAM(exception
);
849 ASSERT(JSContextGetGlobalContext(ctx
) == context
);
851 if (argumentCount
> 0) {
852 JSStringRef string
= JSValueToStringCopy(ctx
, arguments
[0], NULL
);
853 size_t sizeUTF8
= JSStringGetMaximumUTF8CStringSize(string
);
854 char* stringUTF8
= (char*)malloc(sizeUTF8
);
855 JSStringGetUTF8CString(string
, stringUTF8
, sizeUTF8
);
856 printf("%s\n", stringUTF8
);
858 JSStringRelease(string
);
861 return JSValueMakeUndefined(ctx
);
864 static JSObjectRef
myConstructor_callAsConstructor(JSContextRef context
, JSObjectRef constructorObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
866 UNUSED_PARAM(constructorObject
);
867 UNUSED_PARAM(exception
);
869 JSObjectRef result
= JSObjectMake(context
, NULL
, NULL
);
870 if (argumentCount
> 0) {
871 JSStringRef value
= JSStringCreateWithUTF8CString("value");
872 JSObjectSetProperty(context
, result
, value
, arguments
[0], kJSPropertyAttributeNone
, NULL
);
873 JSStringRelease(value
);
879 static JSObjectRef
myBadConstructor_callAsConstructor(JSContextRef context
, JSObjectRef constructorObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
881 UNUSED_PARAM(context
);
882 UNUSED_PARAM(constructorObject
);
883 UNUSED_PARAM(argumentCount
);
884 UNUSED_PARAM(arguments
);
885 UNUSED_PARAM(exception
);
891 static void globalObject_initialize(JSContextRef context
, JSObjectRef object
)
893 UNUSED_PARAM(object
);
894 // Ensure that an execution context is passed in
897 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
898 ASSERT(globalObject
);
900 // Ensure that the standard global properties have been set on the global object
901 JSStringRef array
= JSStringCreateWithUTF8CString("Array");
902 JSObjectRef arrayConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, globalObject
, array
, NULL
), NULL
);
903 JSStringRelease(array
);
905 UNUSED_PARAM(arrayConstructor
);
906 ASSERT(arrayConstructor
);
909 static JSValueRef
globalObject_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
911 UNUSED_PARAM(object
);
912 UNUSED_PARAM(propertyName
);
913 UNUSED_PARAM(exception
);
915 return JSValueMakeNumber(ctx
, 3);
918 static bool globalObject_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
920 UNUSED_PARAM(object
);
921 UNUSED_PARAM(propertyName
);
924 *exception
= JSValueMakeNumber(ctx
, 3);
928 static JSValueRef
globalObject_call(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
930 UNUSED_PARAM(function
);
931 UNUSED_PARAM(thisObject
);
932 UNUSED_PARAM(argumentCount
);
933 UNUSED_PARAM(arguments
);
934 UNUSED_PARAM(exception
);
936 return JSValueMakeNumber(ctx
, 3);
939 static JSValueRef
functionGC(JSContextRef context
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
941 UNUSED_PARAM(function
);
942 UNUSED_PARAM(thisObject
);
943 UNUSED_PARAM(argumentCount
);
944 UNUSED_PARAM(arguments
);
945 UNUSED_PARAM(exception
);
946 JSGarbageCollect(context
);
947 return JSValueMakeUndefined(context
);
950 static JSStaticValue globalObject_staticValues
[] = {
951 { "globalStaticValue", globalObject_get
, globalObject_set
, kJSPropertyAttributeNone
},
955 static JSStaticFunction globalObject_staticFunctions
[] = {
956 { "globalStaticFunction", globalObject_call
, kJSPropertyAttributeNone
},
957 { "gc", functionGC
, kJSPropertyAttributeNone
},
961 static char* createStringWithContentsOfFile(const char* fileName
);
963 static void testInitializeFinalize()
965 JSObjectRef o
= JSObjectMake(context
, Derived_class(context
), (void*)1);
967 ASSERT(JSObjectGetPrivate(o
) == (void*)3);
970 static JSValueRef jsNumberValue
= NULL
;
972 static JSObjectRef aHeapRef
= NULL
;
974 static void makeGlobalNumberValue(JSContextRef context
) {
975 JSValueRef v
= JSValueMakeNumber(context
, 420);
976 JSValueProtect(context
, v
);
981 bool assertTrue(bool value
, const char* message
)
985 fprintf(stderr
, "assertTrue failed: '%s'\n", message
);
987 fprintf(stderr
, "assertTrue failed.\n");
993 static bool checkForCycleInPrototypeChain()
996 JSGlobalContextRef context
= JSGlobalContextCreate(0);
997 JSObjectRef object1
= JSObjectMake(context
, /* jsClass */ 0, /* data */ 0);
998 JSObjectRef object2
= JSObjectMake(context
, /* jsClass */ 0, /* data */ 0);
999 JSObjectRef object3
= JSObjectMake(context
, /* jsClass */ 0, /* data */ 0);
1001 JSObjectSetPrototype(context
, object1
, JSValueMakeNull(context
));
1002 ASSERT(JSValueIsNull(context
, JSObjectGetPrototype(context
, object1
)));
1004 // object1 -> object1
1005 JSObjectSetPrototype(context
, object1
, object1
);
1006 result
&= assertTrue(JSValueIsNull(context
, JSObjectGetPrototype(context
, object1
)), "It is possible to assign self as a prototype");
1008 // object1 -> object2 -> object1
1009 JSObjectSetPrototype(context
, object2
, object1
);
1010 ASSERT(JSValueIsStrictEqual(context
, JSObjectGetPrototype(context
, object2
), object1
));
1011 JSObjectSetPrototype(context
, object1
, object2
);
1012 result
&= assertTrue(JSValueIsNull(context
, JSObjectGetPrototype(context
, object1
)), "It is possible to close a prototype chain cycle");
1014 // object1 -> object2 -> object3 -> object1
1015 JSObjectSetPrototype(context
, object2
, object3
);
1016 ASSERT(JSValueIsStrictEqual(context
, JSObjectGetPrototype(context
, object2
), object3
));
1017 JSObjectSetPrototype(context
, object1
, object2
);
1018 ASSERT(JSValueIsStrictEqual(context
, JSObjectGetPrototype(context
, object1
), object2
));
1019 JSObjectSetPrototype(context
, object3
, object1
);
1020 result
&= assertTrue(!JSValueIsStrictEqual(context
, JSObjectGetPrototype(context
, object3
), object1
), "It is possible to close a prototype chain cycle");
1022 JSValueRef exception
;
1023 JSStringRef code
= JSStringCreateWithUTF8CString("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
1024 JSStringRef file
= JSStringCreateWithUTF8CString("");
1025 result
&= assertTrue(!JSEvaluateScript(context
, code
, /* thisObject*/ 0, file
, 1, &exception
)
1026 , "An exception should be thrown");
1028 JSStringRelease(code
);
1029 JSStringRelease(file
);
1030 JSGlobalContextRelease(context
);
1034 static JSValueRef
valueToObjectExceptionCallAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
1036 UNUSED_PARAM(function
);
1037 UNUSED_PARAM(thisObject
);
1038 UNUSED_PARAM(argumentCount
);
1039 UNUSED_PARAM(arguments
);
1040 JSValueRef jsUndefined
= JSValueMakeUndefined(JSContextGetGlobalContext(ctx
));
1041 JSValueToObject(JSContextGetGlobalContext(ctx
), jsUndefined
, exception
);
1043 return JSValueMakeUndefined(ctx
);
1045 static bool valueToObjectExceptionTest()
1047 JSGlobalContextRef testContext
;
1048 JSClassDefinition globalObjectClassDefinition
= kJSClassDefinitionEmpty
;
1049 globalObjectClassDefinition
.initialize
= globalObject_initialize
;
1050 globalObjectClassDefinition
.staticValues
= globalObject_staticValues
;
1051 globalObjectClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
1052 globalObjectClassDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
1053 JSClassRef globalObjectClass
= JSClassCreate(&globalObjectClassDefinition
);
1054 testContext
= JSGlobalContextCreateInGroup(NULL
, globalObjectClass
);
1055 JSObjectRef globalObject
= JSContextGetGlobalObject(testContext
);
1057 JSStringRef valueToObject
= JSStringCreateWithUTF8CString("valueToObject");
1058 JSObjectRef valueToObjectFunction
= JSObjectMakeFunctionWithCallback(testContext
, valueToObject
, valueToObjectExceptionCallAsFunction
);
1059 JSObjectSetProperty(testContext
, globalObject
, valueToObject
, valueToObjectFunction
, kJSPropertyAttributeNone
, NULL
);
1060 JSStringRelease(valueToObject
);
1062 JSStringRef test
= JSStringCreateWithUTF8CString("valueToObject();");
1063 JSEvaluateScript(testContext
, test
, NULL
, NULL
, 1, NULL
);
1065 JSStringRelease(test
);
1066 JSClassRelease(globalObjectClass
);
1067 JSGlobalContextRelease(testContext
);
1072 static bool globalContextNameTest()
1075 JSGlobalContextRef context
= JSGlobalContextCreate(0);
1077 JSStringRef str
= JSGlobalContextCopyName(context
);
1078 result
&= assertTrue(!str
, "Default context name is NULL");
1080 JSStringRef name1
= JSStringCreateWithUTF8CString("name1");
1081 JSStringRef name2
= JSStringCreateWithUTF8CString("name2");
1083 JSGlobalContextSetName(context
, name1
);
1084 JSStringRef fetchName1
= JSGlobalContextCopyName(context
);
1085 JSGlobalContextSetName(context
, name2
);
1086 JSStringRef fetchName2
= JSGlobalContextCopyName(context
);
1087 JSGlobalContextSetName(context
, NULL
);
1088 JSStringRef fetchName3
= JSGlobalContextCopyName(context
);
1090 result
&= assertTrue(JSStringIsEqual(name1
, fetchName1
), "Unexpected Context name");
1091 result
&= assertTrue(JSStringIsEqual(name2
, fetchName2
), "Unexpected Context name");
1092 result
&= assertTrue(!JSStringIsEqual(fetchName1
, fetchName2
), "Unexpected Context name");
1093 result
&= assertTrue(!fetchName3
, "Unexpected Context name");
1095 JSStringRelease(name1
);
1096 JSStringRelease(name2
);
1097 JSStringRelease(fetchName1
);
1098 JSStringRelease(fetchName2
);
1103 static void checkConstnessInJSObjectNames()
1105 JSStaticFunction fun
;
1106 fun
.name
= "something";
1108 val
.name
= "something";
1112 static double currentCPUTime()
1114 mach_msg_type_number_t infoCount
= THREAD_BASIC_INFO_COUNT
;
1115 thread_basic_info_data_t info
;
1117 /* Get thread information */
1118 mach_port_t threadPort
= mach_thread_self();
1119 thread_info(threadPort
, THREAD_BASIC_INFO
, (thread_info_t
)(&info
), &infoCount
);
1120 mach_port_deallocate(mach_task_self(), threadPort
);
1122 double time
= info
.user_time
.seconds
+ info
.user_time
.microseconds
/ 1000000.;
1123 time
+= info
.system_time
.seconds
+ info
.system_time
.microseconds
/ 1000000.;
1128 static JSValueRef
currentCPUTime_callAsFunction(JSContextRef ctx
, JSObjectRef functionObject
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
1130 UNUSED_PARAM(functionObject
);
1131 UNUSED_PARAM(thisObject
);
1132 UNUSED_PARAM(argumentCount
);
1133 UNUSED_PARAM(arguments
);
1134 UNUSED_PARAM(exception
);
1136 ASSERT(JSContextGetGlobalContext(ctx
) == context
);
1137 return JSValueMakeNumber(ctx
, currentCPUTime());
1140 bool shouldTerminateCallbackWasCalled
= false;
1141 static bool shouldTerminateCallback(JSContextRef ctx
, void* context
)
1144 UNUSED_PARAM(context
);
1145 shouldTerminateCallbackWasCalled
= true;
1149 bool cancelTerminateCallbackWasCalled
= false;
1150 static bool cancelTerminateCallback(JSContextRef ctx
, void* context
)
1153 UNUSED_PARAM(context
);
1154 cancelTerminateCallbackWasCalled
= true;
1158 int extendTerminateCallbackCalled
= 0;
1159 static bool extendTerminateCallback(JSContextRef ctx
, void* context
)
1161 UNUSED_PARAM(context
);
1162 extendTerminateCallbackCalled
++;
1163 if (extendTerminateCallbackCalled
== 1) {
1164 JSContextGroupRef contextGroup
= JSContextGetGroup(ctx
);
1165 JSContextGroupSetExecutionTimeLimit(contextGroup
, .200f
, extendTerminateCallback
, 0);
1170 #endif /* OS(DARWIN) */
1173 int main(int argc
, char* argv
[])
1176 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1177 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1178 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1182 #if JSC_OBJC_API_ENABLED
1183 testObjectiveCAPI();
1186 const char *scriptPath
= "testapi.js";
1188 scriptPath
= argv
[1];
1191 // Test garbage collection with a fresh context
1192 context
= JSGlobalContextCreateInGroup(NULL
, NULL
);
1193 TestInitializeFinalize
= true;
1194 testInitializeFinalize();
1195 JSGlobalContextRelease(context
);
1196 TestInitializeFinalize
= false;
1198 ASSERT(Base_didFinalize
);
1200 JSClassDefinition globalObjectClassDefinition
= kJSClassDefinitionEmpty
;
1201 globalObjectClassDefinition
.initialize
= globalObject_initialize
;
1202 globalObjectClassDefinition
.staticValues
= globalObject_staticValues
;
1203 globalObjectClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
1204 globalObjectClassDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
1205 JSClassRef globalObjectClass
= JSClassCreate(&globalObjectClassDefinition
);
1206 context
= JSGlobalContextCreateInGroup(NULL
, globalObjectClass
);
1208 JSContextGroupRef contextGroup
= JSContextGetGroup(context
);
1210 JSGlobalContextRetain(context
);
1211 JSGlobalContextRelease(context
);
1212 ASSERT(JSContextGetGlobalContext(context
) == context
);
1214 JSReportExtraMemoryCost(context
, 0);
1215 JSReportExtraMemoryCost(context
, 1);
1216 JSReportExtraMemoryCost(context
, 1024);
1218 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
1219 ASSERT(JSValueIsObject(context
, globalObject
));
1221 JSValueRef jsUndefined
= JSValueMakeUndefined(context
);
1222 JSValueRef jsNull
= JSValueMakeNull(context
);
1223 JSValueRef jsTrue
= JSValueMakeBoolean(context
, true);
1224 JSValueRef jsFalse
= JSValueMakeBoolean(context
, false);
1225 JSValueRef jsZero
= JSValueMakeNumber(context
, 0);
1226 JSValueRef jsOne
= JSValueMakeNumber(context
, 1);
1227 JSValueRef jsOneThird
= JSValueMakeNumber(context
, 1.0 / 3.0);
1228 JSObjectRef jsObjectNoProto
= JSObjectMake(context
, NULL
, NULL
);
1229 JSObjectSetPrototype(context
, jsObjectNoProto
, JSValueMakeNull(context
));
1231 JSObjectSetPrivate(globalObject
, (void*)123);
1232 if (JSObjectGetPrivate(globalObject
) != (void*)123) {
1233 printf("FAIL: Didn't return private data when set by JSObjectSetPrivate().\n");
1236 printf("PASS: returned private data when set by JSObjectSetPrivate().\n");
1238 // FIXME: test funny utf8 characters
1239 JSStringRef jsEmptyIString
= JSStringCreateWithUTF8CString("");
1240 JSValueRef jsEmptyString
= JSValueMakeString(context
, jsEmptyIString
);
1242 JSStringRef jsOneIString
= JSStringCreateWithUTF8CString("1");
1243 JSValueRef jsOneString
= JSValueMakeString(context
, jsOneIString
);
1245 UniChar singleUniChar
= 65; // Capital A
1246 CFMutableStringRef cfString
=
1247 CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault
,
1253 JSStringRef jsCFIString
= JSStringCreateWithCFString(cfString
);
1254 JSValueRef jsCFString
= JSValueMakeString(context
, jsCFIString
);
1256 CFStringRef cfEmptyString
= CFStringCreateWithCString(kCFAllocatorDefault
, "", kCFStringEncodingUTF8
);
1258 JSStringRef jsCFEmptyIString
= JSStringCreateWithCFString(cfEmptyString
);
1259 JSValueRef jsCFEmptyString
= JSValueMakeString(context
, jsCFEmptyIString
);
1261 CFIndex cfStringLength
= CFStringGetLength(cfString
);
1262 UniChar
* buffer
= (UniChar
*)malloc(cfStringLength
* sizeof(UniChar
));
1263 CFStringGetCharacters(cfString
,
1264 CFRangeMake(0, cfStringLength
),
1266 JSStringRef jsCFIStringWithCharacters
= JSStringCreateWithCharacters((JSChar
*)buffer
, cfStringLength
);
1267 JSValueRef jsCFStringWithCharacters
= JSValueMakeString(context
, jsCFIStringWithCharacters
);
1269 JSStringRef jsCFEmptyIStringWithCharacters
= JSStringCreateWithCharacters((JSChar
*)buffer
, CFStringGetLength(cfEmptyString
));
1271 JSValueRef jsCFEmptyStringWithCharacters
= JSValueMakeString(context
, jsCFEmptyIStringWithCharacters
);
1273 JSChar constantString
[] = { 'H', 'e', 'l', 'l', 'o', };
1274 JSStringRef constantStringRef
= JSStringCreateWithCharactersNoCopy(constantString
, sizeof(constantString
) / sizeof(constantString
[0]));
1275 ASSERT(JSStringGetCharactersPtr(constantStringRef
) == constantString
);
1276 JSStringRelease(constantStringRef
);
1278 ASSERT(JSValueGetType(context
, NULL
) == kJSTypeNull
);
1279 ASSERT(JSValueGetType(context
, jsUndefined
) == kJSTypeUndefined
);
1280 ASSERT(JSValueGetType(context
, jsNull
) == kJSTypeNull
);
1281 ASSERT(JSValueGetType(context
, jsTrue
) == kJSTypeBoolean
);
1282 ASSERT(JSValueGetType(context
, jsFalse
) == kJSTypeBoolean
);
1283 ASSERT(JSValueGetType(context
, jsZero
) == kJSTypeNumber
);
1284 ASSERT(JSValueGetType(context
, jsOne
) == kJSTypeNumber
);
1285 ASSERT(JSValueGetType(context
, jsOneThird
) == kJSTypeNumber
);
1286 ASSERT(JSValueGetType(context
, jsEmptyString
) == kJSTypeString
);
1287 ASSERT(JSValueGetType(context
, jsOneString
) == kJSTypeString
);
1288 ASSERT(JSValueGetType(context
, jsCFString
) == kJSTypeString
);
1289 ASSERT(JSValueGetType(context
, jsCFStringWithCharacters
) == kJSTypeString
);
1290 ASSERT(JSValueGetType(context
, jsCFEmptyString
) == kJSTypeString
);
1291 ASSERT(JSValueGetType(context
, jsCFEmptyStringWithCharacters
) == kJSTypeString
);
1293 ASSERT(!JSValueIsBoolean(context
, NULL
));
1294 ASSERT(!JSValueIsObject(context
, NULL
));
1295 ASSERT(!JSValueIsString(context
, NULL
));
1296 ASSERT(!JSValueIsNumber(context
, NULL
));
1297 ASSERT(!JSValueIsUndefined(context
, NULL
));
1298 ASSERT(JSValueIsNull(context
, NULL
));
1299 ASSERT(!JSObjectCallAsFunction(context
, NULL
, NULL
, 0, NULL
, NULL
));
1300 ASSERT(!JSObjectCallAsConstructor(context
, NULL
, 0, NULL
, NULL
));
1301 ASSERT(!JSObjectIsConstructor(context
, NULL
));
1302 ASSERT(!JSObjectIsFunction(context
, NULL
));
1304 JSStringRef nullString
= JSStringCreateWithUTF8CString(0);
1305 const JSChar
* characters
= JSStringGetCharactersPtr(nullString
);
1307 printf("FAIL: Didn't return null when accessing character pointer of a null String.\n");
1310 printf("PASS: returned null when accessing character pointer of a null String.\n");
1312 JSStringRef emptyString
= JSStringCreateWithCFString(CFSTR(""));
1313 characters
= JSStringGetCharactersPtr(emptyString
);
1315 printf("FAIL: Returned null when accessing character pointer of an empty String.\n");
1318 printf("PASS: returned empty when accessing character pointer of an empty String.\n");
1320 size_t length
= JSStringGetLength(nullString
);
1322 printf("FAIL: Didn't return 0 length for null String.\n");
1325 printf("PASS: returned 0 length for null String.\n");
1326 JSStringRelease(nullString
);
1328 length
= JSStringGetLength(emptyString
);
1330 printf("FAIL: Didn't return 0 length for empty String.\n");
1333 printf("PASS: returned 0 length for empty String.\n");
1334 JSStringRelease(emptyString
);
1336 JSObjectRef propertyCatchalls
= JSObjectMake(context
, PropertyCatchalls_class(context
), NULL
);
1337 JSStringRef propertyCatchallsString
= JSStringCreateWithUTF8CString("PropertyCatchalls");
1338 JSObjectSetProperty(context
, globalObject
, propertyCatchallsString
, propertyCatchalls
, kJSPropertyAttributeNone
, NULL
);
1339 JSStringRelease(propertyCatchallsString
);
1341 JSObjectRef myObject
= JSObjectMake(context
, MyObject_class(context
), NULL
);
1342 JSStringRef myObjectIString
= JSStringCreateWithUTF8CString("MyObject");
1343 JSObjectSetProperty(context
, globalObject
, myObjectIString
, myObject
, kJSPropertyAttributeNone
, NULL
);
1344 JSStringRelease(myObjectIString
);
1346 JSObjectRef EvilExceptionObject
= JSObjectMake(context
, EvilExceptionObject_class(context
), NULL
);
1347 JSStringRef EvilExceptionObjectIString
= JSStringCreateWithUTF8CString("EvilExceptionObject");
1348 JSObjectSetProperty(context
, globalObject
, EvilExceptionObjectIString
, EvilExceptionObject
, kJSPropertyAttributeNone
, NULL
);
1349 JSStringRelease(EvilExceptionObjectIString
);
1351 JSObjectRef EmptyObject
= JSObjectMake(context
, EmptyObject_class(context
), NULL
);
1352 JSStringRef EmptyObjectIString
= JSStringCreateWithUTF8CString("EmptyObject");
1353 JSObjectSetProperty(context
, globalObject
, EmptyObjectIString
, EmptyObject
, kJSPropertyAttributeNone
, NULL
);
1354 JSStringRelease(EmptyObjectIString
);
1356 JSStringRef lengthStr
= JSStringCreateWithUTF8CString("length");
1357 JSObjectRef aStackRef
= JSObjectMakeArray(context
, 0, 0, 0);
1358 aHeapRef
= aStackRef
;
1359 JSObjectSetProperty(context
, aHeapRef
, lengthStr
, JSValueMakeNumber(context
, 10), 0, 0);
1360 JSStringRef privatePropertyName
= JSStringCreateWithUTF8CString("privateProperty");
1361 if (!JSObjectSetPrivateProperty(context
, myObject
, privatePropertyName
, aHeapRef
)) {
1362 printf("FAIL: Could not set private property.\n");
1365 printf("PASS: Set private property.\n");
1367 if (JSObjectSetPrivateProperty(context
, aHeapRef
, privatePropertyName
, aHeapRef
)) {
1368 printf("FAIL: JSObjectSetPrivateProperty should fail on non-API objects.\n");
1371 printf("PASS: Did not allow JSObjectSetPrivateProperty on a non-API object.\n");
1372 if (JSObjectGetPrivateProperty(context
, myObject
, privatePropertyName
) != aHeapRef
) {
1373 printf("FAIL: Could not retrieve private property.\n");
1376 printf("PASS: Retrieved private property.\n");
1377 if (JSObjectGetPrivateProperty(context
, aHeapRef
, privatePropertyName
)) {
1378 printf("FAIL: JSObjectGetPrivateProperty should return NULL when called on a non-API object.\n");
1381 printf("PASS: JSObjectGetPrivateProperty return NULL.\n");
1383 if (JSObjectGetProperty(context
, myObject
, privatePropertyName
, 0) == aHeapRef
) {
1384 printf("FAIL: Accessed private property through ordinary property lookup.\n");
1387 printf("PASS: Cannot access private property through ordinary property lookup.\n");
1389 JSGarbageCollect(context
);
1391 for (int i
= 0; i
< 10000; i
++)
1392 JSObjectMake(context
, 0, 0);
1394 aHeapRef
= JSValueToObject(context
, JSObjectGetPrivateProperty(context
, myObject
, privatePropertyName
), 0);
1395 if (JSValueToNumber(context
, JSObjectGetProperty(context
, aHeapRef
, lengthStr
, 0), 0) != 10) {
1396 printf("FAIL: Private property has been collected.\n");
1399 printf("PASS: Private property does not appear to have been collected.\n");
1400 JSStringRelease(lengthStr
);
1402 if (!JSObjectSetPrivateProperty(context
, myObject
, privatePropertyName
, 0)) {
1403 printf("FAIL: Could not set private property to NULL.\n");
1406 printf("PASS: Set private property to NULL.\n");
1407 if (JSObjectGetPrivateProperty(context
, myObject
, privatePropertyName
)) {
1408 printf("FAIL: Could not retrieve private property.\n");
1411 printf("PASS: Retrieved private property.\n");
1413 JSStringRef nullJSON
= JSStringCreateWithUTF8CString(0);
1414 JSValueRef nullJSONObject
= JSValueMakeFromJSONString(context
, nullJSON
);
1415 if (nullJSONObject
) {
1416 printf("FAIL: Did not parse null String as JSON correctly\n");
1419 printf("PASS: Parsed null String as JSON correctly.\n");
1420 JSStringRelease(nullJSON
);
1422 JSStringRef validJSON
= JSStringCreateWithUTF8CString("{\"aProperty\":true}");
1423 JSValueRef jsonObject
= JSValueMakeFromJSONString(context
, validJSON
);
1424 JSStringRelease(validJSON
);
1425 if (!JSValueIsObject(context
, jsonObject
)) {
1426 printf("FAIL: Did not parse valid JSON correctly\n");
1429 printf("PASS: Parsed valid JSON string.\n");
1430 JSStringRef propertyName
= JSStringCreateWithUTF8CString("aProperty");
1431 assertEqualsAsBoolean(JSObjectGetProperty(context
, JSValueToObject(context
, jsonObject
, 0), propertyName
, 0), true);
1432 JSStringRelease(propertyName
);
1433 JSStringRef invalidJSON
= JSStringCreateWithUTF8CString("fail!");
1434 if (JSValueMakeFromJSONString(context
, invalidJSON
)) {
1435 printf("FAIL: Should return null for invalid JSON data\n");
1438 printf("PASS: Correctly returned null for invalid JSON data.\n");
1439 JSValueRef exception
;
1440 JSStringRef str
= JSValueCreateJSONString(context
, jsonObject
, 0, 0);
1441 if (!JSStringIsEqualToUTF8CString(str
, "{\"aProperty\":true}")) {
1442 printf("FAIL: Did not correctly serialise with indent of 0.\n");
1445 printf("PASS: Correctly serialised with indent of 0.\n");
1446 JSStringRelease(str
);
1448 str
= JSValueCreateJSONString(context
, jsonObject
, 4, 0);
1449 if (!JSStringIsEqualToUTF8CString(str
, "{\n \"aProperty\": true\n}")) {
1450 printf("FAIL: Did not correctly serialise with indent of 4.\n");
1453 printf("PASS: Correctly serialised with indent of 4.\n");
1454 JSStringRelease(str
);
1455 JSStringRef src
= JSStringCreateWithUTF8CString("({get a(){ throw '';}})");
1456 JSValueRef unstringifiableObj
= JSEvaluateScript(context
, src
, NULL
, NULL
, 1, NULL
);
1458 str
= JSValueCreateJSONString(context
, unstringifiableObj
, 4, 0);
1460 printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
1461 JSStringRelease(str
);
1464 printf("PASS: returned null when attempting to serialize unserializable value.\n");
1466 str
= JSValueCreateJSONString(context
, unstringifiableObj
, 4, &exception
);
1468 printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
1469 JSStringRelease(str
);
1472 printf("PASS: returned null when attempting to serialize unserializable value.\n");
1474 printf("FAIL: Did not set exception on serialisation error\n");
1477 printf("PASS: set exception on serialisation error\n");
1478 // Conversions that throw exceptions
1480 ASSERT(NULL
== JSValueToObject(context
, jsNull
, &exception
));
1484 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
1485 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
1486 // After that's resolved, we can remove these casts
1487 ASSERT(isnan((float)JSValueToNumber(context
, jsObjectNoProto
, &exception
)));
1491 ASSERT(!JSValueToStringCopy(context
, jsObjectNoProto
, &exception
));
1494 ASSERT(JSValueToBoolean(context
, myObject
));
1497 ASSERT(!JSValueIsEqual(context
, jsObjectNoProto
, JSValueMakeNumber(context
, 1), &exception
));
1501 JSObjectGetPropertyAtIndex(context
, myObject
, 0, &exception
);
1502 ASSERT(1 == JSValueToNumber(context
, exception
, NULL
));
1504 assertEqualsAsBoolean(jsUndefined
, false);
1505 assertEqualsAsBoolean(jsNull
, false);
1506 assertEqualsAsBoolean(jsTrue
, true);
1507 assertEqualsAsBoolean(jsFalse
, false);
1508 assertEqualsAsBoolean(jsZero
, false);
1509 assertEqualsAsBoolean(jsOne
, true);
1510 assertEqualsAsBoolean(jsOneThird
, true);
1511 assertEqualsAsBoolean(jsEmptyString
, false);
1512 assertEqualsAsBoolean(jsOneString
, true);
1513 assertEqualsAsBoolean(jsCFString
, true);
1514 assertEqualsAsBoolean(jsCFStringWithCharacters
, true);
1515 assertEqualsAsBoolean(jsCFEmptyString
, false);
1516 assertEqualsAsBoolean(jsCFEmptyStringWithCharacters
, false);
1518 assertEqualsAsNumber(jsUndefined
, nan(""));
1519 assertEqualsAsNumber(jsNull
, 0);
1520 assertEqualsAsNumber(jsTrue
, 1);
1521 assertEqualsAsNumber(jsFalse
, 0);
1522 assertEqualsAsNumber(jsZero
, 0);
1523 assertEqualsAsNumber(jsOne
, 1);
1524 assertEqualsAsNumber(jsOneThird
, 1.0 / 3.0);
1525 assertEqualsAsNumber(jsEmptyString
, 0);
1526 assertEqualsAsNumber(jsOneString
, 1);
1527 assertEqualsAsNumber(jsCFString
, nan(""));
1528 assertEqualsAsNumber(jsCFStringWithCharacters
, nan(""));
1529 assertEqualsAsNumber(jsCFEmptyString
, 0);
1530 assertEqualsAsNumber(jsCFEmptyStringWithCharacters
, 0);
1531 ASSERT(sizeof(JSChar
) == sizeof(UniChar
));
1533 assertEqualsAsCharactersPtr(jsUndefined
, "undefined");
1534 assertEqualsAsCharactersPtr(jsNull
, "null");
1535 assertEqualsAsCharactersPtr(jsTrue
, "true");
1536 assertEqualsAsCharactersPtr(jsFalse
, "false");
1537 assertEqualsAsCharactersPtr(jsZero
, "0");
1538 assertEqualsAsCharactersPtr(jsOne
, "1");
1539 assertEqualsAsCharactersPtr(jsOneThird
, "0.3333333333333333");
1540 assertEqualsAsCharactersPtr(jsEmptyString
, "");
1541 assertEqualsAsCharactersPtr(jsOneString
, "1");
1542 assertEqualsAsCharactersPtr(jsCFString
, "A");
1543 assertEqualsAsCharactersPtr(jsCFStringWithCharacters
, "A");
1544 assertEqualsAsCharactersPtr(jsCFEmptyString
, "");
1545 assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters
, "");
1547 assertEqualsAsUTF8String(jsUndefined
, "undefined");
1548 assertEqualsAsUTF8String(jsNull
, "null");
1549 assertEqualsAsUTF8String(jsTrue
, "true");
1550 assertEqualsAsUTF8String(jsFalse
, "false");
1551 assertEqualsAsUTF8String(jsZero
, "0");
1552 assertEqualsAsUTF8String(jsOne
, "1");
1553 assertEqualsAsUTF8String(jsOneThird
, "0.3333333333333333");
1554 assertEqualsAsUTF8String(jsEmptyString
, "");
1555 assertEqualsAsUTF8String(jsOneString
, "1");
1556 assertEqualsAsUTF8String(jsCFString
, "A");
1557 assertEqualsAsUTF8String(jsCFStringWithCharacters
, "A");
1558 assertEqualsAsUTF8String(jsCFEmptyString
, "");
1559 assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters
, "");
1561 checkConstnessInJSObjectNames();
1563 ASSERT(JSValueIsStrictEqual(context
, jsTrue
, jsTrue
));
1564 ASSERT(!JSValueIsStrictEqual(context
, jsOne
, jsOneString
));
1566 ASSERT(JSValueIsEqual(context
, jsOne
, jsOneString
, NULL
));
1567 ASSERT(!JSValueIsEqual(context
, jsTrue
, jsFalse
, NULL
));
1569 CFStringRef cfJSString
= JSStringCopyCFString(kCFAllocatorDefault
, jsCFIString
);
1570 CFStringRef cfJSEmptyString
= JSStringCopyCFString(kCFAllocatorDefault
, jsCFEmptyIString
);
1571 ASSERT(CFEqual(cfJSString
, cfString
));
1572 ASSERT(CFEqual(cfJSEmptyString
, cfEmptyString
));
1573 CFRelease(cfJSString
);
1574 CFRelease(cfJSEmptyString
);
1576 CFRelease(cfString
);
1577 CFRelease(cfEmptyString
);
1579 jsGlobalValue
= JSObjectMake(context
, NULL
, NULL
);
1580 makeGlobalNumberValue(context
);
1581 JSValueProtect(context
, jsGlobalValue
);
1582 JSGarbageCollect(context
);
1583 ASSERT(JSValueIsObject(context
, jsGlobalValue
));
1584 JSValueUnprotect(context
, jsGlobalValue
);
1585 JSValueUnprotect(context
, jsNumberValue
);
1587 JSStringRef goodSyntax
= JSStringCreateWithUTF8CString("x = 1;");
1588 const char* badSyntaxConstant
= "x := 1;";
1589 JSStringRef badSyntax
= JSStringCreateWithUTF8CString(badSyntaxConstant
);
1590 ASSERT(JSCheckScriptSyntax(context
, goodSyntax
, NULL
, 0, NULL
));
1591 ASSERT(!JSCheckScriptSyntax(context
, badSyntax
, NULL
, 0, NULL
));
1592 ASSERT(!JSScriptCreateFromString(contextGroup
, 0, 0, badSyntax
, 0, 0));
1593 ASSERT(!JSScriptCreateReferencingImmortalASCIIText(contextGroup
, 0, 0, badSyntaxConstant
, strlen(badSyntaxConstant
), 0, 0));
1600 result
= JSEvaluateScript(context
, goodSyntax
, NULL
, NULL
, 1, NULL
);
1602 ASSERT(JSValueIsEqual(context
, result
, jsOne
, NULL
));
1605 result
= JSEvaluateScript(context
, badSyntax
, NULL
, NULL
, 1, &exception
);
1607 ASSERT(JSValueIsObject(context
, exception
));
1609 JSStringRef array
= JSStringCreateWithUTF8CString("Array");
1610 JSObjectRef arrayConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, globalObject
, array
, NULL
), NULL
);
1611 JSStringRelease(array
);
1612 result
= JSObjectCallAsConstructor(context
, arrayConstructor
, 0, NULL
, NULL
);
1614 ASSERT(JSValueIsObject(context
, result
));
1615 ASSERT(JSValueIsInstanceOfConstructor(context
, result
, arrayConstructor
, NULL
));
1616 ASSERT(!JSValueIsInstanceOfConstructor(context
, JSValueMakeNull(context
), arrayConstructor
, NULL
));
1618 o
= JSValueToObject(context
, result
, NULL
);
1620 ASSERT(JSValueIsUndefined(context
, JSObjectGetPropertyAtIndex(context
, o
, 0, &exception
)));
1623 JSObjectSetPropertyAtIndex(context
, o
, 0, JSValueMakeNumber(context
, 1), &exception
);
1627 ASSERT(1 == JSValueToNumber(context
, JSObjectGetPropertyAtIndex(context
, o
, 0, &exception
), &exception
));
1630 JSStringRef functionBody
;
1631 JSObjectRef function
;
1634 functionBody
= JSStringCreateWithUTF8CString("rreturn Array;");
1635 JSStringRef line
= JSStringCreateWithUTF8CString("line");
1636 ASSERT(!JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
));
1637 ASSERT(JSValueIsObject(context
, exception
));
1638 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), line
, NULL
);
1639 assertEqualsAsNumber(v
, 1);
1640 JSStringRelease(functionBody
);
1641 JSStringRelease(line
);
1644 functionBody
= JSStringCreateWithUTF8CString("rreturn Array;");
1645 line
= JSStringCreateWithUTF8CString("line");
1646 ASSERT(!JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, -42, &exception
));
1647 ASSERT(JSValueIsObject(context
, exception
));
1648 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), line
, NULL
);
1649 assertEqualsAsNumber(v
, 1);
1650 JSStringRelease(functionBody
);
1651 JSStringRelease(line
);
1654 functionBody
= JSStringCreateWithUTF8CString("// Line one.\nrreturn Array;");
1655 line
= JSStringCreateWithUTF8CString("line");
1656 ASSERT(!JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
));
1657 ASSERT(JSValueIsObject(context
, exception
));
1658 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), line
, NULL
);
1659 assertEqualsAsNumber(v
, 2);
1660 JSStringRelease(functionBody
);
1661 JSStringRelease(line
);
1664 functionBody
= JSStringCreateWithUTF8CString("return Array;");
1665 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
);
1666 JSStringRelease(functionBody
);
1668 ASSERT(JSObjectIsFunction(context
, function
));
1669 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1671 ASSERT(JSValueIsEqual(context
, v
, arrayConstructor
, NULL
));
1674 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, jsEmptyIString
, NULL
, 0, &exception
);
1676 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, &exception
);
1677 ASSERT(v
&& !exception
);
1678 ASSERT(JSValueIsUndefined(context
, v
));
1682 JSStringRef foo
= JSStringCreateWithUTF8CString("foo");
1683 JSStringRef argumentNames
[] = { foo
};
1684 functionBody
= JSStringCreateWithUTF8CString("return foo;");
1685 function
= JSObjectMakeFunction(context
, foo
, 1, argumentNames
, functionBody
, NULL
, 1, &exception
);
1686 ASSERT(function
&& !exception
);
1687 JSValueRef arguments
[] = { JSValueMakeNumber(context
, 2) };
1688 JSObjectCallAsFunction(context
, function
, NULL
, 1, arguments
, &exception
);
1689 JSStringRelease(foo
);
1690 JSStringRelease(functionBody
);
1692 string
= JSValueToStringCopy(context
, function
, NULL
);
1693 assertEqualsAsUTF8String(JSValueMakeString(context
, string
), "function foo(foo) { return foo;\n}");
1694 JSStringRelease(string
);
1696 JSStringRef print
= JSStringCreateWithUTF8CString("print");
1697 JSObjectRef printFunction
= JSObjectMakeFunctionWithCallback(context
, print
, print_callAsFunction
);
1698 JSObjectSetProperty(context
, globalObject
, print
, printFunction
, kJSPropertyAttributeNone
, NULL
);
1699 JSStringRelease(print
);
1701 ASSERT(!JSObjectSetPrivate(printFunction
, (void*)1));
1702 ASSERT(!JSObjectGetPrivate(printFunction
));
1704 JSStringRef myConstructorIString
= JSStringCreateWithUTF8CString("MyConstructor");
1705 JSObjectRef myConstructor
= JSObjectMakeConstructor(context
, NULL
, myConstructor_callAsConstructor
);
1706 JSObjectSetProperty(context
, globalObject
, myConstructorIString
, myConstructor
, kJSPropertyAttributeNone
, NULL
);
1707 JSStringRelease(myConstructorIString
);
1709 JSStringRef myBadConstructorIString
= JSStringCreateWithUTF8CString("MyBadConstructor");
1710 JSObjectRef myBadConstructor
= JSObjectMakeConstructor(context
, NULL
, myBadConstructor_callAsConstructor
);
1711 JSObjectSetProperty(context
, globalObject
, myBadConstructorIString
, myBadConstructor
, kJSPropertyAttributeNone
, NULL
);
1712 JSStringRelease(myBadConstructorIString
);
1714 ASSERT(!JSObjectSetPrivate(myConstructor
, (void*)1));
1715 ASSERT(!JSObjectGetPrivate(myConstructor
));
1717 string
= JSStringCreateWithUTF8CString("Base");
1718 JSObjectRef baseConstructor
= JSObjectMakeConstructor(context
, Base_class(context
), NULL
);
1719 JSObjectSetProperty(context
, globalObject
, string
, baseConstructor
, kJSPropertyAttributeNone
, NULL
);
1720 JSStringRelease(string
);
1722 string
= JSStringCreateWithUTF8CString("Derived");
1723 JSObjectRef derivedConstructor
= JSObjectMakeConstructor(context
, Derived_class(context
), NULL
);
1724 JSObjectSetProperty(context
, globalObject
, string
, derivedConstructor
, kJSPropertyAttributeNone
, NULL
);
1725 JSStringRelease(string
);
1727 string
= JSStringCreateWithUTF8CString("Derived2");
1728 JSObjectRef derived2Constructor
= JSObjectMakeConstructor(context
, Derived2_class(context
), NULL
);
1729 JSObjectSetProperty(context
, globalObject
, string
, derived2Constructor
, kJSPropertyAttributeNone
, NULL
);
1730 JSStringRelease(string
);
1732 o
= JSObjectMake(context
, NULL
, NULL
);
1733 JSObjectSetProperty(context
, o
, jsOneIString
, JSValueMakeNumber(context
, 1), kJSPropertyAttributeNone
, NULL
);
1734 JSObjectSetProperty(context
, o
, jsCFIString
, JSValueMakeNumber(context
, 1), kJSPropertyAttributeDontEnum
, NULL
);
1735 JSPropertyNameArrayRef nameArray
= JSObjectCopyPropertyNames(context
, o
);
1736 size_t expectedCount
= JSPropertyNameArrayGetCount(nameArray
);
1738 for (count
= 0; count
< expectedCount
; ++count
)
1739 JSPropertyNameArrayGetNameAtIndex(nameArray
, count
);
1740 JSPropertyNameArrayRelease(nameArray
);
1741 ASSERT(count
== 1); // jsCFString should not be enumerated
1743 JSValueRef argumentsArrayValues
[] = { JSValueMakeNumber(context
, 10), JSValueMakeNumber(context
, 20) };
1744 o
= JSObjectMakeArray(context
, sizeof(argumentsArrayValues
) / sizeof(JSValueRef
), argumentsArrayValues
, NULL
);
1745 string
= JSStringCreateWithUTF8CString("length");
1746 v
= JSObjectGetProperty(context
, o
, string
, NULL
);
1747 assertEqualsAsNumber(v
, 2);
1748 v
= JSObjectGetPropertyAtIndex(context
, o
, 0, NULL
);
1749 assertEqualsAsNumber(v
, 10);
1750 v
= JSObjectGetPropertyAtIndex(context
, o
, 1, NULL
);
1751 assertEqualsAsNumber(v
, 20);
1753 o
= JSObjectMakeArray(context
, 0, NULL
, NULL
);
1754 v
= JSObjectGetProperty(context
, o
, string
, NULL
);
1755 assertEqualsAsNumber(v
, 0);
1756 JSStringRelease(string
);
1758 JSValueRef argumentsDateValues
[] = { JSValueMakeNumber(context
, 0) };
1759 o
= JSObjectMakeDate(context
, 1, argumentsDateValues
, NULL
);
1760 if (timeZoneIsPST())
1761 assertEqualsAsUTF8String(o
, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
1763 string
= JSStringCreateWithUTF8CString("an error message");
1764 JSValueRef argumentsErrorValues
[] = { JSValueMakeString(context
, string
) };
1765 o
= JSObjectMakeError(context
, 1, argumentsErrorValues
, NULL
);
1766 assertEqualsAsUTF8String(o
, "Error: an error message");
1767 JSStringRelease(string
);
1769 string
= JSStringCreateWithUTF8CString("foo");
1770 JSStringRef string2
= JSStringCreateWithUTF8CString("gi");
1771 JSValueRef argumentsRegExpValues
[] = { JSValueMakeString(context
, string
), JSValueMakeString(context
, string2
) };
1772 o
= JSObjectMakeRegExp(context
, 2, argumentsRegExpValues
, NULL
);
1773 assertEqualsAsUTF8String(o
, "/foo/gi");
1774 JSStringRelease(string
);
1775 JSStringRelease(string2
);
1777 JSClassDefinition nullDefinition
= kJSClassDefinitionEmpty
;
1778 nullDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
1779 JSClassRef nullClass
= JSClassCreate(&nullDefinition
);
1780 JSClassRelease(nullClass
);
1782 nullDefinition
= kJSClassDefinitionEmpty
;
1783 nullClass
= JSClassCreate(&nullDefinition
);
1784 JSClassRelease(nullClass
);
1786 functionBody
= JSStringCreateWithUTF8CString("return this;");
1787 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, NULL
);
1788 JSStringRelease(functionBody
);
1789 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1790 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1791 v
= JSObjectCallAsFunction(context
, function
, o
, 0, NULL
, NULL
);
1792 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1794 functionBody
= JSStringCreateWithUTF8CString("return eval(\"this\");");
1795 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, NULL
);
1796 JSStringRelease(functionBody
);
1797 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1798 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1799 v
= JSObjectCallAsFunction(context
, function
, o
, 0, NULL
, NULL
);
1800 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1802 const char* thisScript
= "this;";
1803 JSStringRef script
= JSStringCreateWithUTF8CString(thisScript
);
1804 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1805 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1806 v
= JSEvaluateScript(context
, script
, o
, NULL
, 1, NULL
);
1807 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1808 JSStringRelease(script
);
1810 JSScriptRef scriptObject
= JSScriptCreateReferencingImmortalASCIIText(contextGroup
, 0, 0, thisScript
, strlen(thisScript
), 0, 0);
1811 v
= JSScriptEvaluate(context
, scriptObject
, NULL
, NULL
);
1812 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1813 v
= JSScriptEvaluate(context
, scriptObject
, o
, NULL
);
1814 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1815 JSScriptRelease(scriptObject
);
1817 script
= JSStringCreateWithUTF8CString("eval(this);");
1818 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1819 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1820 v
= JSEvaluateScript(context
, script
, o
, NULL
, 1, NULL
);
1821 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1822 JSStringRelease(script
);
1825 script
= JSStringCreateWithUTF8CString("rreturn Array;");
1826 JSStringRef sourceURL
= JSStringCreateWithUTF8CString("file:///foo/bar.js");
1827 JSStringRef sourceURLKey
= JSStringCreateWithUTF8CString("sourceURL");
1828 JSEvaluateScript(context
, script
, NULL
, sourceURL
, 1, &exception
);
1830 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), sourceURLKey
, NULL
);
1831 assertEqualsAsUTF8String(v
, "file:///foo/bar.js");
1832 JSStringRelease(script
);
1833 JSStringRelease(sourceURL
);
1834 JSStringRelease(sourceURLKey
);
1836 // Verify that creating a constructor for a class with no static functions does not trigger
1837 // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
1838 nullDefinition
= kJSClassDefinitionEmpty
;
1839 nullClass
= JSClassCreate(&nullDefinition
);
1840 JSObjectMakeConstructor(context
, nullClass
, 0);
1841 JSClassRelease(nullClass
);
1843 char* scriptUTF8
= createStringWithContentsOfFile(scriptPath
);
1845 printf("FAIL: Test script could not be loaded.\n");
1848 JSStringRef url
= JSStringCreateWithUTF8CString(scriptPath
);
1849 JSStringRef script
= JSStringCreateWithUTF8CString(scriptUTF8
);
1850 JSStringRef errorMessage
= 0;
1852 JSScriptRef scriptObject
= JSScriptCreateFromString(contextGroup
, url
, 1, script
, &errorMessage
, &errorLine
);
1853 ASSERT((!scriptObject
) != (!errorMessage
));
1854 if (!scriptObject
) {
1855 printf("FAIL: Test script did not parse\n\t%s:%d\n\t", scriptPath
, errorLine
);
1856 CFStringRef errorCF
= JSStringCopyCFString(kCFAllocatorDefault
, errorMessage
);
1859 JSStringRelease(errorMessage
);
1863 JSStringRelease(script
);
1865 result
= scriptObject
? JSScriptEvaluate(context
, scriptObject
, 0, &exception
) : 0;
1866 if (result
&& JSValueIsUndefined(context
, result
))
1867 printf("PASS: Test script executed successfully.\n");
1869 printf("FAIL: Test script returned unexpected value:\n");
1870 JSStringRef exceptionIString
= JSValueToStringCopy(context
, exception
, NULL
);
1871 CFStringRef exceptionCF
= JSStringCopyCFString(kCFAllocatorDefault
, exceptionIString
);
1872 CFShow(exceptionCF
);
1873 CFRelease(exceptionCF
);
1874 JSStringRelease(exceptionIString
);
1877 JSScriptRelease(scriptObject
);
1882 JSStringRef currentCPUTimeStr
= JSStringCreateWithUTF8CString("currentCPUTime");
1883 JSObjectRef currentCPUTimeFunction
= JSObjectMakeFunctionWithCallback(context
, currentCPUTimeStr
, currentCPUTime_callAsFunction
);
1884 JSObjectSetProperty(context
, globalObject
, currentCPUTimeStr
, currentCPUTimeFunction
, kJSPropertyAttributeNone
, NULL
);
1885 JSStringRelease(currentCPUTimeStr
);
1887 /* Test script timeout: */
1888 JSContextGroupSetExecutionTimeLimit(contextGroup
, .10f
, shouldTerminateCallback
, 0);
1890 const char* loopForeverScript
= "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
1891 JSStringRef script
= JSStringCreateWithUTF8CString(loopForeverScript
);
1895 shouldTerminateCallbackWasCalled
= false;
1896 startTime
= currentCPUTime();
1897 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, &exception
);
1898 endTime
= currentCPUTime();
1900 if (((endTime
- startTime
) < .150f
) && shouldTerminateCallbackWasCalled
)
1901 printf("PASS: script timed out as expected.\n");
1903 if (!((endTime
- startTime
) < .150f
))
1904 printf("FAIL: script did not timed out as expected.\n");
1905 if (!shouldTerminateCallbackWasCalled
)
1906 printf("FAIL: script timeout callback was not called.\n");
1911 printf("FAIL: TerminatedExecutionException was not thrown.\n");
1916 /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */
1917 JSContextGroupSetExecutionTimeLimit(contextGroup
, 0.10f
, shouldTerminateCallback
, 0);
1919 const char* loopForeverScript
= "var startTime = currentCPUTime(); try { while (true) { if (currentCPUTime() - startTime > .150) break; } } catch(e) { }";
1920 JSStringRef script
= JSStringCreateWithUTF8CString(loopForeverScript
);
1924 shouldTerminateCallbackWasCalled
= false;
1925 startTime
= currentCPUTime();
1926 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, &exception
);
1927 endTime
= currentCPUTime();
1929 if (((endTime
- startTime
) >= .150f
) || !shouldTerminateCallbackWasCalled
) {
1930 if (!((endTime
- startTime
) < .150f
))
1931 printf("FAIL: script did not timed out as expected.\n");
1932 if (!shouldTerminateCallbackWasCalled
)
1933 printf("FAIL: script timeout callback was not called.\n");
1938 printf("PASS: TerminatedExecutionException was not catchable as expected.\n");
1940 printf("FAIL: TerminatedExecutionException was caught.\n");
1945 /* Test script timeout with no callback: */
1946 JSContextGroupSetExecutionTimeLimit(contextGroup
, .10f
, 0, 0);
1948 const char* loopForeverScript
= "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
1949 JSStringRef script
= JSStringCreateWithUTF8CString(loopForeverScript
);
1953 startTime
= currentCPUTime();
1954 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, &exception
);
1955 endTime
= currentCPUTime();
1957 if (((endTime
- startTime
) < .150f
) && shouldTerminateCallbackWasCalled
)
1958 printf("PASS: script timed out as expected when no callback is specified.\n");
1960 if (!((endTime
- startTime
) < .150f
))
1961 printf("FAIL: script did not timed out as expected when no callback is specified.\n");
1966 printf("FAIL: TerminatedExecutionException was not thrown.\n");
1971 /* Test script timeout cancellation: */
1972 JSContextGroupSetExecutionTimeLimit(contextGroup
, 0.10f
, cancelTerminateCallback
, 0);
1974 const char* loopForeverScript
= "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
1975 JSStringRef script
= JSStringCreateWithUTF8CString(loopForeverScript
);
1979 startTime
= currentCPUTime();
1980 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, &exception
);
1981 endTime
= currentCPUTime();
1983 if (((endTime
- startTime
) >= .150f
) && cancelTerminateCallbackWasCalled
&& !exception
)
1984 printf("PASS: script timeout was cancelled as expected.\n");
1986 if (((endTime
- startTime
) < .150) || exception
)
1987 printf("FAIL: script timeout was not cancelled.\n");
1988 if (!cancelTerminateCallbackWasCalled
)
1989 printf("FAIL: script timeout callback was not called.\n");
1994 printf("FAIL: Unexpected TerminatedExecutionException thrown.\n");
1999 /* Test script timeout extension: */
2000 JSContextGroupSetExecutionTimeLimit(contextGroup
, 0.100f
, extendTerminateCallback
, 0);
2002 const char* loopForeverScript
= "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .500) break; } ";
2003 JSStringRef script
= JSStringCreateWithUTF8CString(loopForeverScript
);
2008 startTime
= currentCPUTime();
2009 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, &exception
);
2010 endTime
= currentCPUTime();
2011 deltaTime
= endTime
- startTime
;
2013 if ((deltaTime
>= .300f
) && (deltaTime
< .500f
) && (extendTerminateCallbackCalled
== 2) && exception
)
2014 printf("PASS: script timeout was extended as expected.\n");
2016 if (deltaTime
< .200f
)
2017 printf("FAIL: script timeout was not extended as expected.\n");
2018 else if (deltaTime
>= .500f
)
2019 printf("FAIL: script did not timeout.\n");
2021 if (extendTerminateCallbackCalled
< 1)
2022 printf("FAIL: script timeout callback was not called.\n");
2023 if (extendTerminateCallbackCalled
< 2)
2024 printf("FAIL: script timeout callback was not called after timeout extension.\n");
2027 printf("FAIL: TerminatedExecutionException was not thrown during timeout extension test.\n");
2032 #endif /* OS(DARWIN) */
2034 // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
2038 globalObject
= NULL
;
2039 myConstructor
= NULL
;
2041 JSStringRelease(jsEmptyIString
);
2042 JSStringRelease(jsOneIString
);
2043 JSStringRelease(jsCFIString
);
2044 JSStringRelease(jsCFEmptyIString
);
2045 JSStringRelease(jsCFIStringWithCharacters
);
2046 JSStringRelease(jsCFEmptyIStringWithCharacters
);
2047 JSStringRelease(goodSyntax
);
2048 JSStringRelease(badSyntax
);
2050 JSGlobalContextRelease(context
);
2051 JSClassRelease(globalObjectClass
);
2053 // Test for an infinite prototype chain that used to be created. This test
2054 // passes if the call to JSObjectHasProperty() does not hang.
2056 JSClassDefinition prototypeLoopClassDefinition
= kJSClassDefinitionEmpty
;
2057 prototypeLoopClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
2058 JSClassRef prototypeLoopClass
= JSClassCreate(&prototypeLoopClassDefinition
);
2059 JSGlobalContextRef prototypeLoopContext
= JSGlobalContextCreateInGroup(NULL
, prototypeLoopClass
);
2061 JSStringRef nameProperty
= JSStringCreateWithUTF8CString("name");
2062 JSObjectHasProperty(prototypeLoopContext
, JSContextGetGlobalObject(prototypeLoopContext
), nameProperty
);
2064 JSGlobalContextRelease(prototypeLoopContext
);
2065 JSClassRelease(prototypeLoopClass
);
2067 printf("PASS: Infinite prototype chain does not occur.\n");
2069 if (checkForCycleInPrototypeChain())
2070 printf("PASS: A cycle in a prototype chain can't be created.\n");
2072 printf("FAIL: A cycle in a prototype chain can be created.\n");
2075 if (valueToObjectExceptionTest())
2076 printf("PASS: throwException did not crash when handling an error with appendMessageToError set and no codeBlock available.\n");
2078 if (globalContextNameTest())
2079 printf("PASS: global context name behaves as expected.\n");
2081 customGlobalObjectClassTest();
2082 globalObjectSetPrototypeTest();
2083 globalObjectPrivatePropertyTest();
2086 printf("FAIL: Some tests failed.\n");
2090 printf("PASS: Program exited normally.\n");
2094 static char* createStringWithContentsOfFile(const char* fileName
)
2098 size_t buffer_size
= 0;
2099 size_t buffer_capacity
= 1024;
2100 buffer
= (char*)malloc(buffer_capacity
);
2102 FILE* f
= fopen(fileName
, "r");
2104 fprintf(stderr
, "Could not open file: %s\n", fileName
);
2109 while (!feof(f
) && !ferror(f
)) {
2110 buffer_size
+= fread(buffer
+ buffer_size
, 1, buffer_capacity
- buffer_size
, f
);
2111 if (buffer_size
== buffer_capacity
) { // guarantees space for trailing '\0'
2112 buffer_capacity
*= 2;
2113 buffer
= (char*)realloc(buffer
, buffer_capacity
);
2117 ASSERT(buffer_size
< buffer_capacity
);
2120 buffer
[buffer_size
] = '\0';