2 * Copyright (C) 2006 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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 "JavaScriptCore.h"
27 #include "JSBasePrivate.h"
28 #include "JSContextRefPrivate.h"
30 #define ASSERT_DISABLED 0
31 #include <wtf/Assertions.h>
32 #include <wtf/UnusedParam.h>
36 #include <wtf/MathExtras.h>
38 static double nan(const char*)
40 return std::numeric_limits
<double>::quiet_NaN();
45 static JSGlobalContextRef context
;
47 static void assertEqualsAsBoolean(JSValueRef value
, bool expectedValue
)
49 if (JSValueToBoolean(context
, value
) != expectedValue
) {
50 fprintf(stderr
, "assertEqualsAsBoolean failed: %p, %d\n", value
, expectedValue
);
55 static void assertEqualsAsNumber(JSValueRef value
, double expectedValue
)
57 double number
= JSValueToNumber(context
, value
, NULL
);
59 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
60 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
61 // After that's resolved, we can remove these casts
62 if (number
!= expectedValue
&& !(isnan((float)number
) && isnan((float)expectedValue
))) {
63 fprintf(stderr
, "assertEqualsAsNumber failed: %p, %lf\n", value
, expectedValue
);
68 static void assertEqualsAsUTF8String(JSValueRef value
, const char* expectedValue
)
70 JSStringRef valueAsString
= JSValueToStringCopy(context
, value
, NULL
);
72 size_t jsSize
= JSStringGetMaximumUTF8CStringSize(valueAsString
);
73 char* jsBuffer
= (char*)malloc(jsSize
);
74 JSStringGetUTF8CString(valueAsString
, jsBuffer
, jsSize
);
77 for (i
= 0; jsBuffer
[i
]; i
++) {
78 if (jsBuffer
[i
] != expectedValue
[i
]) {
79 fprintf(stderr
, "assertEqualsAsUTF8String failed at character %d: %c(%d) != %c(%d)\n", i
, jsBuffer
[i
], jsBuffer
[i
], expectedValue
[i
], expectedValue
[i
]);
84 if (jsSize
< strlen(jsBuffer
) + 1) {
85 fprintf(stderr
, "assertEqualsAsUTF8String failed: jsSize was too small\n");
90 JSStringRelease(valueAsString
);
93 static void assertEqualsAsCharactersPtr(JSValueRef value
, const char* expectedValue
)
95 JSStringRef valueAsString
= JSValueToStringCopy(context
, value
, NULL
);
97 size_t jsLength
= JSStringGetLength(valueAsString
);
98 const JSChar
* jsBuffer
= JSStringGetCharactersPtr(valueAsString
);
100 CFStringRef expectedValueAsCFString
= CFStringCreateWithCString(kCFAllocatorDefault
,
102 kCFStringEncodingUTF8
);
103 CFIndex cfLength
= CFStringGetLength(expectedValueAsCFString
);
104 UniChar
* cfBuffer
= (UniChar
*)malloc(cfLength
* sizeof(UniChar
));
105 CFStringGetCharacters(expectedValueAsCFString
, CFRangeMake(0, cfLength
), cfBuffer
);
106 CFRelease(expectedValueAsCFString
);
108 if (memcmp(jsBuffer
, cfBuffer
, cfLength
* sizeof(UniChar
)) != 0) {
109 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
113 if (jsLength
!= (size_t)cfLength
) {
114 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength
, cfLength
);
119 JSStringRelease(valueAsString
);
122 static bool timeZoneIsPST()
124 char timeZoneName
[70];
126 memset(>m
, 0, sizeof(gtm
));
127 strftime(timeZoneName
, sizeof(timeZoneName
), "%Z", >m
);
129 return 0 == strcmp("PST", timeZoneName
);
132 static JSValueRef jsGlobalValue
; // non-stack value for testing JSValueProtect()
134 /* MyObject pseudo-class */
136 static bool MyObject_hasProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
)
138 UNUSED_PARAM(context
);
139 UNUSED_PARAM(object
);
141 if (JSStringIsEqualToUTF8CString(propertyName
, "alwaysOne")
142 || JSStringIsEqualToUTF8CString(propertyName
, "cantFind")
143 || JSStringIsEqualToUTF8CString(propertyName
, "throwOnGet")
144 || JSStringIsEqualToUTF8CString(propertyName
, "myPropertyName")
145 || JSStringIsEqualToUTF8CString(propertyName
, "hasPropertyLie")
146 || JSStringIsEqualToUTF8CString(propertyName
, "0")) {
153 static JSValueRef
MyObject_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
155 UNUSED_PARAM(context
);
156 UNUSED_PARAM(object
);
158 if (JSStringIsEqualToUTF8CString(propertyName
, "alwaysOne")) {
159 return JSValueMakeNumber(context
, 1);
162 if (JSStringIsEqualToUTF8CString(propertyName
, "myPropertyName")) {
163 return JSValueMakeNumber(context
, 1);
166 if (JSStringIsEqualToUTF8CString(propertyName
, "cantFind")) {
167 return JSValueMakeUndefined(context
);
170 if (JSStringIsEqualToUTF8CString(propertyName
, "hasPropertyLie")) {
174 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnGet")) {
175 return JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
178 if (JSStringIsEqualToUTF8CString(propertyName
, "0")) {
179 *exception
= JSValueMakeNumber(context
, 1);
180 return JSValueMakeNumber(context
, 1);
183 return JSValueMakeNull(context
);
186 static bool MyObject_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
188 UNUSED_PARAM(context
);
189 UNUSED_PARAM(object
);
191 UNUSED_PARAM(exception
);
193 if (JSStringIsEqualToUTF8CString(propertyName
, "cantSet"))
194 return true; // pretend we set the property in order to swallow it
196 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnSet")) {
197 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
203 static bool MyObject_deleteProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
205 UNUSED_PARAM(context
);
206 UNUSED_PARAM(object
);
208 if (JSStringIsEqualToUTF8CString(propertyName
, "cantDelete"))
211 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnDelete")) {
212 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
219 static void MyObject_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef propertyNames
)
221 UNUSED_PARAM(context
);
222 UNUSED_PARAM(object
);
224 JSStringRef propertyName
;
226 propertyName
= JSStringCreateWithUTF8CString("alwaysOne");
227 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
228 JSStringRelease(propertyName
);
230 propertyName
= JSStringCreateWithUTF8CString("myPropertyName");
231 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
232 JSStringRelease(propertyName
);
235 static JSValueRef
MyObject_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
237 UNUSED_PARAM(context
);
238 UNUSED_PARAM(object
);
239 UNUSED_PARAM(thisObject
);
240 UNUSED_PARAM(exception
);
242 if (argumentCount
> 0 && JSValueIsString(context
, arguments
[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, arguments
[0], 0), "throwOnCall")) {
243 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
244 return JSValueMakeUndefined(context
);
247 if (argumentCount
> 0 && JSValueIsStrictEqual(context
, arguments
[0], JSValueMakeNumber(context
, 0)))
248 return JSValueMakeNumber(context
, 1);
250 return JSValueMakeUndefined(context
);
253 static JSObjectRef
MyObject_callAsConstructor(JSContextRef context
, JSObjectRef object
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
255 UNUSED_PARAM(context
);
256 UNUSED_PARAM(object
);
258 if (argumentCount
> 0 && JSValueIsString(context
, arguments
[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, arguments
[0], 0), "throwOnConstruct")) {
259 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
263 if (argumentCount
> 0 && JSValueIsStrictEqual(context
, arguments
[0], JSValueMakeNumber(context
, 0)))
264 return JSValueToObject(context
, JSValueMakeNumber(context
, 1), exception
);
266 return JSValueToObject(context
, JSValueMakeNumber(context
, 0), exception
);
269 static bool MyObject_hasInstance(JSContextRef context
, JSObjectRef constructor
, JSValueRef possibleValue
, JSValueRef
* exception
)
271 UNUSED_PARAM(context
);
272 UNUSED_PARAM(constructor
);
274 if (JSValueIsString(context
, possibleValue
) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, possibleValue
, 0), "throwOnHasInstance")) {
275 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), constructor
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
279 JSStringRef numberString
= JSStringCreateWithUTF8CString("Number");
280 JSObjectRef numberConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, JSContextGetGlobalObject(context
), numberString
, exception
), exception
);
281 JSStringRelease(numberString
);
283 return JSValueIsInstanceOfConstructor(context
, possibleValue
, numberConstructor
, exception
);
286 static JSValueRef
MyObject_convertToType(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
288 UNUSED_PARAM(object
);
289 UNUSED_PARAM(exception
);
293 return JSValueMakeNumber(context
, 1);
296 JSStringRef string
= JSStringCreateWithUTF8CString("MyObjectAsString");
297 JSValueRef result
= JSValueMakeString(context
, string
);
298 JSStringRelease(string
);
305 // string conversion -- forward to default object class
306 return JSValueMakeNull(context
);
309 static JSStaticValue evilStaticValues
[] = {
310 { "nullGetSet", 0, 0, kJSPropertyAttributeNone
},
314 static JSStaticFunction evilStaticFunctions
[] = {
315 { "nullCall", 0, kJSPropertyAttributeNone
},
319 JSClassDefinition MyObject_definition
= {
321 kJSClassAttributeNone
,
331 MyObject_hasProperty
,
332 MyObject_getProperty
,
333 MyObject_setProperty
,
334 MyObject_deleteProperty
,
335 MyObject_getPropertyNames
,
336 MyObject_callAsFunction
,
337 MyObject_callAsConstructor
,
338 MyObject_hasInstance
,
339 MyObject_convertToType
,
342 static JSClassRef
MyObject_class(JSContextRef context
)
344 UNUSED_PARAM(context
);
346 static JSClassRef jsClass
;
348 jsClass
= JSClassCreate(&MyObject_definition
);
353 static bool EvilExceptionObject_hasInstance(JSContextRef context
, JSObjectRef constructor
, JSValueRef possibleValue
, JSValueRef
* exception
)
355 UNUSED_PARAM(context
);
356 UNUSED_PARAM(constructor
);
358 JSStringRef hasInstanceName
= JSStringCreateWithUTF8CString("hasInstance");
359 JSValueRef hasInstance
= JSObjectGetProperty(context
, constructor
, hasInstanceName
, exception
);
360 JSStringRelease(hasInstanceName
);
363 JSObjectRef function
= JSValueToObject(context
, hasInstance
, exception
);
364 JSValueRef result
= JSObjectCallAsFunction(context
, function
, constructor
, 1, &possibleValue
, exception
);
365 return result
&& JSValueToBoolean(context
, result
);
368 static JSValueRef
EvilExceptionObject_convertToType(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
370 UNUSED_PARAM(object
);
371 UNUSED_PARAM(exception
);
372 JSStringRef funcName
;
375 funcName
= JSStringCreateWithUTF8CString("toNumber");
378 funcName
= JSStringCreateWithUTF8CString("toStringExplicit");
381 return JSValueMakeNull(context
);
385 JSValueRef func
= JSObjectGetProperty(context
, object
, funcName
, exception
);
386 JSStringRelease(funcName
);
387 JSObjectRef function
= JSValueToObject(context
, func
, exception
);
389 return JSValueMakeNull(context
);
390 JSValueRef value
= JSObjectCallAsFunction(context
, function
, object
, 0, NULL
, exception
);
392 JSStringRef errorString
= JSStringCreateWithUTF8CString("convertToType failed");
393 JSValueRef errorStringRef
= JSValueMakeString(context
, errorString
);
394 JSStringRelease(errorString
);
395 return errorStringRef
;
400 JSClassDefinition EvilExceptionObject_definition
= {
402 kJSClassAttributeNone
,
404 "EvilExceptionObject",
419 EvilExceptionObject_hasInstance
,
420 EvilExceptionObject_convertToType
,
423 static JSClassRef
EvilExceptionObject_class(JSContextRef context
)
425 UNUSED_PARAM(context
);
427 static JSClassRef jsClass
;
429 jsClass
= JSClassCreate(&EvilExceptionObject_definition
);
434 JSClassDefinition EmptyObject_definition
= {
436 kJSClassAttributeNone
,
457 static JSClassRef
EmptyObject_class(JSContextRef context
)
459 UNUSED_PARAM(context
);
461 static JSClassRef jsClass
;
463 jsClass
= JSClassCreate(&EmptyObject_definition
);
469 static JSValueRef
Base_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
471 UNUSED_PARAM(object
);
472 UNUSED_PARAM(propertyName
);
473 UNUSED_PARAM(exception
);
475 return JSValueMakeNumber(ctx
, 1); // distinguish base get form derived get
478 static bool Base_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
480 UNUSED_PARAM(object
);
481 UNUSED_PARAM(propertyName
);
484 *exception
= JSValueMakeNumber(ctx
, 1); // distinguish base set from derived set
488 static JSValueRef
Base_callAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
490 UNUSED_PARAM(function
);
491 UNUSED_PARAM(thisObject
);
492 UNUSED_PARAM(argumentCount
);
493 UNUSED_PARAM(arguments
);
494 UNUSED_PARAM(exception
);
496 return JSValueMakeNumber(ctx
, 1); // distinguish base call from derived call
499 static JSStaticFunction Base_staticFunctions
[] = {
500 { "baseProtoDup", NULL
, kJSPropertyAttributeNone
},
501 { "baseProto", Base_callAsFunction
, kJSPropertyAttributeNone
},
505 static JSStaticValue Base_staticValues
[] = {
506 { "baseDup", Base_get
, Base_set
, kJSPropertyAttributeNone
},
507 { "baseOnly", Base_get
, Base_set
, kJSPropertyAttributeNone
},
511 static bool TestInitializeFinalize
;
512 static void Base_initialize(JSContextRef context
, JSObjectRef object
)
514 UNUSED_PARAM(context
);
516 if (TestInitializeFinalize
) {
517 ASSERT((void*)1 == JSObjectGetPrivate(object
));
518 JSObjectSetPrivate(object
, (void*)2);
522 static unsigned Base_didFinalize
;
523 static void Base_finalize(JSObjectRef object
)
525 UNUSED_PARAM(object
);
526 if (TestInitializeFinalize
) {
527 ASSERT((void*)4 == JSObjectGetPrivate(object
));
528 Base_didFinalize
= true;
532 static JSClassRef
Base_class(JSContextRef context
)
534 UNUSED_PARAM(context
);
536 static JSClassRef jsClass
;
538 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
539 definition
.staticValues
= Base_staticValues
;
540 definition
.staticFunctions
= Base_staticFunctions
;
541 definition
.initialize
= Base_initialize
;
542 definition
.finalize
= Base_finalize
;
543 jsClass
= JSClassCreate(&definition
);
548 static JSValueRef
Derived_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
550 UNUSED_PARAM(object
);
551 UNUSED_PARAM(propertyName
);
552 UNUSED_PARAM(exception
);
554 return JSValueMakeNumber(ctx
, 2); // distinguish base get form derived get
557 static bool Derived_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
560 UNUSED_PARAM(object
);
561 UNUSED_PARAM(propertyName
);
564 *exception
= JSValueMakeNumber(ctx
, 2); // distinguish base set from derived set
568 static JSValueRef
Derived_callAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
570 UNUSED_PARAM(function
);
571 UNUSED_PARAM(thisObject
);
572 UNUSED_PARAM(argumentCount
);
573 UNUSED_PARAM(arguments
);
574 UNUSED_PARAM(exception
);
576 return JSValueMakeNumber(ctx
, 2); // distinguish base call from derived call
579 static JSStaticFunction Derived_staticFunctions
[] = {
580 { "protoOnly", Derived_callAsFunction
, kJSPropertyAttributeNone
},
581 { "protoDup", NULL
, kJSPropertyAttributeNone
},
582 { "baseProtoDup", Derived_callAsFunction
, kJSPropertyAttributeNone
},
586 static JSStaticValue Derived_staticValues
[] = {
587 { "derivedOnly", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
588 { "protoDup", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
589 { "baseDup", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
593 static void Derived_initialize(JSContextRef context
, JSObjectRef object
)
595 UNUSED_PARAM(context
);
597 if (TestInitializeFinalize
) {
598 ASSERT((void*)2 == JSObjectGetPrivate(object
));
599 JSObjectSetPrivate(object
, (void*)3);
603 static void Derived_finalize(JSObjectRef object
)
605 if (TestInitializeFinalize
) {
606 ASSERT((void*)3 == JSObjectGetPrivate(object
));
607 JSObjectSetPrivate(object
, (void*)4);
611 static JSClassRef
Derived_class(JSContextRef context
)
613 static JSClassRef jsClass
;
615 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
616 definition
.parentClass
= Base_class(context
);
617 definition
.staticValues
= Derived_staticValues
;
618 definition
.staticFunctions
= Derived_staticFunctions
;
619 definition
.initialize
= Derived_initialize
;
620 definition
.finalize
= Derived_finalize
;
621 jsClass
= JSClassCreate(&definition
);
626 static JSClassRef
Derived2_class(JSContextRef context
)
628 static JSClassRef jsClass
;
630 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
631 definition
.parentClass
= Derived_class(context
);
632 jsClass
= JSClassCreate(&definition
);
637 static JSValueRef
print_callAsFunction(JSContextRef ctx
, JSObjectRef functionObject
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
639 UNUSED_PARAM(functionObject
);
640 UNUSED_PARAM(thisObject
);
641 UNUSED_PARAM(exception
);
643 ASSERT(JSContextGetGlobalContext(ctx
) == context
);
645 if (argumentCount
> 0) {
646 JSStringRef string
= JSValueToStringCopy(ctx
, arguments
[0], NULL
);
647 size_t sizeUTF8
= JSStringGetMaximumUTF8CStringSize(string
);
648 char* stringUTF8
= (char*)malloc(sizeUTF8
);
649 JSStringGetUTF8CString(string
, stringUTF8
, sizeUTF8
);
650 printf("%s\n", stringUTF8
);
652 JSStringRelease(string
);
655 return JSValueMakeUndefined(ctx
);
658 static JSObjectRef
myConstructor_callAsConstructor(JSContextRef context
, JSObjectRef constructorObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
660 UNUSED_PARAM(constructorObject
);
661 UNUSED_PARAM(exception
);
663 JSObjectRef result
= JSObjectMake(context
, NULL
, NULL
);
664 if (argumentCount
> 0) {
665 JSStringRef value
= JSStringCreateWithUTF8CString("value");
666 JSObjectSetProperty(context
, result
, value
, arguments
[0], kJSPropertyAttributeNone
, NULL
);
667 JSStringRelease(value
);
674 static void globalObject_initialize(JSContextRef context
, JSObjectRef object
)
676 UNUSED_PARAM(object
);
677 // Ensure that an execution context is passed in
680 // Ensure that the global object is set to the object that we were passed
681 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
682 ASSERT(globalObject
);
683 ASSERT(object
== globalObject
);
685 // Ensure that the standard global properties have been set on the global object
686 JSStringRef array
= JSStringCreateWithUTF8CString("Array");
687 JSObjectRef arrayConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, globalObject
, array
, NULL
), NULL
);
688 JSStringRelease(array
);
690 UNUSED_PARAM(arrayConstructor
);
691 ASSERT(arrayConstructor
);
694 static JSValueRef
globalObject_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
696 UNUSED_PARAM(object
);
697 UNUSED_PARAM(propertyName
);
698 UNUSED_PARAM(exception
);
700 return JSValueMakeNumber(ctx
, 3);
703 static bool globalObject_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
705 UNUSED_PARAM(object
);
706 UNUSED_PARAM(propertyName
);
709 *exception
= JSValueMakeNumber(ctx
, 3);
713 static JSValueRef
globalObject_call(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
715 UNUSED_PARAM(function
);
716 UNUSED_PARAM(thisObject
);
717 UNUSED_PARAM(argumentCount
);
718 UNUSED_PARAM(arguments
);
719 UNUSED_PARAM(exception
);
721 return JSValueMakeNumber(ctx
, 3);
724 static JSValueRef
functionGC(JSContextRef context
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
726 UNUSED_PARAM(function
);
727 UNUSED_PARAM(thisObject
);
728 UNUSED_PARAM(argumentCount
);
729 UNUSED_PARAM(arguments
);
730 UNUSED_PARAM(exception
);
731 JSGarbageCollect(context
);
732 return JSValueMakeUndefined(context
);
735 static JSStaticValue globalObject_staticValues
[] = {
736 { "globalStaticValue", globalObject_get
, globalObject_set
, kJSPropertyAttributeNone
},
740 static JSStaticFunction globalObject_staticFunctions
[] = {
741 { "globalStaticFunction", globalObject_call
, kJSPropertyAttributeNone
},
742 { "gc", functionGC
, kJSPropertyAttributeNone
},
746 static char* createStringWithContentsOfFile(const char* fileName
);
748 static void testInitializeFinalize()
750 JSObjectRef o
= JSObjectMake(context
, Derived_class(context
), (void*)1);
752 ASSERT(JSObjectGetPrivate(o
) == (void*)3);
755 static JSValueRef jsNumberValue
= NULL
;
757 static void makeGlobalNumberValue(JSContextRef context
) {
758 JSValueRef v
= JSValueMakeNumber(context
, 420);
759 JSValueProtect(context
, v
);
764 int main(int argc
, char* argv
[])
766 const char *scriptPath
= "testapi.js";
768 scriptPath
= argv
[1];
771 // Test garbage collection with a fresh context
772 context
= JSGlobalContextCreateInGroup(NULL
, NULL
);
773 TestInitializeFinalize
= true;
774 testInitializeFinalize();
775 JSGlobalContextRelease(context
);
776 TestInitializeFinalize
= false;
778 ASSERT(Base_didFinalize
);
780 JSClassDefinition globalObjectClassDefinition
= kJSClassDefinitionEmpty
;
781 globalObjectClassDefinition
.initialize
= globalObject_initialize
;
782 globalObjectClassDefinition
.staticValues
= globalObject_staticValues
;
783 globalObjectClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
784 globalObjectClassDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
785 JSClassRef globalObjectClass
= JSClassCreate(&globalObjectClassDefinition
);
786 context
= JSGlobalContextCreateInGroup(NULL
, globalObjectClass
);
788 JSGlobalContextRetain(context
);
789 JSGlobalContextRelease(context
);
790 ASSERT(JSContextGetGlobalContext(context
) == context
);
792 JSReportExtraMemoryCost(context
, 0);
793 JSReportExtraMemoryCost(context
, 1);
794 JSReportExtraMemoryCost(context
, 1024);
796 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
797 ASSERT(JSValueIsObject(context
, globalObject
));
799 JSValueRef jsUndefined
= JSValueMakeUndefined(context
);
800 JSValueRef jsNull
= JSValueMakeNull(context
);
801 JSValueRef jsTrue
= JSValueMakeBoolean(context
, true);
802 JSValueRef jsFalse
= JSValueMakeBoolean(context
, false);
803 JSValueRef jsZero
= JSValueMakeNumber(context
, 0);
804 JSValueRef jsOne
= JSValueMakeNumber(context
, 1);
805 JSValueRef jsOneThird
= JSValueMakeNumber(context
, 1.0 / 3.0);
806 JSObjectRef jsObjectNoProto
= JSObjectMake(context
, NULL
, NULL
);
807 JSObjectSetPrototype(context
, jsObjectNoProto
, JSValueMakeNull(context
));
809 // FIXME: test funny utf8 characters
810 JSStringRef jsEmptyIString
= JSStringCreateWithUTF8CString("");
811 JSValueRef jsEmptyString
= JSValueMakeString(context
, jsEmptyIString
);
813 JSStringRef jsOneIString
= JSStringCreateWithUTF8CString("1");
814 JSValueRef jsOneString
= JSValueMakeString(context
, jsOneIString
);
816 UniChar singleUniChar
= 65; // Capital A
817 CFMutableStringRef cfString
=
818 CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault
,
824 JSStringRef jsCFIString
= JSStringCreateWithCFString(cfString
);
825 JSValueRef jsCFString
= JSValueMakeString(context
, jsCFIString
);
827 CFStringRef cfEmptyString
= CFStringCreateWithCString(kCFAllocatorDefault
, "", kCFStringEncodingUTF8
);
829 JSStringRef jsCFEmptyIString
= JSStringCreateWithCFString(cfEmptyString
);
830 JSValueRef jsCFEmptyString
= JSValueMakeString(context
, jsCFEmptyIString
);
832 CFIndex cfStringLength
= CFStringGetLength(cfString
);
833 UniChar
* buffer
= (UniChar
*)malloc(cfStringLength
* sizeof(UniChar
));
834 CFStringGetCharacters(cfString
,
835 CFRangeMake(0, cfStringLength
),
837 JSStringRef jsCFIStringWithCharacters
= JSStringCreateWithCharacters((JSChar
*)buffer
, cfStringLength
);
838 JSValueRef jsCFStringWithCharacters
= JSValueMakeString(context
, jsCFIStringWithCharacters
);
840 JSStringRef jsCFEmptyIStringWithCharacters
= JSStringCreateWithCharacters((JSChar
*)buffer
, CFStringGetLength(cfEmptyString
));
842 JSValueRef jsCFEmptyStringWithCharacters
= JSValueMakeString(context
, jsCFEmptyIStringWithCharacters
);
844 ASSERT(JSValueGetType(context
, jsUndefined
) == kJSTypeUndefined
);
845 ASSERT(JSValueGetType(context
, jsNull
) == kJSTypeNull
);
846 ASSERT(JSValueGetType(context
, jsTrue
) == kJSTypeBoolean
);
847 ASSERT(JSValueGetType(context
, jsFalse
) == kJSTypeBoolean
);
848 ASSERT(JSValueGetType(context
, jsZero
) == kJSTypeNumber
);
849 ASSERT(JSValueGetType(context
, jsOne
) == kJSTypeNumber
);
850 ASSERT(JSValueGetType(context
, jsOneThird
) == kJSTypeNumber
);
851 ASSERT(JSValueGetType(context
, jsEmptyString
) == kJSTypeString
);
852 ASSERT(JSValueGetType(context
, jsOneString
) == kJSTypeString
);
853 ASSERT(JSValueGetType(context
, jsCFString
) == kJSTypeString
);
854 ASSERT(JSValueGetType(context
, jsCFStringWithCharacters
) == kJSTypeString
);
855 ASSERT(JSValueGetType(context
, jsCFEmptyString
) == kJSTypeString
);
856 ASSERT(JSValueGetType(context
, jsCFEmptyStringWithCharacters
) == kJSTypeString
);
858 JSObjectRef myObject
= JSObjectMake(context
, MyObject_class(context
), NULL
);
859 JSStringRef myObjectIString
= JSStringCreateWithUTF8CString("MyObject");
860 JSObjectSetProperty(context
, globalObject
, myObjectIString
, myObject
, kJSPropertyAttributeNone
, NULL
);
861 JSStringRelease(myObjectIString
);
863 JSObjectRef EvilExceptionObject
= JSObjectMake(context
, EvilExceptionObject_class(context
), NULL
);
864 JSStringRef EvilExceptionObjectIString
= JSStringCreateWithUTF8CString("EvilExceptionObject");
865 JSObjectSetProperty(context
, globalObject
, EvilExceptionObjectIString
, EvilExceptionObject
, kJSPropertyAttributeNone
, NULL
);
866 JSStringRelease(EvilExceptionObjectIString
);
868 JSObjectRef EmptyObject
= JSObjectMake(context
, EmptyObject_class(context
), NULL
);
869 JSStringRef EmptyObjectIString
= JSStringCreateWithUTF8CString("EmptyObject");
870 JSObjectSetProperty(context
, globalObject
, EmptyObjectIString
, EmptyObject
, kJSPropertyAttributeNone
, NULL
);
871 JSStringRelease(EmptyObjectIString
);
873 JSValueRef exception
;
875 // Conversions that throw exceptions
877 ASSERT(NULL
== JSValueToObject(context
, jsNull
, &exception
));
881 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
882 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
883 // After that's resolved, we can remove these casts
884 ASSERT(isnan((float)JSValueToNumber(context
, jsObjectNoProto
, &exception
)));
888 ASSERT(!JSValueToStringCopy(context
, jsObjectNoProto
, &exception
));
891 ASSERT(JSValueToBoolean(context
, myObject
));
894 ASSERT(!JSValueIsEqual(context
, jsObjectNoProto
, JSValueMakeNumber(context
, 1), &exception
));
898 JSObjectGetPropertyAtIndex(context
, myObject
, 0, &exception
);
899 ASSERT(1 == JSValueToNumber(context
, exception
, NULL
));
901 assertEqualsAsBoolean(jsUndefined
, false);
902 assertEqualsAsBoolean(jsNull
, false);
903 assertEqualsAsBoolean(jsTrue
, true);
904 assertEqualsAsBoolean(jsFalse
, false);
905 assertEqualsAsBoolean(jsZero
, false);
906 assertEqualsAsBoolean(jsOne
, true);
907 assertEqualsAsBoolean(jsOneThird
, true);
908 assertEqualsAsBoolean(jsEmptyString
, false);
909 assertEqualsAsBoolean(jsOneString
, true);
910 assertEqualsAsBoolean(jsCFString
, true);
911 assertEqualsAsBoolean(jsCFStringWithCharacters
, true);
912 assertEqualsAsBoolean(jsCFEmptyString
, false);
913 assertEqualsAsBoolean(jsCFEmptyStringWithCharacters
, false);
915 assertEqualsAsNumber(jsUndefined
, nan(""));
916 assertEqualsAsNumber(jsNull
, 0);
917 assertEqualsAsNumber(jsTrue
, 1);
918 assertEqualsAsNumber(jsFalse
, 0);
919 assertEqualsAsNumber(jsZero
, 0);
920 assertEqualsAsNumber(jsOne
, 1);
921 assertEqualsAsNumber(jsOneThird
, 1.0 / 3.0);
922 assertEqualsAsNumber(jsEmptyString
, 0);
923 assertEqualsAsNumber(jsOneString
, 1);
924 assertEqualsAsNumber(jsCFString
, nan(""));
925 assertEqualsAsNumber(jsCFStringWithCharacters
, nan(""));
926 assertEqualsAsNumber(jsCFEmptyString
, 0);
927 assertEqualsAsNumber(jsCFEmptyStringWithCharacters
, 0);
928 ASSERT(sizeof(JSChar
) == sizeof(UniChar
));
930 assertEqualsAsCharactersPtr(jsUndefined
, "undefined");
931 assertEqualsAsCharactersPtr(jsNull
, "null");
932 assertEqualsAsCharactersPtr(jsTrue
, "true");
933 assertEqualsAsCharactersPtr(jsFalse
, "false");
934 assertEqualsAsCharactersPtr(jsZero
, "0");
935 assertEqualsAsCharactersPtr(jsOne
, "1");
936 assertEqualsAsCharactersPtr(jsOneThird
, "0.3333333333333333");
937 assertEqualsAsCharactersPtr(jsEmptyString
, "");
938 assertEqualsAsCharactersPtr(jsOneString
, "1");
939 assertEqualsAsCharactersPtr(jsCFString
, "A");
940 assertEqualsAsCharactersPtr(jsCFStringWithCharacters
, "A");
941 assertEqualsAsCharactersPtr(jsCFEmptyString
, "");
942 assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters
, "");
944 assertEqualsAsUTF8String(jsUndefined
, "undefined");
945 assertEqualsAsUTF8String(jsNull
, "null");
946 assertEqualsAsUTF8String(jsTrue
, "true");
947 assertEqualsAsUTF8String(jsFalse
, "false");
948 assertEqualsAsUTF8String(jsZero
, "0");
949 assertEqualsAsUTF8String(jsOne
, "1");
950 assertEqualsAsUTF8String(jsOneThird
, "0.3333333333333333");
951 assertEqualsAsUTF8String(jsEmptyString
, "");
952 assertEqualsAsUTF8String(jsOneString
, "1");
953 assertEqualsAsUTF8String(jsCFString
, "A");
954 assertEqualsAsUTF8String(jsCFStringWithCharacters
, "A");
955 assertEqualsAsUTF8String(jsCFEmptyString
, "");
956 assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters
, "");
958 ASSERT(JSValueIsStrictEqual(context
, jsTrue
, jsTrue
));
959 ASSERT(!JSValueIsStrictEqual(context
, jsOne
, jsOneString
));
961 ASSERT(JSValueIsEqual(context
, jsOne
, jsOneString
, NULL
));
962 ASSERT(!JSValueIsEqual(context
, jsTrue
, jsFalse
, NULL
));
964 CFStringRef cfJSString
= JSStringCopyCFString(kCFAllocatorDefault
, jsCFIString
);
965 CFStringRef cfJSEmptyString
= JSStringCopyCFString(kCFAllocatorDefault
, jsCFEmptyIString
);
966 ASSERT(CFEqual(cfJSString
, cfString
));
967 ASSERT(CFEqual(cfJSEmptyString
, cfEmptyString
));
968 CFRelease(cfJSString
);
969 CFRelease(cfJSEmptyString
);
972 CFRelease(cfEmptyString
);
974 jsGlobalValue
= JSObjectMake(context
, NULL
, NULL
);
975 makeGlobalNumberValue(context
);
976 JSValueProtect(context
, jsGlobalValue
);
977 JSGarbageCollect(context
);
978 ASSERT(JSValueIsObject(context
, jsGlobalValue
));
979 JSValueUnprotect(context
, jsGlobalValue
);
980 JSValueUnprotect(context
, jsNumberValue
);
982 JSStringRef goodSyntax
= JSStringCreateWithUTF8CString("x = 1;");
983 JSStringRef badSyntax
= JSStringCreateWithUTF8CString("x := 1;");
984 ASSERT(JSCheckScriptSyntax(context
, goodSyntax
, NULL
, 0, NULL
));
985 ASSERT(!JSCheckScriptSyntax(context
, badSyntax
, NULL
, 0, NULL
));
992 result
= JSEvaluateScript(context
, goodSyntax
, NULL
, NULL
, 1, NULL
);
994 ASSERT(JSValueIsEqual(context
, result
, jsOne
, NULL
));
997 result
= JSEvaluateScript(context
, badSyntax
, NULL
, NULL
, 1, &exception
);
999 ASSERT(JSValueIsObject(context
, exception
));
1001 JSStringRef array
= JSStringCreateWithUTF8CString("Array");
1002 JSObjectRef arrayConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, globalObject
, array
, NULL
), NULL
);
1003 JSStringRelease(array
);
1004 result
= JSObjectCallAsConstructor(context
, arrayConstructor
, 0, NULL
, NULL
);
1006 ASSERT(JSValueIsObject(context
, result
));
1007 ASSERT(JSValueIsInstanceOfConstructor(context
, result
, arrayConstructor
, NULL
));
1008 ASSERT(!JSValueIsInstanceOfConstructor(context
, JSValueMakeNull(context
), arrayConstructor
, NULL
));
1010 o
= JSValueToObject(context
, result
, NULL
);
1012 ASSERT(JSValueIsUndefined(context
, JSObjectGetPropertyAtIndex(context
, o
, 0, &exception
)));
1015 JSObjectSetPropertyAtIndex(context
, o
, 0, JSValueMakeNumber(context
, 1), &exception
);
1019 ASSERT(1 == JSValueToNumber(context
, JSObjectGetPropertyAtIndex(context
, o
, 0, &exception
), &exception
));
1022 JSStringRef functionBody
;
1023 JSObjectRef function
;
1026 functionBody
= JSStringCreateWithUTF8CString("rreturn Array;");
1027 JSStringRef line
= JSStringCreateWithUTF8CString("line");
1028 ASSERT(!JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
));
1029 ASSERT(JSValueIsObject(context
, exception
));
1030 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), line
, NULL
);
1031 assertEqualsAsNumber(v
, 1);
1032 JSStringRelease(functionBody
);
1033 JSStringRelease(line
);
1036 functionBody
= JSStringCreateWithUTF8CString("return Array;");
1037 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
);
1038 JSStringRelease(functionBody
);
1040 ASSERT(JSObjectIsFunction(context
, function
));
1041 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1043 ASSERT(JSValueIsEqual(context
, v
, arrayConstructor
, NULL
));
1046 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, jsEmptyIString
, NULL
, 0, &exception
);
1048 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, &exception
);
1049 ASSERT(v
&& !exception
);
1050 ASSERT(JSValueIsUndefined(context
, v
));
1054 JSStringRef foo
= JSStringCreateWithUTF8CString("foo");
1055 JSStringRef argumentNames
[] = { foo
};
1056 functionBody
= JSStringCreateWithUTF8CString("return foo;");
1057 function
= JSObjectMakeFunction(context
, foo
, 1, argumentNames
, functionBody
, NULL
, 1, &exception
);
1058 ASSERT(function
&& !exception
);
1059 JSValueRef arguments
[] = { JSValueMakeNumber(context
, 2) };
1060 v
= JSObjectCallAsFunction(context
, function
, NULL
, 1, arguments
, &exception
);
1061 JSStringRelease(foo
);
1062 JSStringRelease(functionBody
);
1064 string
= JSValueToStringCopy(context
, function
, NULL
);
1065 assertEqualsAsUTF8String(JSValueMakeString(context
, string
), "function foo(foo) { return foo;\n}");
1066 JSStringRelease(string
);
1068 JSStringRef print
= JSStringCreateWithUTF8CString("print");
1069 JSObjectRef printFunction
= JSObjectMakeFunctionWithCallback(context
, print
, print_callAsFunction
);
1070 JSObjectSetProperty(context
, globalObject
, print
, printFunction
, kJSPropertyAttributeNone
, NULL
);
1071 JSStringRelease(print
);
1073 ASSERT(!JSObjectSetPrivate(printFunction
, (void*)1));
1074 ASSERT(!JSObjectGetPrivate(printFunction
));
1076 JSStringRef myConstructorIString
= JSStringCreateWithUTF8CString("MyConstructor");
1077 JSObjectRef myConstructor
= JSObjectMakeConstructor(context
, NULL
, myConstructor_callAsConstructor
);
1078 JSObjectSetProperty(context
, globalObject
, myConstructorIString
, myConstructor
, kJSPropertyAttributeNone
, NULL
);
1079 JSStringRelease(myConstructorIString
);
1081 ASSERT(!JSObjectSetPrivate(myConstructor
, (void*)1));
1082 ASSERT(!JSObjectGetPrivate(myConstructor
));
1084 string
= JSStringCreateWithUTF8CString("Base");
1085 JSObjectRef baseConstructor
= JSObjectMakeConstructor(context
, Base_class(context
), NULL
);
1086 JSObjectSetProperty(context
, globalObject
, string
, baseConstructor
, kJSPropertyAttributeNone
, NULL
);
1087 JSStringRelease(string
);
1089 string
= JSStringCreateWithUTF8CString("Derived");
1090 JSObjectRef derivedConstructor
= JSObjectMakeConstructor(context
, Derived_class(context
), NULL
);
1091 JSObjectSetProperty(context
, globalObject
, string
, derivedConstructor
, kJSPropertyAttributeNone
, NULL
);
1092 JSStringRelease(string
);
1094 string
= JSStringCreateWithUTF8CString("Derived2");
1095 JSObjectRef derived2Constructor
= JSObjectMakeConstructor(context
, Derived2_class(context
), NULL
);
1096 JSObjectSetProperty(context
, globalObject
, string
, derived2Constructor
, kJSPropertyAttributeNone
, NULL
);
1097 JSStringRelease(string
);
1099 o
= JSObjectMake(context
, NULL
, NULL
);
1100 JSObjectSetProperty(context
, o
, jsOneIString
, JSValueMakeNumber(context
, 1), kJSPropertyAttributeNone
, NULL
);
1101 JSObjectSetProperty(context
, o
, jsCFIString
, JSValueMakeNumber(context
, 1), kJSPropertyAttributeDontEnum
, NULL
);
1102 JSPropertyNameArrayRef nameArray
= JSObjectCopyPropertyNames(context
, o
);
1103 size_t expectedCount
= JSPropertyNameArrayGetCount(nameArray
);
1105 for (count
= 0; count
< expectedCount
; ++count
)
1106 JSPropertyNameArrayGetNameAtIndex(nameArray
, count
);
1107 JSPropertyNameArrayRelease(nameArray
);
1108 ASSERT(count
== 1); // jsCFString should not be enumerated
1110 JSValueRef argumentsArrayValues
[] = { JSValueMakeNumber(context
, 10), JSValueMakeNumber(context
, 20) };
1111 o
= JSObjectMakeArray(context
, sizeof(argumentsArrayValues
) / sizeof(JSValueRef
), argumentsArrayValues
, NULL
);
1112 string
= JSStringCreateWithUTF8CString("length");
1113 v
= JSObjectGetProperty(context
, o
, string
, NULL
);
1114 assertEqualsAsNumber(v
, 2);
1115 v
= JSObjectGetPropertyAtIndex(context
, o
, 0, NULL
);
1116 assertEqualsAsNumber(v
, 10);
1117 v
= JSObjectGetPropertyAtIndex(context
, o
, 1, NULL
);
1118 assertEqualsAsNumber(v
, 20);
1120 o
= JSObjectMakeArray(context
, 0, NULL
, NULL
);
1121 v
= JSObjectGetProperty(context
, o
, string
, NULL
);
1122 assertEqualsAsNumber(v
, 0);
1123 JSStringRelease(string
);
1125 JSValueRef argumentsDateValues
[] = { JSValueMakeNumber(context
, 0) };
1126 o
= JSObjectMakeDate(context
, 1, argumentsDateValues
, NULL
);
1127 if (timeZoneIsPST())
1128 assertEqualsAsUTF8String(o
, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
1130 string
= JSStringCreateWithUTF8CString("an error message");
1131 JSValueRef argumentsErrorValues
[] = { JSValueMakeString(context
, string
) };
1132 o
= JSObjectMakeError(context
, 1, argumentsErrorValues
, NULL
);
1133 assertEqualsAsUTF8String(o
, "Error: an error message");
1134 JSStringRelease(string
);
1136 string
= JSStringCreateWithUTF8CString("foo");
1137 JSStringRef string2
= JSStringCreateWithUTF8CString("gi");
1138 JSValueRef argumentsRegExpValues
[] = { JSValueMakeString(context
, string
), JSValueMakeString(context
, string2
) };
1139 o
= JSObjectMakeRegExp(context
, 2, argumentsRegExpValues
, NULL
);
1140 assertEqualsAsUTF8String(o
, "/foo/gi");
1141 JSStringRelease(string
);
1142 JSStringRelease(string2
);
1144 JSClassDefinition nullDefinition
= kJSClassDefinitionEmpty
;
1145 nullDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
1146 JSClassRef nullClass
= JSClassCreate(&nullDefinition
);
1147 JSClassRelease(nullClass
);
1149 nullDefinition
= kJSClassDefinitionEmpty
;
1150 nullClass
= JSClassCreate(&nullDefinition
);
1151 JSClassRelease(nullClass
);
1153 functionBody
= JSStringCreateWithUTF8CString("return this;");
1154 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, NULL
);
1155 JSStringRelease(functionBody
);
1156 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1157 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1158 v
= JSObjectCallAsFunction(context
, function
, o
, 0, NULL
, NULL
);
1159 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1161 functionBody
= JSStringCreateWithUTF8CString("return eval(\"this\");");
1162 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, NULL
);
1163 JSStringRelease(functionBody
);
1164 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1165 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1166 v
= JSObjectCallAsFunction(context
, function
, o
, 0, NULL
, NULL
);
1167 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1169 JSStringRef script
= JSStringCreateWithUTF8CString("this;");
1170 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1171 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1172 v
= JSEvaluateScript(context
, script
, o
, NULL
, 1, NULL
);
1173 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1174 JSStringRelease(script
);
1176 script
= JSStringCreateWithUTF8CString("eval(this);");
1177 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1178 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1179 v
= JSEvaluateScript(context
, script
, o
, NULL
, 1, NULL
);
1180 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1181 JSStringRelease(script
);
1183 // Verify that creating a constructor for a class with no static functions does not trigger
1184 // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
1185 nullDefinition
= kJSClassDefinitionEmpty
;
1186 nullClass
= JSClassCreate(&nullDefinition
);
1187 myConstructor
= JSObjectMakeConstructor(context
, nullClass
, 0);
1188 JSClassRelease(nullClass
);
1190 char* scriptUTF8
= createStringWithContentsOfFile(scriptPath
);
1192 printf("FAIL: Test script could not be loaded.\n");
1195 script
= JSStringCreateWithUTF8CString(scriptUTF8
);
1196 result
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, &exception
);
1197 if (result
&& JSValueIsUndefined(context
, result
))
1198 printf("PASS: Test script executed successfully.\n");
1200 printf("FAIL: Test script returned unexpected value:\n");
1201 JSStringRef exceptionIString
= JSValueToStringCopy(context
, exception
, NULL
);
1202 CFStringRef exceptionCF
= JSStringCopyCFString(kCFAllocatorDefault
, exceptionIString
);
1203 CFShow(exceptionCF
);
1204 CFRelease(exceptionCF
);
1205 JSStringRelease(exceptionIString
);
1208 JSStringRelease(script
);
1212 // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
1216 globalObject
= NULL
;
1217 myConstructor
= NULL
;
1219 JSStringRelease(jsEmptyIString
);
1220 JSStringRelease(jsOneIString
);
1221 JSStringRelease(jsCFIString
);
1222 JSStringRelease(jsCFEmptyIString
);
1223 JSStringRelease(jsCFIStringWithCharacters
);
1224 JSStringRelease(jsCFEmptyIStringWithCharacters
);
1225 JSStringRelease(goodSyntax
);
1226 JSStringRelease(badSyntax
);
1228 JSGlobalContextRelease(context
);
1229 JSClassRelease(globalObjectClass
);
1231 // Test for an infinite prototype chain that used to be created. This test
1232 // passes if the call to JSObjectHasProperty() does not hang.
1234 JSClassDefinition prototypeLoopClassDefinition
= kJSClassDefinitionEmpty
;
1235 prototypeLoopClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
1236 JSClassRef prototypeLoopClass
= JSClassCreate(&prototypeLoopClassDefinition
);
1237 JSGlobalContextRef prototypeLoopContext
= JSGlobalContextCreateInGroup(NULL
, prototypeLoopClass
);
1239 JSStringRef nameProperty
= JSStringCreateWithUTF8CString("name");
1240 JSObjectHasProperty(prototypeLoopContext
, JSContextGetGlobalObject(prototypeLoopContext
), nameProperty
);
1242 JSGlobalContextRelease(prototypeLoopContext
);
1243 JSClassRelease(prototypeLoopClass
);
1245 printf("PASS: Infinite prototype chain does not occur.\n");
1248 printf("FAIL: Some tests failed.\n");
1252 printf("PASS: Program exited normally.\n");
1256 static char* createStringWithContentsOfFile(const char* fileName
)
1260 size_t buffer_size
= 0;
1261 size_t buffer_capacity
= 1024;
1262 buffer
= (char*)malloc(buffer_capacity
);
1264 FILE* f
= fopen(fileName
, "r");
1266 fprintf(stderr
, "Could not open file: %s\n", fileName
);
1270 while (!feof(f
) && !ferror(f
)) {
1271 buffer_size
+= fread(buffer
+ buffer_size
, 1, buffer_capacity
- buffer_size
, f
);
1272 if (buffer_size
== buffer_capacity
) { // guarantees space for trailing '\0'
1273 buffer_capacity
*= 2;
1274 buffer
= (char*)realloc(buffer
, buffer_capacity
);
1278 ASSERT(buffer_size
< buffer_capacity
);
1281 buffer
[buffer_size
] = '\0';