2 * Copyright (C) 2006, 2015 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>
42 #include "CompareAndSwapTest.h"
43 #include "CustomGlobalObjectClassTest.h"
44 #include "GlobalContextWithFinalizerTest.h"
47 #include "ExecutionTimeLimitTest.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
]);
92 fprintf(stderr
, "value: %s\n", jsBuffer
);
93 fprintf(stderr
, "expectedValue: %s\n", expectedValue
);
98 if (jsSize
< strlen(jsBuffer
) + 1) {
99 fprintf(stderr
, "assertEqualsAsUTF8String failed: jsSize was too small\n");
104 JSStringRelease(valueAsString
);
107 static void assertEqualsAsCharactersPtr(JSValueRef value
, const char* expectedValue
)
109 JSStringRef valueAsString
= JSValueToStringCopy(context
, value
, NULL
);
111 size_t jsLength
= JSStringGetLength(valueAsString
);
112 const JSChar
* jsBuffer
= JSStringGetCharactersPtr(valueAsString
);
114 CFStringRef expectedValueAsCFString
= CFStringCreateWithCString(kCFAllocatorDefault
,
116 kCFStringEncodingUTF8
);
117 CFIndex cfLength
= CFStringGetLength(expectedValueAsCFString
);
118 UniChar
* cfBuffer
= (UniChar
*)malloc(cfLength
* sizeof(UniChar
));
119 CFStringGetCharacters(expectedValueAsCFString
, CFRangeMake(0, cfLength
), cfBuffer
);
120 CFRelease(expectedValueAsCFString
);
122 if (memcmp(jsBuffer
, cfBuffer
, cfLength
* sizeof(UniChar
)) != 0) {
123 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
127 if (jsLength
!= (size_t)cfLength
) {
129 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsLength(%Iu) != cfLength(%Iu)\n", jsLength
, (size_t)cfLength
);
131 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsLength(%zu) != cfLength(%zu)\n", jsLength
, (size_t)cfLength
);
137 JSStringRelease(valueAsString
);
140 static bool timeZoneIsPST()
142 char timeZoneName
[70];
144 memset(>m
, 0, sizeof(gtm
));
145 strftime(timeZoneName
, sizeof(timeZoneName
), "%Z", >m
);
147 return 0 == strcmp("PST", timeZoneName
);
150 static JSValueRef jsGlobalValue
; // non-stack value for testing JSValueProtect()
152 /* MyObject pseudo-class */
154 static bool MyObject_hasProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
)
156 UNUSED_PARAM(context
);
157 UNUSED_PARAM(object
);
159 if (JSStringIsEqualToUTF8CString(propertyName
, "alwaysOne")
160 || JSStringIsEqualToUTF8CString(propertyName
, "cantFind")
161 || JSStringIsEqualToUTF8CString(propertyName
, "throwOnGet")
162 || JSStringIsEqualToUTF8CString(propertyName
, "myPropertyName")
163 || JSStringIsEqualToUTF8CString(propertyName
, "hasPropertyLie")
164 || JSStringIsEqualToUTF8CString(propertyName
, "0")) {
171 static JSValueRef
MyObject_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
173 UNUSED_PARAM(context
);
174 UNUSED_PARAM(object
);
176 if (JSStringIsEqualToUTF8CString(propertyName
, "alwaysOne")) {
177 return JSValueMakeNumber(context
, 1);
180 if (JSStringIsEqualToUTF8CString(propertyName
, "myPropertyName")) {
181 return JSValueMakeNumber(context
, 1);
184 if (JSStringIsEqualToUTF8CString(propertyName
, "cantFind")) {
185 return JSValueMakeUndefined(context
);
188 if (JSStringIsEqualToUTF8CString(propertyName
, "hasPropertyLie")) {
192 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnGet")) {
193 return JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
196 if (JSStringIsEqualToUTF8CString(propertyName
, "0")) {
197 *exception
= JSValueMakeNumber(context
, 1);
198 return JSValueMakeNumber(context
, 1);
201 return JSValueMakeNull(context
);
204 static bool MyObject_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
206 UNUSED_PARAM(context
);
207 UNUSED_PARAM(object
);
209 UNUSED_PARAM(exception
);
211 if (JSStringIsEqualToUTF8CString(propertyName
, "cantSet"))
212 return true; // pretend we set the property in order to swallow it
214 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnSet")) {
215 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
221 static bool MyObject_deleteProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
223 UNUSED_PARAM(context
);
224 UNUSED_PARAM(object
);
226 if (JSStringIsEqualToUTF8CString(propertyName
, "cantDelete"))
229 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnDelete")) {
230 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
237 static void MyObject_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef propertyNames
)
239 UNUSED_PARAM(context
);
240 UNUSED_PARAM(object
);
242 JSStringRef propertyName
;
244 propertyName
= JSStringCreateWithUTF8CString("alwaysOne");
245 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
246 JSStringRelease(propertyName
);
248 propertyName
= JSStringCreateWithUTF8CString("myPropertyName");
249 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
250 JSStringRelease(propertyName
);
253 static JSValueRef
MyObject_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
255 UNUSED_PARAM(context
);
256 UNUSED_PARAM(object
);
257 UNUSED_PARAM(thisObject
);
258 UNUSED_PARAM(exception
);
260 if (argumentCount
> 0 && JSValueIsString(context
, arguments
[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, arguments
[0], 0), "throwOnCall")) {
261 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
262 return JSValueMakeUndefined(context
);
265 if (argumentCount
> 0 && JSValueIsStrictEqual(context
, arguments
[0], JSValueMakeNumber(context
, 0)))
266 return JSValueMakeNumber(context
, 1);
268 return JSValueMakeUndefined(context
);
271 static JSObjectRef
MyObject_callAsConstructor(JSContextRef context
, JSObjectRef object
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
273 UNUSED_PARAM(context
);
274 UNUSED_PARAM(object
);
276 if (argumentCount
> 0 && JSValueIsString(context
, arguments
[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, arguments
[0], 0), "throwOnConstruct")) {
277 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
281 if (argumentCount
> 0 && JSValueIsStrictEqual(context
, arguments
[0], JSValueMakeNumber(context
, 0)))
282 return JSValueToObject(context
, JSValueMakeNumber(context
, 1), exception
);
284 return JSValueToObject(context
, JSValueMakeNumber(context
, 0), exception
);
287 static bool MyObject_hasInstance(JSContextRef context
, JSObjectRef constructor
, JSValueRef possibleValue
, JSValueRef
* exception
)
289 UNUSED_PARAM(context
);
290 UNUSED_PARAM(constructor
);
292 if (JSValueIsString(context
, possibleValue
) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, possibleValue
, 0), "throwOnHasInstance")) {
293 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), constructor
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
297 JSStringRef numberString
= JSStringCreateWithUTF8CString("Number");
298 JSObjectRef numberConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, JSContextGetGlobalObject(context
), numberString
, exception
), exception
);
299 JSStringRelease(numberString
);
301 return JSValueIsInstanceOfConstructor(context
, possibleValue
, numberConstructor
, exception
);
304 static JSValueRef
MyObject_convertToType(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
306 UNUSED_PARAM(object
);
307 UNUSED_PARAM(exception
);
311 return JSValueMakeNumber(context
, 1);
314 JSStringRef string
= JSStringCreateWithUTF8CString("MyObjectAsString");
315 JSValueRef result
= JSValueMakeString(context
, string
);
316 JSStringRelease(string
);
323 // string conversion -- forward to default object class
324 return JSValueMakeNull(context
);
327 static JSValueRef
MyObject_convertToTypeWrapper(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
329 UNUSED_PARAM(context
);
330 UNUSED_PARAM(object
);
332 UNUSED_PARAM(exception
);
333 // Forward to default object class
337 static bool MyObject_set_nullGetForwardSet(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
340 UNUSED_PARAM(object
);
341 UNUSED_PARAM(propertyName
);
343 UNUSED_PARAM(exception
);
344 return false; // Forward to parent class.
347 static JSStaticValue evilStaticValues
[] = {
348 { "nullGetSet", 0, 0, kJSPropertyAttributeNone
},
349 { "nullGetForwardSet", 0, MyObject_set_nullGetForwardSet
, kJSPropertyAttributeNone
},
353 static JSStaticFunction evilStaticFunctions
[] = {
354 { "nullCall", 0, kJSPropertyAttributeNone
},
358 JSClassDefinition MyObject_definition
= {
360 kJSClassAttributeNone
,
370 MyObject_hasProperty
,
371 MyObject_getProperty
,
372 MyObject_setProperty
,
373 MyObject_deleteProperty
,
374 MyObject_getPropertyNames
,
375 MyObject_callAsFunction
,
376 MyObject_callAsConstructor
,
377 MyObject_hasInstance
,
378 MyObject_convertToType
,
381 JSClassDefinition MyObject_convertToTypeWrapperDefinition
= {
383 kJSClassAttributeNone
,
401 MyObject_convertToTypeWrapper
,
404 JSClassDefinition MyObject_nullWrapperDefinition
= {
406 kJSClassAttributeNone
,
427 static JSClassRef
MyObject_class(JSContextRef context
)
429 UNUSED_PARAM(context
);
431 static JSClassRef jsClass
;
433 JSClassRef baseClass
= JSClassCreate(&MyObject_definition
);
434 MyObject_convertToTypeWrapperDefinition
.parentClass
= baseClass
;
435 JSClassRef wrapperClass
= JSClassCreate(&MyObject_convertToTypeWrapperDefinition
);
436 MyObject_nullWrapperDefinition
.parentClass
= wrapperClass
;
437 jsClass
= JSClassCreate(&MyObject_nullWrapperDefinition
);
443 static JSValueRef
PropertyCatchalls_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
445 UNUSED_PARAM(context
);
446 UNUSED_PARAM(object
);
447 UNUSED_PARAM(propertyName
);
448 UNUSED_PARAM(exception
);
450 if (JSStringIsEqualToUTF8CString(propertyName
, "x")) {
455 // Swallow all .x gets after 5, returning null.
456 return JSValueMakeNull(context
);
459 if (JSStringIsEqualToUTF8CString(propertyName
, "y")) {
464 // Swallow all .y gets after 5, returning null.
465 return JSValueMakeNull(context
);
468 if (JSStringIsEqualToUTF8CString(propertyName
, "z")) {
473 // Swallow all .y gets after 5, returning null.
474 return JSValueMakeNull(context
);
480 static bool PropertyCatchalls_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
482 UNUSED_PARAM(context
);
483 UNUSED_PARAM(object
);
484 UNUSED_PARAM(propertyName
);
486 UNUSED_PARAM(exception
);
488 if (JSStringIsEqualToUTF8CString(propertyName
, "x")) {
493 // Swallow all .x sets after 4.
497 if (JSStringIsEqualToUTF8CString(propertyName
, "make_throw") || JSStringIsEqualToUTF8CString(propertyName
, "0")) {
498 *exception
= JSValueMakeNumber(context
, 5);
505 static void PropertyCatchalls_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef propertyNames
)
507 UNUSED_PARAM(context
);
508 UNUSED_PARAM(object
);
511 static const char* numbers
[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
513 // Provide a property of a different name every time.
514 JSStringRef propertyName
= JSStringCreateWithUTF8CString(numbers
[count
++ % 10]);
515 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
516 JSStringRelease(propertyName
);
519 JSClassDefinition PropertyCatchalls_definition
= {
521 kJSClassAttributeNone
,
532 PropertyCatchalls_getProperty
,
533 PropertyCatchalls_setProperty
,
535 PropertyCatchalls_getPropertyNames
,
542 static JSClassRef
PropertyCatchalls_class(JSContextRef context
)
544 UNUSED_PARAM(context
);
546 static JSClassRef jsClass
;
548 jsClass
= JSClassCreate(&PropertyCatchalls_definition
);
553 static bool EvilExceptionObject_hasInstance(JSContextRef context
, JSObjectRef constructor
, JSValueRef possibleValue
, JSValueRef
* exception
)
555 UNUSED_PARAM(context
);
556 UNUSED_PARAM(constructor
);
558 JSStringRef hasInstanceName
= JSStringCreateWithUTF8CString("hasInstance");
559 JSValueRef hasInstance
= JSObjectGetProperty(context
, constructor
, hasInstanceName
, exception
);
560 JSStringRelease(hasInstanceName
);
563 JSObjectRef function
= JSValueToObject(context
, hasInstance
, exception
);
564 JSValueRef result
= JSObjectCallAsFunction(context
, function
, constructor
, 1, &possibleValue
, exception
);
565 return result
&& JSValueToBoolean(context
, result
);
568 static JSValueRef
EvilExceptionObject_convertToType(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
570 UNUSED_PARAM(object
);
571 UNUSED_PARAM(exception
);
572 JSStringRef funcName
;
575 funcName
= JSStringCreateWithUTF8CString("toNumber");
578 funcName
= JSStringCreateWithUTF8CString("toStringExplicit");
581 return JSValueMakeNull(context
);
584 JSValueRef func
= JSObjectGetProperty(context
, object
, funcName
, exception
);
585 JSStringRelease(funcName
);
586 JSObjectRef function
= JSValueToObject(context
, func
, exception
);
588 return JSValueMakeNull(context
);
589 JSValueRef value
= JSObjectCallAsFunction(context
, function
, object
, 0, NULL
, exception
);
591 JSStringRef errorString
= JSStringCreateWithUTF8CString("convertToType failed");
592 JSValueRef errorStringRef
= JSValueMakeString(context
, errorString
);
593 JSStringRelease(errorString
);
594 return errorStringRef
;
599 JSClassDefinition EvilExceptionObject_definition
= {
601 kJSClassAttributeNone
,
603 "EvilExceptionObject",
618 EvilExceptionObject_hasInstance
,
619 EvilExceptionObject_convertToType
,
622 static JSClassRef
EvilExceptionObject_class(JSContextRef context
)
624 UNUSED_PARAM(context
);
626 static JSClassRef jsClass
;
628 jsClass
= JSClassCreate(&EvilExceptionObject_definition
);
633 JSClassDefinition EmptyObject_definition
= {
635 kJSClassAttributeNone
,
656 static JSClassRef
EmptyObject_class(JSContextRef context
)
658 UNUSED_PARAM(context
);
660 static JSClassRef jsClass
;
662 jsClass
= JSClassCreate(&EmptyObject_definition
);
668 static JSValueRef
Base_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
670 UNUSED_PARAM(object
);
671 UNUSED_PARAM(propertyName
);
672 UNUSED_PARAM(exception
);
674 return JSValueMakeNumber(ctx
, 1); // distinguish base get form derived get
677 static bool Base_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
679 UNUSED_PARAM(object
);
680 UNUSED_PARAM(propertyName
);
683 *exception
= JSValueMakeNumber(ctx
, 1); // distinguish base set from derived set
687 static JSValueRef
Base_callAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
689 UNUSED_PARAM(function
);
690 UNUSED_PARAM(thisObject
);
691 UNUSED_PARAM(argumentCount
);
692 UNUSED_PARAM(arguments
);
693 UNUSED_PARAM(exception
);
695 return JSValueMakeNumber(ctx
, 1); // distinguish base call from derived call
698 static JSValueRef
Base_returnHardNull(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
701 UNUSED_PARAM(function
);
702 UNUSED_PARAM(thisObject
);
703 UNUSED_PARAM(argumentCount
);
704 UNUSED_PARAM(arguments
);
705 UNUSED_PARAM(exception
);
707 return 0; // should convert to undefined!
710 static JSStaticFunction Base_staticFunctions
[] = {
711 { "baseProtoDup", NULL
, kJSPropertyAttributeNone
},
712 { "baseProto", Base_callAsFunction
, kJSPropertyAttributeNone
},
713 { "baseHardNull", Base_returnHardNull
, kJSPropertyAttributeNone
},
717 static JSStaticValue Base_staticValues
[] = {
718 { "baseDup", Base_get
, Base_set
, kJSPropertyAttributeNone
},
719 { "baseOnly", Base_get
, Base_set
, kJSPropertyAttributeNone
},
723 static bool TestInitializeFinalize
;
724 static void Base_initialize(JSContextRef context
, JSObjectRef object
)
726 UNUSED_PARAM(context
);
728 if (TestInitializeFinalize
) {
729 ASSERT((void*)1 == JSObjectGetPrivate(object
));
730 JSObjectSetPrivate(object
, (void*)2);
734 static unsigned Base_didFinalize
;
735 static void Base_finalize(JSObjectRef object
)
737 UNUSED_PARAM(object
);
738 if (TestInitializeFinalize
) {
739 ASSERT((void*)4 == JSObjectGetPrivate(object
));
740 Base_didFinalize
= true;
744 static JSClassRef
Base_class(JSContextRef context
)
746 UNUSED_PARAM(context
);
748 static JSClassRef jsClass
;
750 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
751 definition
.staticValues
= Base_staticValues
;
752 definition
.staticFunctions
= Base_staticFunctions
;
753 definition
.initialize
= Base_initialize
;
754 definition
.finalize
= Base_finalize
;
755 jsClass
= JSClassCreate(&definition
);
760 static JSValueRef
Derived_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
762 UNUSED_PARAM(object
);
763 UNUSED_PARAM(propertyName
);
764 UNUSED_PARAM(exception
);
766 return JSValueMakeNumber(ctx
, 2); // distinguish base get form derived get
769 static bool Derived_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
772 UNUSED_PARAM(object
);
773 UNUSED_PARAM(propertyName
);
776 *exception
= JSValueMakeNumber(ctx
, 2); // distinguish base set from derived set
780 static JSValueRef
Derived_callAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
782 UNUSED_PARAM(function
);
783 UNUSED_PARAM(thisObject
);
784 UNUSED_PARAM(argumentCount
);
785 UNUSED_PARAM(arguments
);
786 UNUSED_PARAM(exception
);
788 return JSValueMakeNumber(ctx
, 2); // distinguish base call from derived call
791 static JSStaticFunction Derived_staticFunctions
[] = {
792 { "protoOnly", Derived_callAsFunction
, kJSPropertyAttributeNone
},
793 { "protoDup", NULL
, kJSPropertyAttributeNone
},
794 { "baseProtoDup", Derived_callAsFunction
, kJSPropertyAttributeNone
},
798 static JSStaticValue Derived_staticValues
[] = {
799 { "derivedOnly", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
800 { "protoDup", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
801 { "baseDup", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
805 static void Derived_initialize(JSContextRef context
, JSObjectRef object
)
807 UNUSED_PARAM(context
);
809 if (TestInitializeFinalize
) {
810 ASSERT((void*)2 == JSObjectGetPrivate(object
));
811 JSObjectSetPrivate(object
, (void*)3);
815 static void Derived_finalize(JSObjectRef object
)
817 if (TestInitializeFinalize
) {
818 ASSERT((void*)3 == JSObjectGetPrivate(object
));
819 JSObjectSetPrivate(object
, (void*)4);
823 static JSClassRef
Derived_class(JSContextRef context
)
825 static JSClassRef jsClass
;
827 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
828 definition
.parentClass
= Base_class(context
);
829 definition
.staticValues
= Derived_staticValues
;
830 definition
.staticFunctions
= Derived_staticFunctions
;
831 definition
.initialize
= Derived_initialize
;
832 definition
.finalize
= Derived_finalize
;
833 jsClass
= JSClassCreate(&definition
);
838 static JSClassRef
Derived2_class(JSContextRef context
)
840 static JSClassRef jsClass
;
842 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
843 definition
.parentClass
= Derived_class(context
);
844 jsClass
= JSClassCreate(&definition
);
849 static JSValueRef
print_callAsFunction(JSContextRef ctx
, JSObjectRef functionObject
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
851 UNUSED_PARAM(functionObject
);
852 UNUSED_PARAM(thisObject
);
853 UNUSED_PARAM(exception
);
855 ASSERT(JSContextGetGlobalContext(ctx
) == context
);
857 if (argumentCount
> 0) {
858 JSStringRef string
= JSValueToStringCopy(ctx
, arguments
[0], NULL
);
859 size_t sizeUTF8
= JSStringGetMaximumUTF8CStringSize(string
);
860 char* stringUTF8
= (char*)malloc(sizeUTF8
);
861 JSStringGetUTF8CString(string
, stringUTF8
, sizeUTF8
);
862 printf("%s\n", stringUTF8
);
864 JSStringRelease(string
);
867 return JSValueMakeUndefined(ctx
);
870 static JSObjectRef
myConstructor_callAsConstructor(JSContextRef context
, JSObjectRef constructorObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
872 UNUSED_PARAM(constructorObject
);
873 UNUSED_PARAM(exception
);
875 JSObjectRef result
= JSObjectMake(context
, NULL
, NULL
);
876 if (argumentCount
> 0) {
877 JSStringRef value
= JSStringCreateWithUTF8CString("value");
878 JSObjectSetProperty(context
, result
, value
, arguments
[0], kJSPropertyAttributeNone
, NULL
);
879 JSStringRelease(value
);
885 static JSObjectRef
myBadConstructor_callAsConstructor(JSContextRef context
, JSObjectRef constructorObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
887 UNUSED_PARAM(context
);
888 UNUSED_PARAM(constructorObject
);
889 UNUSED_PARAM(argumentCount
);
890 UNUSED_PARAM(arguments
);
891 UNUSED_PARAM(exception
);
897 static void globalObject_initialize(JSContextRef context
, JSObjectRef object
)
899 UNUSED_PARAM(object
);
900 // Ensure that an execution context is passed in
903 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
904 ASSERT(globalObject
);
906 // Ensure that the standard global properties have been set on the global object
907 JSStringRef array
= JSStringCreateWithUTF8CString("Array");
908 JSObjectRef arrayConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, globalObject
, array
, NULL
), NULL
);
909 JSStringRelease(array
);
911 UNUSED_PARAM(arrayConstructor
);
912 ASSERT(arrayConstructor
);
915 static JSValueRef
globalObject_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
917 UNUSED_PARAM(object
);
918 UNUSED_PARAM(propertyName
);
919 UNUSED_PARAM(exception
);
921 return JSValueMakeNumber(ctx
, 3);
924 static bool globalObject_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
926 UNUSED_PARAM(object
);
927 UNUSED_PARAM(propertyName
);
930 *exception
= JSValueMakeNumber(ctx
, 3);
934 static JSValueRef
globalObject_call(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
936 UNUSED_PARAM(function
);
937 UNUSED_PARAM(thisObject
);
938 UNUSED_PARAM(argumentCount
);
939 UNUSED_PARAM(arguments
);
940 UNUSED_PARAM(exception
);
942 return JSValueMakeNumber(ctx
, 3);
945 static JSValueRef
functionGC(JSContextRef context
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
947 UNUSED_PARAM(function
);
948 UNUSED_PARAM(thisObject
);
949 UNUSED_PARAM(argumentCount
);
950 UNUSED_PARAM(arguments
);
951 UNUSED_PARAM(exception
);
952 JSGarbageCollect(context
);
953 return JSValueMakeUndefined(context
);
956 static JSStaticValue globalObject_staticValues
[] = {
957 { "globalStaticValue", globalObject_get
, globalObject_set
, kJSPropertyAttributeNone
},
961 static JSStaticFunction globalObject_staticFunctions
[] = {
962 { "globalStaticFunction", globalObject_call
, kJSPropertyAttributeNone
},
963 { "globalStaticFunction2", globalObject_call
, kJSPropertyAttributeNone
},
964 { "gc", functionGC
, kJSPropertyAttributeNone
},
968 static char* createStringWithContentsOfFile(const char* fileName
);
970 static void testInitializeFinalize()
972 JSObjectRef o
= JSObjectMake(context
, Derived_class(context
), (void*)1);
974 ASSERT(JSObjectGetPrivate(o
) == (void*)3);
977 static JSValueRef jsNumberValue
= NULL
;
979 static JSObjectRef aHeapRef
= NULL
;
981 static void makeGlobalNumberValue(JSContextRef context
) {
982 JSValueRef v
= JSValueMakeNumber(context
, 420);
983 JSValueProtect(context
, v
);
988 bool assertTrue(bool value
, const char* message
)
992 fprintf(stderr
, "assertTrue failed: '%s'\n", message
);
994 fprintf(stderr
, "assertTrue failed.\n");
1000 static bool checkForCycleInPrototypeChain()
1003 JSGlobalContextRef context
= JSGlobalContextCreate(0);
1004 JSObjectRef object1
= JSObjectMake(context
, /* jsClass */ 0, /* data */ 0);
1005 JSObjectRef object2
= JSObjectMake(context
, /* jsClass */ 0, /* data */ 0);
1006 JSObjectRef object3
= JSObjectMake(context
, /* jsClass */ 0, /* data */ 0);
1008 JSObjectSetPrototype(context
, object1
, JSValueMakeNull(context
));
1009 ASSERT(JSValueIsNull(context
, JSObjectGetPrototype(context
, object1
)));
1011 // object1 -> object1
1012 JSObjectSetPrototype(context
, object1
, object1
);
1013 result
&= assertTrue(JSValueIsNull(context
, JSObjectGetPrototype(context
, object1
)), "It is possible to assign self as a prototype");
1015 // object1 -> object2 -> object1
1016 JSObjectSetPrototype(context
, object2
, object1
);
1017 ASSERT(JSValueIsStrictEqual(context
, JSObjectGetPrototype(context
, object2
), object1
));
1018 JSObjectSetPrototype(context
, object1
, object2
);
1019 result
&= assertTrue(JSValueIsNull(context
, JSObjectGetPrototype(context
, object1
)), "It is possible to close a prototype chain cycle");
1021 // object1 -> object2 -> object3 -> object1
1022 JSObjectSetPrototype(context
, object2
, object3
);
1023 ASSERT(JSValueIsStrictEqual(context
, JSObjectGetPrototype(context
, object2
), object3
));
1024 JSObjectSetPrototype(context
, object1
, object2
);
1025 ASSERT(JSValueIsStrictEqual(context
, JSObjectGetPrototype(context
, object1
), object2
));
1026 JSObjectSetPrototype(context
, object3
, object1
);
1027 result
&= assertTrue(!JSValueIsStrictEqual(context
, JSObjectGetPrototype(context
, object3
), object1
), "It is possible to close a prototype chain cycle");
1029 JSValueRef exception
;
1030 JSStringRef code
= JSStringCreateWithUTF8CString("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
1031 JSStringRef file
= JSStringCreateWithUTF8CString("");
1032 result
&= assertTrue(!JSEvaluateScript(context
, code
, /* thisObject*/ 0, file
, 1, &exception
)
1033 , "An exception should be thrown");
1035 JSStringRelease(code
);
1036 JSStringRelease(file
);
1037 JSGlobalContextRelease(context
);
1041 static JSValueRef
valueToObjectExceptionCallAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
1043 UNUSED_PARAM(function
);
1044 UNUSED_PARAM(thisObject
);
1045 UNUSED_PARAM(argumentCount
);
1046 UNUSED_PARAM(arguments
);
1047 JSValueRef jsUndefined
= JSValueMakeUndefined(JSContextGetGlobalContext(ctx
));
1048 JSValueToObject(JSContextGetGlobalContext(ctx
), jsUndefined
, exception
);
1050 return JSValueMakeUndefined(ctx
);
1052 static bool valueToObjectExceptionTest()
1054 JSGlobalContextRef testContext
;
1055 JSClassDefinition globalObjectClassDefinition
= kJSClassDefinitionEmpty
;
1056 globalObjectClassDefinition
.initialize
= globalObject_initialize
;
1057 globalObjectClassDefinition
.staticValues
= globalObject_staticValues
;
1058 globalObjectClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
1059 globalObjectClassDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
1060 JSClassRef globalObjectClass
= JSClassCreate(&globalObjectClassDefinition
);
1061 testContext
= JSGlobalContextCreateInGroup(NULL
, globalObjectClass
);
1062 JSObjectRef globalObject
= JSContextGetGlobalObject(testContext
);
1064 JSStringRef valueToObject
= JSStringCreateWithUTF8CString("valueToObject");
1065 JSObjectRef valueToObjectFunction
= JSObjectMakeFunctionWithCallback(testContext
, valueToObject
, valueToObjectExceptionCallAsFunction
);
1066 JSObjectSetProperty(testContext
, globalObject
, valueToObject
, valueToObjectFunction
, kJSPropertyAttributeNone
, NULL
);
1067 JSStringRelease(valueToObject
);
1069 JSStringRef test
= JSStringCreateWithUTF8CString("valueToObject();");
1070 JSEvaluateScript(testContext
, test
, NULL
, NULL
, 1, NULL
);
1072 JSStringRelease(test
);
1073 JSClassRelease(globalObjectClass
);
1074 JSGlobalContextRelease(testContext
);
1079 static bool globalContextNameTest()
1082 JSGlobalContextRef context
= JSGlobalContextCreate(0);
1084 JSStringRef str
= JSGlobalContextCopyName(context
);
1085 result
&= assertTrue(!str
, "Default context name is NULL");
1087 JSStringRef name1
= JSStringCreateWithUTF8CString("name1");
1088 JSStringRef name2
= JSStringCreateWithUTF8CString("name2");
1090 JSGlobalContextSetName(context
, name1
);
1091 JSStringRef fetchName1
= JSGlobalContextCopyName(context
);
1092 JSGlobalContextSetName(context
, name2
);
1093 JSStringRef fetchName2
= JSGlobalContextCopyName(context
);
1094 JSGlobalContextSetName(context
, NULL
);
1095 JSStringRef fetchName3
= JSGlobalContextCopyName(context
);
1097 result
&= assertTrue(JSStringIsEqual(name1
, fetchName1
), "Unexpected Context name");
1098 result
&= assertTrue(JSStringIsEqual(name2
, fetchName2
), "Unexpected Context name");
1099 result
&= assertTrue(!JSStringIsEqual(fetchName1
, fetchName2
), "Unexpected Context name");
1100 result
&= assertTrue(!fetchName3
, "Unexpected Context name");
1102 JSStringRelease(name1
);
1103 JSStringRelease(name2
);
1104 JSStringRelease(fetchName1
);
1105 JSStringRelease(fetchName2
);
1110 static void checkConstnessInJSObjectNames()
1112 JSStaticFunction fun
;
1113 fun
.name
= "something";
1115 val
.name
= "something";
1119 int main(int argc
, char* argv
[])
1122 #if defined(_M_X64) || defined(__x86_64__)
1123 // The VS2013 runtime has a bug where it mis-detects AVX-capable processors
1124 // if the feature has been disabled in firmware. This causes us to crash
1125 // in some of the math functions. For now, we disable those optimizations
1126 // because Microsoft is not going to fix the problem in VS2013.
1127 // FIXME: http://webkit.org/b/141449: Remove this workaround when we switch to VS2015+.
1128 _set_FMA3_enable(0);
1131 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1132 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1133 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1137 testCompareAndSwap();
1139 #if JSC_OBJC_API_ENABLED
1140 testObjectiveCAPI();
1143 const char *scriptPath
= "testapi.js";
1145 scriptPath
= argv
[1];
1148 // Test garbage collection with a fresh context
1149 context
= JSGlobalContextCreateInGroup(NULL
, NULL
);
1150 TestInitializeFinalize
= true;
1151 testInitializeFinalize();
1152 JSGlobalContextRelease(context
);
1153 TestInitializeFinalize
= false;
1155 ASSERT(Base_didFinalize
);
1157 JSClassDefinition globalObjectClassDefinition
= kJSClassDefinitionEmpty
;
1158 globalObjectClassDefinition
.initialize
= globalObject_initialize
;
1159 globalObjectClassDefinition
.staticValues
= globalObject_staticValues
;
1160 globalObjectClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
1161 globalObjectClassDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
1162 JSClassRef globalObjectClass
= JSClassCreate(&globalObjectClassDefinition
);
1163 context
= JSGlobalContextCreateInGroup(NULL
, globalObjectClass
);
1165 JSContextGroupRef contextGroup
= JSContextGetGroup(context
);
1167 JSGlobalContextRetain(context
);
1168 JSGlobalContextRelease(context
);
1169 ASSERT(JSContextGetGlobalContext(context
) == context
);
1171 JSReportExtraMemoryCost(context
, 0);
1172 JSReportExtraMemoryCost(context
, 1);
1173 JSReportExtraMemoryCost(context
, 1024);
1175 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
1176 ASSERT(JSValueIsObject(context
, globalObject
));
1178 JSValueRef jsUndefined
= JSValueMakeUndefined(context
);
1179 JSValueRef jsNull
= JSValueMakeNull(context
);
1180 JSValueRef jsTrue
= JSValueMakeBoolean(context
, true);
1181 JSValueRef jsFalse
= JSValueMakeBoolean(context
, false);
1182 JSValueRef jsZero
= JSValueMakeNumber(context
, 0);
1183 JSValueRef jsOne
= JSValueMakeNumber(context
, 1);
1184 JSValueRef jsOneThird
= JSValueMakeNumber(context
, 1.0 / 3.0);
1185 JSObjectRef jsObjectNoProto
= JSObjectMake(context
, NULL
, NULL
);
1186 JSObjectSetPrototype(context
, jsObjectNoProto
, JSValueMakeNull(context
));
1188 JSObjectSetPrivate(globalObject
, (void*)123);
1189 if (JSObjectGetPrivate(globalObject
) != (void*)123) {
1190 printf("FAIL: Didn't return private data when set by JSObjectSetPrivate().\n");
1193 printf("PASS: returned private data when set by JSObjectSetPrivate().\n");
1195 // FIXME: test funny utf8 characters
1196 JSStringRef jsEmptyIString
= JSStringCreateWithUTF8CString("");
1197 JSValueRef jsEmptyString
= JSValueMakeString(context
, jsEmptyIString
);
1199 JSStringRef jsOneIString
= JSStringCreateWithUTF8CString("1");
1200 JSValueRef jsOneString
= JSValueMakeString(context
, jsOneIString
);
1202 UniChar singleUniChar
= 65; // Capital A
1203 CFMutableStringRef cfString
=
1204 CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault
,
1210 JSStringRef jsCFIString
= JSStringCreateWithCFString(cfString
);
1211 JSValueRef jsCFString
= JSValueMakeString(context
, jsCFIString
);
1213 CFStringRef cfEmptyString
= CFStringCreateWithCString(kCFAllocatorDefault
, "", kCFStringEncodingUTF8
);
1215 JSStringRef jsCFEmptyIString
= JSStringCreateWithCFString(cfEmptyString
);
1216 JSValueRef jsCFEmptyString
= JSValueMakeString(context
, jsCFEmptyIString
);
1218 CFIndex cfStringLength
= CFStringGetLength(cfString
);
1219 UniChar
* buffer
= (UniChar
*)malloc(cfStringLength
* sizeof(UniChar
));
1220 CFStringGetCharacters(cfString
,
1221 CFRangeMake(0, cfStringLength
),
1223 JSStringRef jsCFIStringWithCharacters
= JSStringCreateWithCharacters((JSChar
*)buffer
, cfStringLength
);
1224 JSValueRef jsCFStringWithCharacters
= JSValueMakeString(context
, jsCFIStringWithCharacters
);
1226 JSStringRef jsCFEmptyIStringWithCharacters
= JSStringCreateWithCharacters((JSChar
*)buffer
, CFStringGetLength(cfEmptyString
));
1228 JSValueRef jsCFEmptyStringWithCharacters
= JSValueMakeString(context
, jsCFEmptyIStringWithCharacters
);
1230 JSChar constantString
[] = { 'H', 'e', 'l', 'l', 'o', };
1231 JSStringRef constantStringRef
= JSStringCreateWithCharactersNoCopy(constantString
, sizeof(constantString
) / sizeof(constantString
[0]));
1232 ASSERT(JSStringGetCharactersPtr(constantStringRef
) == constantString
);
1233 JSStringRelease(constantStringRef
);
1235 ASSERT(JSValueGetType(context
, NULL
) == kJSTypeNull
);
1236 ASSERT(JSValueGetType(context
, jsUndefined
) == kJSTypeUndefined
);
1237 ASSERT(JSValueGetType(context
, jsNull
) == kJSTypeNull
);
1238 ASSERT(JSValueGetType(context
, jsTrue
) == kJSTypeBoolean
);
1239 ASSERT(JSValueGetType(context
, jsFalse
) == kJSTypeBoolean
);
1240 ASSERT(JSValueGetType(context
, jsZero
) == kJSTypeNumber
);
1241 ASSERT(JSValueGetType(context
, jsOne
) == kJSTypeNumber
);
1242 ASSERT(JSValueGetType(context
, jsOneThird
) == kJSTypeNumber
);
1243 ASSERT(JSValueGetType(context
, jsEmptyString
) == kJSTypeString
);
1244 ASSERT(JSValueGetType(context
, jsOneString
) == kJSTypeString
);
1245 ASSERT(JSValueGetType(context
, jsCFString
) == kJSTypeString
);
1246 ASSERT(JSValueGetType(context
, jsCFStringWithCharacters
) == kJSTypeString
);
1247 ASSERT(JSValueGetType(context
, jsCFEmptyString
) == kJSTypeString
);
1248 ASSERT(JSValueGetType(context
, jsCFEmptyStringWithCharacters
) == kJSTypeString
);
1250 ASSERT(!JSValueIsBoolean(context
, NULL
));
1251 ASSERT(!JSValueIsObject(context
, NULL
));
1252 ASSERT(!JSValueIsArray(context
, NULL
));
1253 ASSERT(!JSValueIsDate(context
, NULL
));
1254 ASSERT(!JSValueIsString(context
, NULL
));
1255 ASSERT(!JSValueIsNumber(context
, NULL
));
1256 ASSERT(!JSValueIsUndefined(context
, NULL
));
1257 ASSERT(JSValueIsNull(context
, NULL
));
1258 ASSERT(!JSObjectCallAsFunction(context
, NULL
, NULL
, 0, NULL
, NULL
));
1259 ASSERT(!JSObjectCallAsConstructor(context
, NULL
, 0, NULL
, NULL
));
1260 ASSERT(!JSObjectIsConstructor(context
, NULL
));
1261 ASSERT(!JSObjectIsFunction(context
, NULL
));
1263 JSStringRef nullString
= JSStringCreateWithUTF8CString(0);
1264 const JSChar
* characters
= JSStringGetCharactersPtr(nullString
);
1266 printf("FAIL: Didn't return null when accessing character pointer of a null String.\n");
1269 printf("PASS: returned null when accessing character pointer of a null String.\n");
1271 JSStringRef emptyString
= JSStringCreateWithCFString(CFSTR(""));
1272 characters
= JSStringGetCharactersPtr(emptyString
);
1274 printf("FAIL: Returned null when accessing character pointer of an empty String.\n");
1277 printf("PASS: returned empty when accessing character pointer of an empty String.\n");
1279 size_t length
= JSStringGetLength(nullString
);
1281 printf("FAIL: Didn't return 0 length for null String.\n");
1284 printf("PASS: returned 0 length for null String.\n");
1285 JSStringRelease(nullString
);
1287 length
= JSStringGetLength(emptyString
);
1289 printf("FAIL: Didn't return 0 length for empty String.\n");
1292 printf("PASS: returned 0 length for empty String.\n");
1293 JSStringRelease(emptyString
);
1295 JSObjectRef propertyCatchalls
= JSObjectMake(context
, PropertyCatchalls_class(context
), NULL
);
1296 JSStringRef propertyCatchallsString
= JSStringCreateWithUTF8CString("PropertyCatchalls");
1297 JSObjectSetProperty(context
, globalObject
, propertyCatchallsString
, propertyCatchalls
, kJSPropertyAttributeNone
, NULL
);
1298 JSStringRelease(propertyCatchallsString
);
1300 JSObjectRef myObject
= JSObjectMake(context
, MyObject_class(context
), NULL
);
1301 JSStringRef myObjectIString
= JSStringCreateWithUTF8CString("MyObject");
1302 JSObjectSetProperty(context
, globalObject
, myObjectIString
, myObject
, kJSPropertyAttributeNone
, NULL
);
1303 JSStringRelease(myObjectIString
);
1305 JSObjectRef EvilExceptionObject
= JSObjectMake(context
, EvilExceptionObject_class(context
), NULL
);
1306 JSStringRef EvilExceptionObjectIString
= JSStringCreateWithUTF8CString("EvilExceptionObject");
1307 JSObjectSetProperty(context
, globalObject
, EvilExceptionObjectIString
, EvilExceptionObject
, kJSPropertyAttributeNone
, NULL
);
1308 JSStringRelease(EvilExceptionObjectIString
);
1310 JSObjectRef EmptyObject
= JSObjectMake(context
, EmptyObject_class(context
), NULL
);
1311 JSStringRef EmptyObjectIString
= JSStringCreateWithUTF8CString("EmptyObject");
1312 JSObjectSetProperty(context
, globalObject
, EmptyObjectIString
, EmptyObject
, kJSPropertyAttributeNone
, NULL
);
1313 JSStringRelease(EmptyObjectIString
);
1315 JSStringRef lengthStr
= JSStringCreateWithUTF8CString("length");
1316 JSObjectRef aStackRef
= JSObjectMakeArray(context
, 0, 0, 0);
1317 aHeapRef
= aStackRef
;
1318 JSObjectSetProperty(context
, aHeapRef
, lengthStr
, JSValueMakeNumber(context
, 10), 0, 0);
1319 JSStringRef privatePropertyName
= JSStringCreateWithUTF8CString("privateProperty");
1320 if (!JSObjectSetPrivateProperty(context
, myObject
, privatePropertyName
, aHeapRef
)) {
1321 printf("FAIL: Could not set private property.\n");
1324 printf("PASS: Set private property.\n");
1326 if (JSObjectSetPrivateProperty(context
, aHeapRef
, privatePropertyName
, aHeapRef
)) {
1327 printf("FAIL: JSObjectSetPrivateProperty should fail on non-API objects.\n");
1330 printf("PASS: Did not allow JSObjectSetPrivateProperty on a non-API object.\n");
1331 if (JSObjectGetPrivateProperty(context
, myObject
, privatePropertyName
) != aHeapRef
) {
1332 printf("FAIL: Could not retrieve private property.\n");
1335 printf("PASS: Retrieved private property.\n");
1336 if (JSObjectGetPrivateProperty(context
, aHeapRef
, privatePropertyName
)) {
1337 printf("FAIL: JSObjectGetPrivateProperty should return NULL when called on a non-API object.\n");
1340 printf("PASS: JSObjectGetPrivateProperty return NULL.\n");
1342 if (JSObjectGetProperty(context
, myObject
, privatePropertyName
, 0) == aHeapRef
) {
1343 printf("FAIL: Accessed private property through ordinary property lookup.\n");
1346 printf("PASS: Cannot access private property through ordinary property lookup.\n");
1348 JSGarbageCollect(context
);
1350 for (int i
= 0; i
< 10000; i
++)
1351 JSObjectMake(context
, 0, 0);
1353 aHeapRef
= JSValueToObject(context
, JSObjectGetPrivateProperty(context
, myObject
, privatePropertyName
), 0);
1354 if (JSValueToNumber(context
, JSObjectGetProperty(context
, aHeapRef
, lengthStr
, 0), 0) != 10) {
1355 printf("FAIL: Private property has been collected.\n");
1358 printf("PASS: Private property does not appear to have been collected.\n");
1359 JSStringRelease(lengthStr
);
1361 if (!JSObjectSetPrivateProperty(context
, myObject
, privatePropertyName
, 0)) {
1362 printf("FAIL: Could not set private property to NULL.\n");
1365 printf("PASS: Set private property to NULL.\n");
1366 if (JSObjectGetPrivateProperty(context
, myObject
, privatePropertyName
)) {
1367 printf("FAIL: Could not retrieve private property.\n");
1370 printf("PASS: Retrieved private property.\n");
1372 JSStringRef nullJSON
= JSStringCreateWithUTF8CString(0);
1373 JSValueRef nullJSONObject
= JSValueMakeFromJSONString(context
, nullJSON
);
1374 if (nullJSONObject
) {
1375 printf("FAIL: Did not parse null String as JSON correctly\n");
1378 printf("PASS: Parsed null String as JSON correctly.\n");
1379 JSStringRelease(nullJSON
);
1381 JSStringRef validJSON
= JSStringCreateWithUTF8CString("{\"aProperty\":true}");
1382 JSValueRef jsonObject
= JSValueMakeFromJSONString(context
, validJSON
);
1383 JSStringRelease(validJSON
);
1384 if (!JSValueIsObject(context
, jsonObject
)) {
1385 printf("FAIL: Did not parse valid JSON correctly\n");
1388 printf("PASS: Parsed valid JSON string.\n");
1389 JSStringRef propertyName
= JSStringCreateWithUTF8CString("aProperty");
1390 assertEqualsAsBoolean(JSObjectGetProperty(context
, JSValueToObject(context
, jsonObject
, 0), propertyName
, 0), true);
1391 JSStringRelease(propertyName
);
1392 JSStringRef invalidJSON
= JSStringCreateWithUTF8CString("fail!");
1393 if (JSValueMakeFromJSONString(context
, invalidJSON
)) {
1394 printf("FAIL: Should return null for invalid JSON data\n");
1397 printf("PASS: Correctly returned null for invalid JSON data.\n");
1398 JSValueRef exception
;
1399 JSStringRef str
= JSValueCreateJSONString(context
, jsonObject
, 0, 0);
1400 if (!JSStringIsEqualToUTF8CString(str
, "{\"aProperty\":true}")) {
1401 printf("FAIL: Did not correctly serialise with indent of 0.\n");
1404 printf("PASS: Correctly serialised with indent of 0.\n");
1405 JSStringRelease(str
);
1407 str
= JSValueCreateJSONString(context
, jsonObject
, 4, 0);
1408 if (!JSStringIsEqualToUTF8CString(str
, "{\n \"aProperty\": true\n}")) {
1409 printf("FAIL: Did not correctly serialise with indent of 4.\n");
1412 printf("PASS: Correctly serialised with indent of 4.\n");
1413 JSStringRelease(str
);
1415 str
= JSStringCreateWithUTF8CString("({get a(){ throw '';}})");
1416 JSValueRef unstringifiableObj
= JSEvaluateScript(context
, str
, NULL
, NULL
, 1, NULL
);
1417 JSStringRelease(str
);
1419 str
= JSValueCreateJSONString(context
, unstringifiableObj
, 4, 0);
1421 printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
1422 JSStringRelease(str
);
1425 printf("PASS: returned null when attempting to serialize unserializable value.\n");
1427 str
= JSValueCreateJSONString(context
, unstringifiableObj
, 4, &exception
);
1429 printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
1430 JSStringRelease(str
);
1433 printf("PASS: returned null when attempting to serialize unserializable value.\n");
1435 printf("FAIL: Did not set exception on serialisation error\n");
1438 printf("PASS: set exception on serialisation error\n");
1439 // Conversions that throw exceptions
1441 ASSERT(NULL
== JSValueToObject(context
, jsNull
, &exception
));
1445 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
1446 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
1447 // After that's resolved, we can remove these casts
1448 ASSERT(isnan((float)JSValueToNumber(context
, jsObjectNoProto
, &exception
)));
1452 ASSERT(!JSValueToStringCopy(context
, jsObjectNoProto
, &exception
));
1455 ASSERT(JSValueToBoolean(context
, myObject
));
1458 ASSERT(!JSValueIsEqual(context
, jsObjectNoProto
, JSValueMakeNumber(context
, 1), &exception
));
1462 JSObjectGetPropertyAtIndex(context
, myObject
, 0, &exception
);
1463 ASSERT(1 == JSValueToNumber(context
, exception
, NULL
));
1465 assertEqualsAsBoolean(jsUndefined
, false);
1466 assertEqualsAsBoolean(jsNull
, false);
1467 assertEqualsAsBoolean(jsTrue
, true);
1468 assertEqualsAsBoolean(jsFalse
, false);
1469 assertEqualsAsBoolean(jsZero
, false);
1470 assertEqualsAsBoolean(jsOne
, true);
1471 assertEqualsAsBoolean(jsOneThird
, true);
1472 assertEqualsAsBoolean(jsEmptyString
, false);
1473 assertEqualsAsBoolean(jsOneString
, true);
1474 assertEqualsAsBoolean(jsCFString
, true);
1475 assertEqualsAsBoolean(jsCFStringWithCharacters
, true);
1476 assertEqualsAsBoolean(jsCFEmptyString
, false);
1477 assertEqualsAsBoolean(jsCFEmptyStringWithCharacters
, false);
1479 assertEqualsAsNumber(jsUndefined
, nan(""));
1480 assertEqualsAsNumber(jsNull
, 0);
1481 assertEqualsAsNumber(jsTrue
, 1);
1482 assertEqualsAsNumber(jsFalse
, 0);
1483 assertEqualsAsNumber(jsZero
, 0);
1484 assertEqualsAsNumber(jsOne
, 1);
1485 assertEqualsAsNumber(jsOneThird
, 1.0 / 3.0);
1486 assertEqualsAsNumber(jsEmptyString
, 0);
1487 assertEqualsAsNumber(jsOneString
, 1);
1488 assertEqualsAsNumber(jsCFString
, nan(""));
1489 assertEqualsAsNumber(jsCFStringWithCharacters
, nan(""));
1490 assertEqualsAsNumber(jsCFEmptyString
, 0);
1491 assertEqualsAsNumber(jsCFEmptyStringWithCharacters
, 0);
1492 ASSERT(sizeof(JSChar
) == sizeof(UniChar
));
1494 assertEqualsAsCharactersPtr(jsUndefined
, "undefined");
1495 assertEqualsAsCharactersPtr(jsNull
, "null");
1496 assertEqualsAsCharactersPtr(jsTrue
, "true");
1497 assertEqualsAsCharactersPtr(jsFalse
, "false");
1498 assertEqualsAsCharactersPtr(jsZero
, "0");
1499 assertEqualsAsCharactersPtr(jsOne
, "1");
1500 assertEqualsAsCharactersPtr(jsOneThird
, "0.3333333333333333");
1501 assertEqualsAsCharactersPtr(jsEmptyString
, "");
1502 assertEqualsAsCharactersPtr(jsOneString
, "1");
1503 assertEqualsAsCharactersPtr(jsCFString
, "A");
1504 assertEqualsAsCharactersPtr(jsCFStringWithCharacters
, "A");
1505 assertEqualsAsCharactersPtr(jsCFEmptyString
, "");
1506 assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters
, "");
1508 assertEqualsAsUTF8String(jsUndefined
, "undefined");
1509 assertEqualsAsUTF8String(jsNull
, "null");
1510 assertEqualsAsUTF8String(jsTrue
, "true");
1511 assertEqualsAsUTF8String(jsFalse
, "false");
1512 assertEqualsAsUTF8String(jsZero
, "0");
1513 assertEqualsAsUTF8String(jsOne
, "1");
1514 assertEqualsAsUTF8String(jsOneThird
, "0.3333333333333333");
1515 assertEqualsAsUTF8String(jsEmptyString
, "");
1516 assertEqualsAsUTF8String(jsOneString
, "1");
1517 assertEqualsAsUTF8String(jsCFString
, "A");
1518 assertEqualsAsUTF8String(jsCFStringWithCharacters
, "A");
1519 assertEqualsAsUTF8String(jsCFEmptyString
, "");
1520 assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters
, "");
1522 checkConstnessInJSObjectNames();
1524 ASSERT(JSValueIsStrictEqual(context
, jsTrue
, jsTrue
));
1525 ASSERT(!JSValueIsStrictEqual(context
, jsOne
, jsOneString
));
1527 ASSERT(JSValueIsEqual(context
, jsOne
, jsOneString
, NULL
));
1528 ASSERT(!JSValueIsEqual(context
, jsTrue
, jsFalse
, NULL
));
1530 CFStringRef cfJSString
= JSStringCopyCFString(kCFAllocatorDefault
, jsCFIString
);
1531 CFStringRef cfJSEmptyString
= JSStringCopyCFString(kCFAllocatorDefault
, jsCFEmptyIString
);
1532 ASSERT(CFEqual(cfJSString
, cfString
));
1533 ASSERT(CFEqual(cfJSEmptyString
, cfEmptyString
));
1534 CFRelease(cfJSString
);
1535 CFRelease(cfJSEmptyString
);
1537 CFRelease(cfString
);
1538 CFRelease(cfEmptyString
);
1540 jsGlobalValue
= JSObjectMake(context
, NULL
, NULL
);
1541 makeGlobalNumberValue(context
);
1542 JSValueProtect(context
, jsGlobalValue
);
1543 JSGarbageCollect(context
);
1544 ASSERT(JSValueIsObject(context
, jsGlobalValue
));
1545 JSValueUnprotect(context
, jsGlobalValue
);
1546 JSValueUnprotect(context
, jsNumberValue
);
1548 JSStringRef goodSyntax
= JSStringCreateWithUTF8CString("x = 1;");
1549 const char* badSyntaxConstant
= "x := 1;";
1550 JSStringRef badSyntax
= JSStringCreateWithUTF8CString(badSyntaxConstant
);
1551 ASSERT(JSCheckScriptSyntax(context
, goodSyntax
, NULL
, 0, NULL
));
1552 ASSERT(!JSCheckScriptSyntax(context
, badSyntax
, NULL
, 0, NULL
));
1553 ASSERT(!JSScriptCreateFromString(contextGroup
, 0, 0, badSyntax
, 0, 0));
1554 ASSERT(!JSScriptCreateReferencingImmortalASCIIText(contextGroup
, 0, 0, badSyntaxConstant
, strlen(badSyntaxConstant
), 0, 0));
1561 result
= JSEvaluateScript(context
, goodSyntax
, NULL
, NULL
, 1, NULL
);
1563 ASSERT(JSValueIsEqual(context
, result
, jsOne
, NULL
));
1566 result
= JSEvaluateScript(context
, badSyntax
, NULL
, NULL
, 1, &exception
);
1568 ASSERT(JSValueIsObject(context
, exception
));
1570 JSStringRef array
= JSStringCreateWithUTF8CString("Array");
1571 JSObjectRef arrayConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, globalObject
, array
, NULL
), NULL
);
1572 JSStringRelease(array
);
1573 result
= JSObjectCallAsConstructor(context
, arrayConstructor
, 0, NULL
, NULL
);
1575 ASSERT(JSValueIsObject(context
, result
));
1576 ASSERT(JSValueIsInstanceOfConstructor(context
, result
, arrayConstructor
, NULL
));
1577 ASSERT(!JSValueIsInstanceOfConstructor(context
, JSValueMakeNull(context
), arrayConstructor
, NULL
));
1579 o
= JSValueToObject(context
, result
, NULL
);
1581 ASSERT(JSValueIsUndefined(context
, JSObjectGetPropertyAtIndex(context
, o
, 0, &exception
)));
1584 JSObjectSetPropertyAtIndex(context
, o
, 0, JSValueMakeNumber(context
, 1), &exception
);
1588 ASSERT(1 == JSValueToNumber(context
, JSObjectGetPropertyAtIndex(context
, o
, 0, &exception
), &exception
));
1591 JSStringRef functionBody
;
1592 JSObjectRef function
;
1595 functionBody
= JSStringCreateWithUTF8CString("rreturn Array;");
1596 JSStringRef line
= JSStringCreateWithUTF8CString("line");
1597 ASSERT(!JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
));
1598 ASSERT(JSValueIsObject(context
, exception
));
1599 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), line
, NULL
);
1600 assertEqualsAsNumber(v
, 2);
1601 JSStringRelease(functionBody
);
1602 JSStringRelease(line
);
1605 functionBody
= JSStringCreateWithUTF8CString("rreturn Array;");
1606 line
= JSStringCreateWithUTF8CString("line");
1607 ASSERT(!JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, -42, &exception
));
1608 ASSERT(JSValueIsObject(context
, exception
));
1609 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), line
, NULL
);
1610 assertEqualsAsNumber(v
, 2);
1611 JSStringRelease(functionBody
);
1612 JSStringRelease(line
);
1615 functionBody
= JSStringCreateWithUTF8CString("// Line one.\nrreturn Array;");
1616 line
= JSStringCreateWithUTF8CString("line");
1617 ASSERT(!JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
));
1618 ASSERT(JSValueIsObject(context
, exception
));
1619 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), line
, NULL
);
1620 assertEqualsAsNumber(v
, 3);
1621 JSStringRelease(functionBody
);
1622 JSStringRelease(line
);
1625 functionBody
= JSStringCreateWithUTF8CString("return Array;");
1626 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
);
1627 JSStringRelease(functionBody
);
1629 ASSERT(JSObjectIsFunction(context
, function
));
1630 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1632 ASSERT(JSValueIsEqual(context
, v
, arrayConstructor
, NULL
));
1635 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, jsEmptyIString
, NULL
, 0, &exception
);
1637 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, &exception
);
1638 ASSERT(v
&& !exception
);
1639 ASSERT(JSValueIsUndefined(context
, v
));
1643 JSStringRef foo
= JSStringCreateWithUTF8CString("foo");
1644 JSStringRef argumentNames
[] = { foo
};
1645 functionBody
= JSStringCreateWithUTF8CString("return foo;");
1646 function
= JSObjectMakeFunction(context
, foo
, 1, argumentNames
, functionBody
, NULL
, 1, &exception
);
1647 ASSERT(function
&& !exception
);
1648 JSValueRef arguments
[] = { JSValueMakeNumber(context
, 2) };
1649 JSObjectCallAsFunction(context
, function
, NULL
, 1, arguments
, &exception
);
1650 JSStringRelease(foo
);
1651 JSStringRelease(functionBody
);
1653 string
= JSValueToStringCopy(context
, function
, NULL
);
1654 assertEqualsAsUTF8String(JSValueMakeString(context
, string
), "function foo(foo) {\nreturn foo;\n}");
1655 JSStringRelease(string
);
1657 JSStringRef print
= JSStringCreateWithUTF8CString("print");
1658 JSObjectRef printFunction
= JSObjectMakeFunctionWithCallback(context
, print
, print_callAsFunction
);
1659 JSObjectSetProperty(context
, globalObject
, print
, printFunction
, kJSPropertyAttributeNone
, NULL
);
1660 JSStringRelease(print
);
1662 ASSERT(!JSObjectSetPrivate(printFunction
, (void*)1));
1663 ASSERT(!JSObjectGetPrivate(printFunction
));
1665 JSStringRef myConstructorIString
= JSStringCreateWithUTF8CString("MyConstructor");
1666 JSObjectRef myConstructor
= JSObjectMakeConstructor(context
, NULL
, myConstructor_callAsConstructor
);
1667 JSObjectSetProperty(context
, globalObject
, myConstructorIString
, myConstructor
, kJSPropertyAttributeNone
, NULL
);
1668 JSStringRelease(myConstructorIString
);
1670 JSStringRef myBadConstructorIString
= JSStringCreateWithUTF8CString("MyBadConstructor");
1671 JSObjectRef myBadConstructor
= JSObjectMakeConstructor(context
, NULL
, myBadConstructor_callAsConstructor
);
1672 JSObjectSetProperty(context
, globalObject
, myBadConstructorIString
, myBadConstructor
, kJSPropertyAttributeNone
, NULL
);
1673 JSStringRelease(myBadConstructorIString
);
1675 ASSERT(!JSObjectSetPrivate(myConstructor
, (void*)1));
1676 ASSERT(!JSObjectGetPrivate(myConstructor
));
1678 string
= JSStringCreateWithUTF8CString("Base");
1679 JSObjectRef baseConstructor
= JSObjectMakeConstructor(context
, Base_class(context
), NULL
);
1680 JSObjectSetProperty(context
, globalObject
, string
, baseConstructor
, kJSPropertyAttributeNone
, NULL
);
1681 JSStringRelease(string
);
1683 string
= JSStringCreateWithUTF8CString("Derived");
1684 JSObjectRef derivedConstructor
= JSObjectMakeConstructor(context
, Derived_class(context
), NULL
);
1685 JSObjectSetProperty(context
, globalObject
, string
, derivedConstructor
, kJSPropertyAttributeNone
, NULL
);
1686 JSStringRelease(string
);
1688 string
= JSStringCreateWithUTF8CString("Derived2");
1689 JSObjectRef derived2Constructor
= JSObjectMakeConstructor(context
, Derived2_class(context
), NULL
);
1690 JSObjectSetProperty(context
, globalObject
, string
, derived2Constructor
, kJSPropertyAttributeNone
, NULL
);
1691 JSStringRelease(string
);
1693 o
= JSObjectMake(context
, NULL
, NULL
);
1694 JSObjectSetProperty(context
, o
, jsOneIString
, JSValueMakeNumber(context
, 1), kJSPropertyAttributeNone
, NULL
);
1695 JSObjectSetProperty(context
, o
, jsCFIString
, JSValueMakeNumber(context
, 1), kJSPropertyAttributeDontEnum
, NULL
);
1696 JSPropertyNameArrayRef nameArray
= JSObjectCopyPropertyNames(context
, o
);
1697 size_t expectedCount
= JSPropertyNameArrayGetCount(nameArray
);
1699 for (count
= 0; count
< expectedCount
; ++count
)
1700 JSPropertyNameArrayGetNameAtIndex(nameArray
, count
);
1701 JSPropertyNameArrayRelease(nameArray
);
1702 ASSERT(count
== 1); // jsCFString should not be enumerated
1704 JSValueRef argumentsArrayValues
[] = { JSValueMakeNumber(context
, 10), JSValueMakeNumber(context
, 20) };
1705 o
= JSObjectMakeArray(context
, sizeof(argumentsArrayValues
) / sizeof(JSValueRef
), argumentsArrayValues
, NULL
);
1706 string
= JSStringCreateWithUTF8CString("length");
1707 v
= JSObjectGetProperty(context
, o
, string
, NULL
);
1708 assertEqualsAsNumber(v
, 2);
1709 v
= JSObjectGetPropertyAtIndex(context
, o
, 0, NULL
);
1710 assertEqualsAsNumber(v
, 10);
1711 v
= JSObjectGetPropertyAtIndex(context
, o
, 1, NULL
);
1712 assertEqualsAsNumber(v
, 20);
1714 o
= JSObjectMakeArray(context
, 0, NULL
, NULL
);
1715 v
= JSObjectGetProperty(context
, o
, string
, NULL
);
1716 assertEqualsAsNumber(v
, 0);
1717 JSStringRelease(string
);
1719 JSValueRef argumentsDateValues
[] = { JSValueMakeNumber(context
, 0) };
1720 o
= JSObjectMakeDate(context
, 1, argumentsDateValues
, NULL
);
1721 if (timeZoneIsPST())
1722 assertEqualsAsUTF8String(o
, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
1724 string
= JSStringCreateWithUTF8CString("an error message");
1725 JSValueRef argumentsErrorValues
[] = { JSValueMakeString(context
, string
) };
1726 o
= JSObjectMakeError(context
, 1, argumentsErrorValues
, NULL
);
1727 assertEqualsAsUTF8String(o
, "Error: an error message");
1728 JSStringRelease(string
);
1730 string
= JSStringCreateWithUTF8CString("foo");
1731 JSStringRef string2
= JSStringCreateWithUTF8CString("gi");
1732 JSValueRef argumentsRegExpValues
[] = { JSValueMakeString(context
, string
), JSValueMakeString(context
, string2
) };
1733 o
= JSObjectMakeRegExp(context
, 2, argumentsRegExpValues
, NULL
);
1734 assertEqualsAsUTF8String(o
, "/foo/gi");
1735 JSStringRelease(string
);
1736 JSStringRelease(string2
);
1738 JSClassDefinition nullDefinition
= kJSClassDefinitionEmpty
;
1739 nullDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
1740 JSClassRef nullClass
= JSClassCreate(&nullDefinition
);
1741 JSClassRelease(nullClass
);
1743 nullDefinition
= kJSClassDefinitionEmpty
;
1744 nullClass
= JSClassCreate(&nullDefinition
);
1745 JSClassRelease(nullClass
);
1747 functionBody
= JSStringCreateWithUTF8CString("return this;");
1748 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, NULL
);
1749 JSStringRelease(functionBody
);
1750 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1751 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1752 v
= JSObjectCallAsFunction(context
, function
, o
, 0, NULL
, NULL
);
1753 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1755 functionBody
= JSStringCreateWithUTF8CString("return eval(\"this\");");
1756 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, NULL
);
1757 JSStringRelease(functionBody
);
1758 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1759 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1760 v
= JSObjectCallAsFunction(context
, function
, o
, 0, NULL
, NULL
);
1761 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1763 const char* thisScript
= "this;";
1764 JSStringRef script
= JSStringCreateWithUTF8CString(thisScript
);
1765 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1766 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1767 v
= JSEvaluateScript(context
, script
, o
, NULL
, 1, NULL
);
1768 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1769 JSStringRelease(script
);
1771 JSScriptRef scriptObject
= JSScriptCreateReferencingImmortalASCIIText(contextGroup
, 0, 0, thisScript
, strlen(thisScript
), 0, 0);
1772 v
= JSScriptEvaluate(context
, scriptObject
, NULL
, NULL
);
1773 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1774 v
= JSScriptEvaluate(context
, scriptObject
, o
, NULL
);
1775 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1776 JSScriptRelease(scriptObject
);
1778 script
= JSStringCreateWithUTF8CString("eval(this);");
1779 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1780 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1781 v
= JSEvaluateScript(context
, script
, o
, NULL
, 1, NULL
);
1782 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1783 JSStringRelease(script
);
1785 script
= JSStringCreateWithUTF8CString("[ ]");
1786 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1787 ASSERT(JSValueIsArray(context
, v
));
1788 JSStringRelease(script
);
1790 script
= JSStringCreateWithUTF8CString("new Date");
1791 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1792 ASSERT(JSValueIsDate(context
, v
));
1793 JSStringRelease(script
);
1796 script
= JSStringCreateWithUTF8CString("rreturn Array;");
1797 JSStringRef sourceURL
= JSStringCreateWithUTF8CString("file:///foo/bar.js");
1798 JSStringRef sourceURLKey
= JSStringCreateWithUTF8CString("sourceURL");
1799 JSEvaluateScript(context
, script
, NULL
, sourceURL
, 1, &exception
);
1801 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), sourceURLKey
, NULL
);
1802 assertEqualsAsUTF8String(v
, "file:///foo/bar.js");
1803 JSStringRelease(script
);
1804 JSStringRelease(sourceURL
);
1805 JSStringRelease(sourceURLKey
);
1807 // Verify that creating a constructor for a class with no static functions does not trigger
1808 // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
1809 nullDefinition
= kJSClassDefinitionEmpty
;
1810 nullClass
= JSClassCreate(&nullDefinition
);
1811 JSObjectMakeConstructor(context
, nullClass
, 0);
1812 JSClassRelease(nullClass
);
1814 char* scriptUTF8
= createStringWithContentsOfFile(scriptPath
);
1816 printf("FAIL: Test script could not be loaded.\n");
1819 JSStringRef url
= JSStringCreateWithUTF8CString(scriptPath
);
1820 JSStringRef script
= JSStringCreateWithUTF8CString(scriptUTF8
);
1821 JSStringRef errorMessage
= 0;
1823 JSScriptRef scriptObject
= JSScriptCreateFromString(contextGroup
, url
, 1, script
, &errorMessage
, &errorLine
);
1824 ASSERT((!scriptObject
) != (!errorMessage
));
1825 if (!scriptObject
) {
1826 printf("FAIL: Test script did not parse\n\t%s:%d\n\t", scriptPath
, errorLine
);
1827 CFStringRef errorCF
= JSStringCopyCFString(kCFAllocatorDefault
, errorMessage
);
1830 JSStringRelease(errorMessage
);
1834 JSStringRelease(script
);
1836 result
= scriptObject
? JSScriptEvaluate(context
, scriptObject
, 0, &exception
) : 0;
1837 if (result
&& JSValueIsUndefined(context
, result
))
1838 printf("PASS: Test script executed successfully.\n");
1840 printf("FAIL: Test script returned unexpected value:\n");
1841 JSStringRef exceptionIString
= JSValueToStringCopy(context
, exception
, NULL
);
1842 CFStringRef exceptionCF
= JSStringCopyCFString(kCFAllocatorDefault
, exceptionIString
);
1843 CFShow(exceptionCF
);
1844 CFRelease(exceptionCF
);
1845 JSStringRelease(exceptionIString
);
1848 JSScriptRelease(scriptObject
);
1852 // Check Promise is not exposed.
1854 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
1856 JSStringRef promiseProperty
= JSStringCreateWithUTF8CString("Promise");
1857 ASSERT(!JSObjectHasProperty(context
, globalObject
, promiseProperty
));
1858 JSStringRelease(promiseProperty
);
1861 JSStringRef script
= JSStringCreateWithUTF8CString("typeof Promise");
1862 JSStringRef undefined
= JSStringCreateWithUTF8CString("undefined");
1863 JSValueRef value
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1864 ASSERT(JSValueIsString(context
, value
));
1865 JSStringRef valueAsString
= JSValueToStringCopy(context
, value
, NULL
);
1866 ASSERT(JSStringIsEqual(valueAsString
, undefined
));
1867 JSStringRelease(valueAsString
);
1868 JSStringRelease(undefined
);
1869 JSStringRelease(script
);
1871 printf("PASS: Promise is not exposed under JSContext API.\n");
1875 failed
= testExecutionTimeLimit() || failed
;
1876 #endif /* OS(DARWIN) */
1877 failed
= testGlobalContextWithFinalizer() || failed
;
1879 // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
1883 globalObject
= NULL
;
1884 myConstructor
= NULL
;
1886 JSStringRelease(jsEmptyIString
);
1887 JSStringRelease(jsOneIString
);
1888 JSStringRelease(jsCFIString
);
1889 JSStringRelease(jsCFEmptyIString
);
1890 JSStringRelease(jsCFIStringWithCharacters
);
1891 JSStringRelease(jsCFEmptyIStringWithCharacters
);
1892 JSStringRelease(goodSyntax
);
1893 JSStringRelease(badSyntax
);
1895 JSGlobalContextRelease(context
);
1896 JSClassRelease(globalObjectClass
);
1898 // Test for an infinite prototype chain that used to be created. This test
1899 // passes if the call to JSObjectHasProperty() does not hang.
1901 JSClassDefinition prototypeLoopClassDefinition
= kJSClassDefinitionEmpty
;
1902 prototypeLoopClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
1903 JSClassRef prototypeLoopClass
= JSClassCreate(&prototypeLoopClassDefinition
);
1904 JSGlobalContextRef prototypeLoopContext
= JSGlobalContextCreateInGroup(NULL
, prototypeLoopClass
);
1906 JSStringRef nameProperty
= JSStringCreateWithUTF8CString("name");
1907 JSObjectHasProperty(prototypeLoopContext
, JSContextGetGlobalObject(prototypeLoopContext
), nameProperty
);
1909 JSGlobalContextRelease(prototypeLoopContext
);
1910 JSClassRelease(prototypeLoopClass
);
1912 printf("PASS: Infinite prototype chain does not occur.\n");
1914 if (checkForCycleInPrototypeChain())
1915 printf("PASS: A cycle in a prototype chain can't be created.\n");
1917 printf("FAIL: A cycle in a prototype chain can be created.\n");
1920 if (valueToObjectExceptionTest())
1921 printf("PASS: throwException did not crash when handling an error with appendMessageToError set and no codeBlock available.\n");
1923 if (globalContextNameTest())
1924 printf("PASS: global context name behaves as expected.\n");
1926 customGlobalObjectClassTest();
1927 globalObjectSetPrototypeTest();
1928 globalObjectPrivatePropertyTest();
1931 printf("FAIL: Some tests failed.\n");
1935 printf("PASS: Program exited normally.\n");
1939 static char* createStringWithContentsOfFile(const char* fileName
)
1943 size_t buffer_size
= 0;
1944 size_t buffer_capacity
= 1024;
1945 buffer
= (char*)malloc(buffer_capacity
);
1947 FILE* f
= fopen(fileName
, "r");
1949 fprintf(stderr
, "Could not open file: %s\n", fileName
);
1954 while (!feof(f
) && !ferror(f
)) {
1955 buffer_size
+= fread(buffer
+ buffer_size
, 1, buffer_capacity
- buffer_size
, f
);
1956 if (buffer_size
== buffer_capacity
) { // guarantees space for trailing '\0'
1957 buffer_capacity
*= 2;
1958 buffer
= (char*)realloc(buffer
, buffer_capacity
);
1962 ASSERT(buffer_size
< buffer_capacity
);
1965 buffer
[buffer_size
] = '\0';
1971 extern "C" __declspec(dllexport
) int WINAPI
dllLauncherEntryPoint(int argc
, const char* argv
[])
1973 return main(argc
, const_cast<char**>(argv
));