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"
29 #define ASSERT_DISABLED 0
30 #include <wtf/Assertions.h>
31 #include <wtf/UnusedParam.h>
35 #include <wtf/MathExtras.h>
37 static double nan(const char*)
39 return std::numeric_limits
<double>::quiet_NaN();
44 static JSGlobalContextRef context
= 0;
45 static int failed
= 0;
46 static void assertEqualsAsBoolean(JSValueRef value
, bool expectedValue
)
48 if (JSValueToBoolean(context
, value
) != expectedValue
) {
49 fprintf(stderr
, "assertEqualsAsBoolean failed: %p, %d\n", value
, expectedValue
);
54 static void assertEqualsAsNumber(JSValueRef value
, double expectedValue
)
56 double number
= JSValueToNumber(context
, value
, NULL
);
58 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
59 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
60 // After that's resolved, we can remove these casts
61 if (number
!= expectedValue
&& !(isnan((float)number
) && isnan((float)expectedValue
))) {
62 fprintf(stderr
, "assertEqualsAsNumber failed: %p, %lf\n", value
, expectedValue
);
67 static void assertEqualsAsUTF8String(JSValueRef value
, const char* expectedValue
)
69 JSStringRef valueAsString
= JSValueToStringCopy(context
, value
, NULL
);
71 size_t jsSize
= JSStringGetMaximumUTF8CStringSize(valueAsString
);
72 char* jsBuffer
= (char*)malloc(jsSize
);
73 JSStringGetUTF8CString(valueAsString
, jsBuffer
, jsSize
);
76 for (i
= 0; jsBuffer
[i
]; i
++) {
77 if (jsBuffer
[i
] != expectedValue
[i
]) {
78 fprintf(stderr
, "assertEqualsAsUTF8String failed at character %d: %c(%d) != %c(%d)\n", i
, jsBuffer
[i
], jsBuffer
[i
], expectedValue
[i
], expectedValue
[i
]);
83 if (jsSize
< strlen(jsBuffer
) + 1) {
84 fprintf(stderr
, "assertEqualsAsUTF8String failed: jsSize was too small\n");
89 JSStringRelease(valueAsString
);
92 static void assertEqualsAsCharactersPtr(JSValueRef value
, const char* expectedValue
)
94 JSStringRef valueAsString
= JSValueToStringCopy(context
, value
, NULL
);
96 size_t jsLength
= JSStringGetLength(valueAsString
);
97 const JSChar
* jsBuffer
= JSStringGetCharactersPtr(valueAsString
);
99 CFStringRef expectedValueAsCFString
= CFStringCreateWithCString(kCFAllocatorDefault
,
101 kCFStringEncodingUTF8
);
102 CFIndex cfLength
= CFStringGetLength(expectedValueAsCFString
);
103 UniChar
* cfBuffer
= (UniChar
*)malloc(cfLength
* sizeof(UniChar
));
104 CFStringGetCharacters(expectedValueAsCFString
, CFRangeMake(0, cfLength
), cfBuffer
);
105 CFRelease(expectedValueAsCFString
);
107 if (memcmp(jsBuffer
, cfBuffer
, cfLength
* sizeof(UniChar
)) != 0) {
108 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
112 if (jsLength
!= (size_t)cfLength
) {
113 fprintf(stderr
, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength
, cfLength
);
118 JSStringRelease(valueAsString
);
121 static bool timeZoneIsPST()
123 char timeZoneName
[70];
125 memset(>m
, 0, sizeof(gtm
));
126 strftime(timeZoneName
, sizeof(timeZoneName
), "%Z", >m
);
128 return 0 == strcmp("PST", timeZoneName
);
131 static JSValueRef jsGlobalValue
; // non-stack value for testing JSValueProtect()
133 /* MyObject pseudo-class */
135 static bool MyObject_hasProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
)
137 UNUSED_PARAM(context
);
138 UNUSED_PARAM(object
);
140 if (JSStringIsEqualToUTF8CString(propertyName
, "alwaysOne")
141 || JSStringIsEqualToUTF8CString(propertyName
, "cantFind")
142 || JSStringIsEqualToUTF8CString(propertyName
, "throwOnGet")
143 || JSStringIsEqualToUTF8CString(propertyName
, "myPropertyName")
144 || JSStringIsEqualToUTF8CString(propertyName
, "hasPropertyLie")
145 || JSStringIsEqualToUTF8CString(propertyName
, "0")) {
152 static JSValueRef
MyObject_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
154 UNUSED_PARAM(context
);
155 UNUSED_PARAM(object
);
157 if (JSStringIsEqualToUTF8CString(propertyName
, "alwaysOne")) {
158 return JSValueMakeNumber(context
, 1);
161 if (JSStringIsEqualToUTF8CString(propertyName
, "myPropertyName")) {
162 return JSValueMakeNumber(context
, 1);
165 if (JSStringIsEqualToUTF8CString(propertyName
, "cantFind")) {
166 return JSValueMakeUndefined(context
);
169 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnGet")) {
170 return JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
173 if (JSStringIsEqualToUTF8CString(propertyName
, "0")) {
174 *exception
= JSValueMakeNumber(context
, 1);
175 return JSValueMakeNumber(context
, 1);
181 static bool MyObject_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
183 UNUSED_PARAM(context
);
184 UNUSED_PARAM(object
);
186 UNUSED_PARAM(exception
);
188 if (JSStringIsEqualToUTF8CString(propertyName
, "cantSet"))
189 return true; // pretend we set the property in order to swallow it
191 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnSet")) {
192 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
198 static bool MyObject_deleteProperty(JSContextRef context
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
200 UNUSED_PARAM(context
);
201 UNUSED_PARAM(object
);
203 if (JSStringIsEqualToUTF8CString(propertyName
, "cantDelete"))
206 if (JSStringIsEqualToUTF8CString(propertyName
, "throwOnDelete")) {
207 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
214 static void MyObject_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef propertyNames
)
216 UNUSED_PARAM(context
);
217 UNUSED_PARAM(object
);
219 JSStringRef propertyName
;
221 propertyName
= JSStringCreateWithUTF8CString("alwaysOne");
222 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
223 JSStringRelease(propertyName
);
225 propertyName
= JSStringCreateWithUTF8CString("myPropertyName");
226 JSPropertyNameAccumulatorAddName(propertyNames
, propertyName
);
227 JSStringRelease(propertyName
);
230 static JSValueRef
MyObject_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
232 UNUSED_PARAM(context
);
233 UNUSED_PARAM(object
);
234 UNUSED_PARAM(thisObject
);
235 UNUSED_PARAM(exception
);
237 if (argumentCount
> 0 && JSValueIsString(context
, arguments
[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, arguments
[0], 0), "throwOnCall")) {
238 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
239 return JSValueMakeUndefined(context
);
242 if (argumentCount
> 0 && JSValueIsStrictEqual(context
, arguments
[0], JSValueMakeNumber(context
, 0)))
243 return JSValueMakeNumber(context
, 1);
245 return JSValueMakeUndefined(context
);
248 static JSObjectRef
MyObject_callAsConstructor(JSContextRef context
, JSObjectRef object
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
250 UNUSED_PARAM(context
);
251 UNUSED_PARAM(object
);
253 if (argumentCount
> 0 && JSValueIsString(context
, arguments
[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, arguments
[0], 0), "throwOnConstruct")) {
254 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), object
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
258 if (argumentCount
> 0 && JSValueIsStrictEqual(context
, arguments
[0], JSValueMakeNumber(context
, 0)))
259 return JSValueToObject(context
, JSValueMakeNumber(context
, 1), exception
);
261 return JSValueToObject(context
, JSValueMakeNumber(context
, 0), exception
);
264 static bool MyObject_hasInstance(JSContextRef context
, JSObjectRef constructor
, JSValueRef possibleValue
, JSValueRef
* exception
)
266 UNUSED_PARAM(context
);
267 UNUSED_PARAM(constructor
);
269 if (JSValueIsString(context
, possibleValue
) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context
, possibleValue
, 0), "throwOnHasInstance")) {
270 JSEvaluateScript(context
, JSStringCreateWithUTF8CString("throw 'an exception'"), constructor
, JSStringCreateWithUTF8CString("test script"), 1, exception
);
274 JSStringRef numberString
= JSStringCreateWithUTF8CString("Number");
275 JSObjectRef numberConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, JSContextGetGlobalObject(context
), numberString
, exception
), exception
);
276 JSStringRelease(numberString
);
278 return JSValueIsInstanceOfConstructor(context
, possibleValue
, numberConstructor
, exception
);
281 static JSValueRef
MyObject_convertToType(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
283 UNUSED_PARAM(object
);
284 UNUSED_PARAM(exception
);
288 return JSValueMakeNumber(context
, 1);
291 JSStringRef string
= JSStringCreateWithUTF8CString("MyObjectAsString");
292 JSValueRef result
= JSValueMakeString(context
, string
);
293 JSStringRelease(string
);
300 // string conversion -- forward to default object class
304 static JSStaticValue evilStaticValues
[] = {
305 { "nullGetSet", 0, 0, kJSPropertyAttributeNone
},
309 static JSStaticFunction evilStaticFunctions
[] = {
310 { "nullCall", 0, kJSPropertyAttributeNone
},
314 JSClassDefinition MyObject_definition
= {
316 kJSClassAttributeNone
,
326 MyObject_hasProperty
,
327 MyObject_getProperty
,
328 MyObject_setProperty
,
329 MyObject_deleteProperty
,
330 MyObject_getPropertyNames
,
331 MyObject_callAsFunction
,
332 MyObject_callAsConstructor
,
333 MyObject_hasInstance
,
334 MyObject_convertToType
,
337 static JSClassRef
MyObject_class(JSContextRef context
)
339 UNUSED_PARAM(context
);
341 static JSClassRef jsClass
;
343 jsClass
= JSClassCreate(&MyObject_definition
);
348 static bool EvilExceptionObject_hasInstance(JSContextRef context
, JSObjectRef constructor
, JSValueRef possibleValue
, JSValueRef
* exception
)
350 UNUSED_PARAM(context
);
351 UNUSED_PARAM(constructor
);
353 JSStringRef hasInstanceName
= JSStringCreateWithUTF8CString("hasInstance");
354 JSValueRef hasInstance
= JSObjectGetProperty(context
, constructor
, hasInstanceName
, exception
);
355 JSStringRelease(hasInstanceName
);
358 JSObjectRef function
= JSValueToObject(context
, hasInstance
, exception
);
359 JSValueRef result
= JSObjectCallAsFunction(context
, function
, constructor
, 1, &possibleValue
, exception
);
360 return result
&& JSValueToBoolean(context
, result
);
363 static JSValueRef
EvilExceptionObject_convertToType(JSContextRef context
, JSObjectRef object
, JSType type
, JSValueRef
* exception
)
365 UNUSED_PARAM(object
);
366 UNUSED_PARAM(exception
);
367 JSStringRef funcName
;
370 funcName
= JSStringCreateWithUTF8CString("toNumber");
373 funcName
= JSStringCreateWithUTF8CString("toStringExplicit");
380 JSValueRef func
= JSObjectGetProperty(context
, object
, funcName
, exception
);
381 JSStringRelease(funcName
);
382 JSObjectRef function
= JSValueToObject(context
, func
, exception
);
385 JSValueRef value
= JSObjectCallAsFunction(context
, function
, object
, 0, NULL
, exception
);
387 JSStringRef errorString
= JSStringCreateWithUTF8CString("convertToType failed");
388 JSValueRef errorStringRef
= JSValueMakeString(context
, errorString
);
389 JSStringRelease(errorString
);
390 return errorStringRef
;
395 JSClassDefinition EvilExceptionObject_definition
= {
397 kJSClassAttributeNone
,
399 "EvilExceptionObject",
414 EvilExceptionObject_hasInstance
,
415 EvilExceptionObject_convertToType
,
418 static JSClassRef
EvilExceptionObject_class(JSContextRef context
)
420 UNUSED_PARAM(context
);
422 static JSClassRef jsClass
;
424 jsClass
= JSClassCreate(&EvilExceptionObject_definition
);
429 JSClassDefinition EmptyObject_definition
= {
431 kJSClassAttributeNone
,
452 static JSClassRef
EmptyObject_class(JSContextRef context
)
454 UNUSED_PARAM(context
);
456 static JSClassRef jsClass
;
458 jsClass
= JSClassCreate(&EmptyObject_definition
);
464 static JSValueRef
Base_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
466 UNUSED_PARAM(object
);
467 UNUSED_PARAM(propertyName
);
468 UNUSED_PARAM(exception
);
470 return JSValueMakeNumber(ctx
, 1); // distinguish base get form derived get
473 static bool Base_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
475 UNUSED_PARAM(object
);
476 UNUSED_PARAM(propertyName
);
479 *exception
= JSValueMakeNumber(ctx
, 1); // distinguish base set from derived set
483 static JSValueRef
Base_callAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
485 UNUSED_PARAM(function
);
486 UNUSED_PARAM(thisObject
);
487 UNUSED_PARAM(argumentCount
);
488 UNUSED_PARAM(arguments
);
489 UNUSED_PARAM(exception
);
491 return JSValueMakeNumber(ctx
, 1); // distinguish base call from derived call
494 static JSStaticFunction Base_staticFunctions
[] = {
495 { "baseProtoDup", NULL
, kJSPropertyAttributeNone
},
496 { "baseProto", Base_callAsFunction
, kJSPropertyAttributeNone
},
500 static JSStaticValue Base_staticValues
[] = {
501 { "baseDup", Base_get
, Base_set
, kJSPropertyAttributeNone
},
502 { "baseOnly", Base_get
, Base_set
, kJSPropertyAttributeNone
},
506 static bool TestInitializeFinalize
;
507 static void Base_initialize(JSContextRef context
, JSObjectRef object
)
509 UNUSED_PARAM(context
);
511 if (TestInitializeFinalize
) {
512 ASSERT((void*)1 == JSObjectGetPrivate(object
));
513 JSObjectSetPrivate(object
, (void*)2);
517 static unsigned Base_didFinalize
;
518 static void Base_finalize(JSObjectRef object
)
520 UNUSED_PARAM(object
);
521 if (TestInitializeFinalize
) {
522 ASSERT((void*)4 == JSObjectGetPrivate(object
));
523 Base_didFinalize
= true;
527 static JSClassRef
Base_class(JSContextRef context
)
529 UNUSED_PARAM(context
);
531 static JSClassRef jsClass
;
533 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
534 definition
.staticValues
= Base_staticValues
;
535 definition
.staticFunctions
= Base_staticFunctions
;
536 definition
.initialize
= Base_initialize
;
537 definition
.finalize
= Base_finalize
;
538 jsClass
= JSClassCreate(&definition
);
543 static JSValueRef
Derived_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
545 UNUSED_PARAM(object
);
546 UNUSED_PARAM(propertyName
);
547 UNUSED_PARAM(exception
);
549 return JSValueMakeNumber(ctx
, 2); // distinguish base get form derived get
552 static bool Derived_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
555 UNUSED_PARAM(object
);
556 UNUSED_PARAM(propertyName
);
559 *exception
= JSValueMakeNumber(ctx
, 2); // distinguish base set from derived set
563 static JSValueRef
Derived_callAsFunction(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
565 UNUSED_PARAM(function
);
566 UNUSED_PARAM(thisObject
);
567 UNUSED_PARAM(argumentCount
);
568 UNUSED_PARAM(arguments
);
569 UNUSED_PARAM(exception
);
571 return JSValueMakeNumber(ctx
, 2); // distinguish base call from derived call
574 static JSStaticFunction Derived_staticFunctions
[] = {
575 { "protoOnly", Derived_callAsFunction
, kJSPropertyAttributeNone
},
576 { "protoDup", NULL
, kJSPropertyAttributeNone
},
577 { "baseProtoDup", Derived_callAsFunction
, kJSPropertyAttributeNone
},
581 static JSStaticValue Derived_staticValues
[] = {
582 { "derivedOnly", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
583 { "protoDup", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
584 { "baseDup", Derived_get
, Derived_set
, kJSPropertyAttributeNone
},
588 static void Derived_initialize(JSContextRef context
, JSObjectRef object
)
590 UNUSED_PARAM(context
);
592 if (TestInitializeFinalize
) {
593 ASSERT((void*)2 == JSObjectGetPrivate(object
));
594 JSObjectSetPrivate(object
, (void*)3);
598 static void Derived_finalize(JSObjectRef object
)
600 if (TestInitializeFinalize
) {
601 ASSERT((void*)3 == JSObjectGetPrivate(object
));
602 JSObjectSetPrivate(object
, (void*)4);
606 static JSClassRef
Derived_class(JSContextRef context
)
608 static JSClassRef jsClass
;
610 JSClassDefinition definition
= kJSClassDefinitionEmpty
;
611 definition
.parentClass
= Base_class(context
);
612 definition
.staticValues
= Derived_staticValues
;
613 definition
.staticFunctions
= Derived_staticFunctions
;
614 definition
.initialize
= Derived_initialize
;
615 definition
.finalize
= Derived_finalize
;
616 jsClass
= JSClassCreate(&definition
);
621 static JSValueRef
print_callAsFunction(JSContextRef context
, JSObjectRef functionObject
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
623 UNUSED_PARAM(functionObject
);
624 UNUSED_PARAM(thisObject
);
625 UNUSED_PARAM(exception
);
627 if (argumentCount
> 0) {
628 JSStringRef string
= JSValueToStringCopy(context
, arguments
[0], NULL
);
629 size_t sizeUTF8
= JSStringGetMaximumUTF8CStringSize(string
);
630 char* stringUTF8
= (char*)malloc(sizeUTF8
);
631 JSStringGetUTF8CString(string
, stringUTF8
, sizeUTF8
);
632 printf("%s\n", stringUTF8
);
634 JSStringRelease(string
);
637 return JSValueMakeUndefined(context
);
640 static JSObjectRef
myConstructor_callAsConstructor(JSContextRef context
, JSObjectRef constructorObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
642 UNUSED_PARAM(constructorObject
);
643 UNUSED_PARAM(exception
);
645 JSObjectRef result
= JSObjectMake(context
, NULL
, NULL
);
646 if (argumentCount
> 0) {
647 JSStringRef value
= JSStringCreateWithUTF8CString("value");
648 JSObjectSetProperty(context
, result
, value
, arguments
[0], kJSPropertyAttributeNone
, NULL
);
649 JSStringRelease(value
);
656 static void globalObject_initialize(JSContextRef context
, JSObjectRef object
)
658 UNUSED_PARAM(object
);
659 // Ensure that an execution context is passed in
662 // Ensure that the global object is set to the object that we were passed
663 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
664 ASSERT(globalObject
);
665 ASSERT(object
== globalObject
);
667 // Ensure that the standard global properties have been set on the global object
668 JSStringRef array
= JSStringCreateWithUTF8CString("Array");
669 JSObjectRef arrayConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, globalObject
, array
, NULL
), NULL
);
670 JSStringRelease(array
);
672 UNUSED_PARAM(arrayConstructor
);
673 ASSERT(arrayConstructor
);
676 static JSValueRef
globalObject_get(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
678 UNUSED_PARAM(object
);
679 UNUSED_PARAM(propertyName
);
680 UNUSED_PARAM(exception
);
682 return JSValueMakeNumber(ctx
, 3);
685 static bool globalObject_set(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSValueRef
* exception
)
687 UNUSED_PARAM(object
);
688 UNUSED_PARAM(propertyName
);
691 *exception
= JSValueMakeNumber(ctx
, 3);
695 static JSValueRef
globalObject_call(JSContextRef ctx
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
697 UNUSED_PARAM(function
);
698 UNUSED_PARAM(thisObject
);
699 UNUSED_PARAM(argumentCount
);
700 UNUSED_PARAM(arguments
);
701 UNUSED_PARAM(exception
);
703 return JSValueMakeNumber(ctx
, 3);
706 static JSValueRef
functionGC(JSContextRef context
, JSObjectRef function
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
708 UNUSED_PARAM(function
);
709 UNUSED_PARAM(thisObject
);
710 UNUSED_PARAM(argumentCount
);
711 UNUSED_PARAM(arguments
);
712 UNUSED_PARAM(exception
);
713 JSGarbageCollect(context
);
714 return JSValueMakeUndefined(context
);
717 static JSStaticValue globalObject_staticValues
[] = {
718 { "globalStaticValue", globalObject_get
, globalObject_set
, kJSPropertyAttributeNone
},
722 static JSStaticFunction globalObject_staticFunctions
[] = {
723 { "globalStaticFunction", globalObject_call
, kJSPropertyAttributeNone
},
724 { "gc", functionGC
, kJSPropertyAttributeNone
},
728 static char* createStringWithContentsOfFile(const char* fileName
);
730 static void testInitializeFinalize()
732 JSObjectRef o
= JSObjectMake(context
, Derived_class(context
), (void*)1);
734 ASSERT(JSObjectGetPrivate(o
) == (void*)3);
737 int main(int argc
, char* argv
[])
739 const char *scriptPath
= "testapi.js";
741 scriptPath
= argv
[1];
744 // Test garbage collection with a fresh context
745 context
= JSGlobalContextCreateInGroup(NULL
, NULL
);
746 TestInitializeFinalize
= true;
747 testInitializeFinalize();
748 JSGlobalContextRelease(context
);
749 TestInitializeFinalize
= false;
751 ASSERT(Base_didFinalize
);
753 JSClassDefinition globalObjectClassDefinition
= kJSClassDefinitionEmpty
;
754 globalObjectClassDefinition
.initialize
= globalObject_initialize
;
755 globalObjectClassDefinition
.staticValues
= globalObject_staticValues
;
756 globalObjectClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
757 globalObjectClassDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
758 JSClassRef globalObjectClass
= JSClassCreate(&globalObjectClassDefinition
);
759 context
= JSGlobalContextCreateInGroup(NULL
, globalObjectClass
);
761 JSGlobalContextRetain(context
);
762 JSGlobalContextRelease(context
);
764 JSReportExtraMemoryCost(context
, 0);
765 JSReportExtraMemoryCost(context
, 1);
766 JSReportExtraMemoryCost(context
, 1024);
768 JSObjectRef globalObject
= JSContextGetGlobalObject(context
);
769 ASSERT(JSValueIsObject(context
, globalObject
));
771 JSValueRef jsUndefined
= JSValueMakeUndefined(context
);
772 JSValueRef jsNull
= JSValueMakeNull(context
);
773 JSValueRef jsTrue
= JSValueMakeBoolean(context
, true);
774 JSValueRef jsFalse
= JSValueMakeBoolean(context
, false);
775 JSValueRef jsZero
= JSValueMakeNumber(context
, 0);
776 JSValueRef jsOne
= JSValueMakeNumber(context
, 1);
777 JSValueRef jsOneThird
= JSValueMakeNumber(context
, 1.0 / 3.0);
778 JSObjectRef jsObjectNoProto
= JSObjectMake(context
, NULL
, NULL
);
779 JSObjectSetPrototype(context
, jsObjectNoProto
, JSValueMakeNull(context
));
781 // FIXME: test funny utf8 characters
782 JSStringRef jsEmptyIString
= JSStringCreateWithUTF8CString("");
783 JSValueRef jsEmptyString
= JSValueMakeString(context
, jsEmptyIString
);
785 JSStringRef jsOneIString
= JSStringCreateWithUTF8CString("1");
786 JSValueRef jsOneString
= JSValueMakeString(context
, jsOneIString
);
788 UniChar singleUniChar
= 65; // Capital A
789 CFMutableStringRef cfString
=
790 CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault
,
796 JSStringRef jsCFIString
= JSStringCreateWithCFString(cfString
);
797 JSValueRef jsCFString
= JSValueMakeString(context
, jsCFIString
);
799 CFStringRef cfEmptyString
= CFStringCreateWithCString(kCFAllocatorDefault
, "", kCFStringEncodingUTF8
);
801 JSStringRef jsCFEmptyIString
= JSStringCreateWithCFString(cfEmptyString
);
802 JSValueRef jsCFEmptyString
= JSValueMakeString(context
, jsCFEmptyIString
);
804 CFIndex cfStringLength
= CFStringGetLength(cfString
);
805 UniChar
* buffer
= (UniChar
*)malloc(cfStringLength
* sizeof(UniChar
));
806 CFStringGetCharacters(cfString
,
807 CFRangeMake(0, cfStringLength
),
809 JSStringRef jsCFIStringWithCharacters
= JSStringCreateWithCharacters((JSChar
*)buffer
, cfStringLength
);
810 JSValueRef jsCFStringWithCharacters
= JSValueMakeString(context
, jsCFIStringWithCharacters
);
812 JSStringRef jsCFEmptyIStringWithCharacters
= JSStringCreateWithCharacters((JSChar
*)buffer
, CFStringGetLength(cfEmptyString
));
814 JSValueRef jsCFEmptyStringWithCharacters
= JSValueMakeString(context
, jsCFEmptyIStringWithCharacters
);
816 ASSERT(JSValueGetType(context
, jsUndefined
) == kJSTypeUndefined
);
817 ASSERT(JSValueGetType(context
, jsNull
) == kJSTypeNull
);
818 ASSERT(JSValueGetType(context
, jsTrue
) == kJSTypeBoolean
);
819 ASSERT(JSValueGetType(context
, jsFalse
) == kJSTypeBoolean
);
820 ASSERT(JSValueGetType(context
, jsZero
) == kJSTypeNumber
);
821 ASSERT(JSValueGetType(context
, jsOne
) == kJSTypeNumber
);
822 ASSERT(JSValueGetType(context
, jsOneThird
) == kJSTypeNumber
);
823 ASSERT(JSValueGetType(context
, jsEmptyString
) == kJSTypeString
);
824 ASSERT(JSValueGetType(context
, jsOneString
) == kJSTypeString
);
825 ASSERT(JSValueGetType(context
, jsCFString
) == kJSTypeString
);
826 ASSERT(JSValueGetType(context
, jsCFStringWithCharacters
) == kJSTypeString
);
827 ASSERT(JSValueGetType(context
, jsCFEmptyString
) == kJSTypeString
);
828 ASSERT(JSValueGetType(context
, jsCFEmptyStringWithCharacters
) == kJSTypeString
);
830 JSObjectRef myObject
= JSObjectMake(context
, MyObject_class(context
), NULL
);
831 JSStringRef myObjectIString
= JSStringCreateWithUTF8CString("MyObject");
832 JSObjectSetProperty(context
, globalObject
, myObjectIString
, myObject
, kJSPropertyAttributeNone
, NULL
);
833 JSStringRelease(myObjectIString
);
835 JSObjectRef EvilExceptionObject
= JSObjectMake(context
, EvilExceptionObject_class(context
), NULL
);
836 JSStringRef EvilExceptionObjectIString
= JSStringCreateWithUTF8CString("EvilExceptionObject");
837 JSObjectSetProperty(context
, globalObject
, EvilExceptionObjectIString
, EvilExceptionObject
, kJSPropertyAttributeNone
, NULL
);
838 JSStringRelease(EvilExceptionObjectIString
);
840 JSObjectRef EmptyObject
= JSObjectMake(context
, EmptyObject_class(context
), NULL
);
841 JSStringRef EmptyObjectIString
= JSStringCreateWithUTF8CString("EmptyObject");
842 JSObjectSetProperty(context
, globalObject
, EmptyObjectIString
, EmptyObject
, kJSPropertyAttributeNone
, NULL
);
843 JSStringRelease(EmptyObjectIString
);
845 JSValueRef exception
;
847 // Conversions that throw exceptions
849 ASSERT(NULL
== JSValueToObject(context
, jsNull
, &exception
));
853 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
854 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
855 // After that's resolved, we can remove these casts
856 ASSERT(isnan((float)JSValueToNumber(context
, jsObjectNoProto
, &exception
)));
860 ASSERT(!JSValueToStringCopy(context
, jsObjectNoProto
, &exception
));
863 ASSERT(JSValueToBoolean(context
, myObject
));
866 ASSERT(!JSValueIsEqual(context
, jsObjectNoProto
, JSValueMakeNumber(context
, 1), &exception
));
870 JSObjectGetPropertyAtIndex(context
, myObject
, 0, &exception
);
871 ASSERT(1 == JSValueToNumber(context
, exception
, NULL
));
873 assertEqualsAsBoolean(jsUndefined
, false);
874 assertEqualsAsBoolean(jsNull
, false);
875 assertEqualsAsBoolean(jsTrue
, true);
876 assertEqualsAsBoolean(jsFalse
, false);
877 assertEqualsAsBoolean(jsZero
, false);
878 assertEqualsAsBoolean(jsOne
, true);
879 assertEqualsAsBoolean(jsOneThird
, true);
880 assertEqualsAsBoolean(jsEmptyString
, false);
881 assertEqualsAsBoolean(jsOneString
, true);
882 assertEqualsAsBoolean(jsCFString
, true);
883 assertEqualsAsBoolean(jsCFStringWithCharacters
, true);
884 assertEqualsAsBoolean(jsCFEmptyString
, false);
885 assertEqualsAsBoolean(jsCFEmptyStringWithCharacters
, false);
887 assertEqualsAsNumber(jsUndefined
, nan(""));
888 assertEqualsAsNumber(jsNull
, 0);
889 assertEqualsAsNumber(jsTrue
, 1);
890 assertEqualsAsNumber(jsFalse
, 0);
891 assertEqualsAsNumber(jsZero
, 0);
892 assertEqualsAsNumber(jsOne
, 1);
893 assertEqualsAsNumber(jsOneThird
, 1.0 / 3.0);
894 assertEqualsAsNumber(jsEmptyString
, 0);
895 assertEqualsAsNumber(jsOneString
, 1);
896 assertEqualsAsNumber(jsCFString
, nan(""));
897 assertEqualsAsNumber(jsCFStringWithCharacters
, nan(""));
898 assertEqualsAsNumber(jsCFEmptyString
, 0);
899 assertEqualsAsNumber(jsCFEmptyStringWithCharacters
, 0);
900 ASSERT(sizeof(JSChar
) == sizeof(UniChar
));
902 assertEqualsAsCharactersPtr(jsUndefined
, "undefined");
903 assertEqualsAsCharactersPtr(jsNull
, "null");
904 assertEqualsAsCharactersPtr(jsTrue
, "true");
905 assertEqualsAsCharactersPtr(jsFalse
, "false");
906 assertEqualsAsCharactersPtr(jsZero
, "0");
907 assertEqualsAsCharactersPtr(jsOne
, "1");
908 assertEqualsAsCharactersPtr(jsOneThird
, "0.3333333333333333");
909 assertEqualsAsCharactersPtr(jsEmptyString
, "");
910 assertEqualsAsCharactersPtr(jsOneString
, "1");
911 assertEqualsAsCharactersPtr(jsCFString
, "A");
912 assertEqualsAsCharactersPtr(jsCFStringWithCharacters
, "A");
913 assertEqualsAsCharactersPtr(jsCFEmptyString
, "");
914 assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters
, "");
916 assertEqualsAsUTF8String(jsUndefined
, "undefined");
917 assertEqualsAsUTF8String(jsNull
, "null");
918 assertEqualsAsUTF8String(jsTrue
, "true");
919 assertEqualsAsUTF8String(jsFalse
, "false");
920 assertEqualsAsUTF8String(jsZero
, "0");
921 assertEqualsAsUTF8String(jsOne
, "1");
922 assertEqualsAsUTF8String(jsOneThird
, "0.3333333333333333");
923 assertEqualsAsUTF8String(jsEmptyString
, "");
924 assertEqualsAsUTF8String(jsOneString
, "1");
925 assertEqualsAsUTF8String(jsCFString
, "A");
926 assertEqualsAsUTF8String(jsCFStringWithCharacters
, "A");
927 assertEqualsAsUTF8String(jsCFEmptyString
, "");
928 assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters
, "");
930 ASSERT(JSValueIsStrictEqual(context
, jsTrue
, jsTrue
));
931 ASSERT(!JSValueIsStrictEqual(context
, jsOne
, jsOneString
));
933 ASSERT(JSValueIsEqual(context
, jsOne
, jsOneString
, NULL
));
934 ASSERT(!JSValueIsEqual(context
, jsTrue
, jsFalse
, NULL
));
936 CFStringRef cfJSString
= JSStringCopyCFString(kCFAllocatorDefault
, jsCFIString
);
937 CFStringRef cfJSEmptyString
= JSStringCopyCFString(kCFAllocatorDefault
, jsCFEmptyIString
);
938 ASSERT(CFEqual(cfJSString
, cfString
));
939 ASSERT(CFEqual(cfJSEmptyString
, cfEmptyString
));
940 CFRelease(cfJSString
);
941 CFRelease(cfJSEmptyString
);
944 CFRelease(cfEmptyString
);
946 jsGlobalValue
= JSObjectMake(context
, NULL
, NULL
);
947 JSValueProtect(context
, jsGlobalValue
);
948 JSGarbageCollect(context
);
949 ASSERT(JSValueIsObject(context
, jsGlobalValue
));
950 JSValueUnprotect(context
, jsGlobalValue
);
952 JSStringRef goodSyntax
= JSStringCreateWithUTF8CString("x = 1;");
953 JSStringRef badSyntax
= JSStringCreateWithUTF8CString("x := 1;");
954 ASSERT(JSCheckScriptSyntax(context
, goodSyntax
, NULL
, 0, NULL
));
955 ASSERT(!JSCheckScriptSyntax(context
, badSyntax
, NULL
, 0, NULL
));
962 result
= JSEvaluateScript(context
, goodSyntax
, NULL
, NULL
, 1, NULL
);
964 ASSERT(JSValueIsEqual(context
, result
, jsOne
, NULL
));
967 result
= JSEvaluateScript(context
, badSyntax
, NULL
, NULL
, 1, &exception
);
969 ASSERT(JSValueIsObject(context
, exception
));
971 JSStringRef array
= JSStringCreateWithUTF8CString("Array");
972 JSObjectRef arrayConstructor
= JSValueToObject(context
, JSObjectGetProperty(context
, globalObject
, array
, NULL
), NULL
);
973 JSStringRelease(array
);
974 result
= JSObjectCallAsConstructor(context
, arrayConstructor
, 0, NULL
, NULL
);
976 ASSERT(JSValueIsObject(context
, result
));
977 ASSERT(JSValueIsInstanceOfConstructor(context
, result
, arrayConstructor
, NULL
));
978 ASSERT(!JSValueIsInstanceOfConstructor(context
, JSValueMakeNull(context
), arrayConstructor
, NULL
));
980 o
= JSValueToObject(context
, result
, NULL
);
982 ASSERT(JSValueIsUndefined(context
, JSObjectGetPropertyAtIndex(context
, o
, 0, &exception
)));
985 JSObjectSetPropertyAtIndex(context
, o
, 0, JSValueMakeNumber(context
, 1), &exception
);
989 ASSERT(1 == JSValueToNumber(context
, JSObjectGetPropertyAtIndex(context
, o
, 0, &exception
), &exception
));
992 JSStringRef functionBody
;
993 JSObjectRef function
;
996 functionBody
= JSStringCreateWithUTF8CString("rreturn Array;");
997 JSStringRef line
= JSStringCreateWithUTF8CString("line");
998 ASSERT(!JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
));
999 ASSERT(JSValueIsObject(context
, exception
));
1000 v
= JSObjectGetProperty(context
, JSValueToObject(context
, exception
, NULL
), line
, NULL
);
1001 assertEqualsAsNumber(v
, 1);
1002 JSStringRelease(functionBody
);
1003 JSStringRelease(line
);
1006 functionBody
= JSStringCreateWithUTF8CString("return Array;");
1007 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, &exception
);
1008 JSStringRelease(functionBody
);
1010 ASSERT(JSObjectIsFunction(context
, function
));
1011 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1013 ASSERT(JSValueIsEqual(context
, v
, arrayConstructor
, NULL
));
1016 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, jsEmptyIString
, NULL
, 0, &exception
);
1018 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, &exception
);
1019 ASSERT(v
&& !exception
);
1020 ASSERT(JSValueIsUndefined(context
, v
));
1024 JSStringRef foo
= JSStringCreateWithUTF8CString("foo");
1025 JSStringRef argumentNames
[] = { foo
};
1026 functionBody
= JSStringCreateWithUTF8CString("return foo;");
1027 function
= JSObjectMakeFunction(context
, foo
, 1, argumentNames
, functionBody
, NULL
, 1, &exception
);
1028 ASSERT(function
&& !exception
);
1029 JSValueRef arguments
[] = { JSValueMakeNumber(context
, 2) };
1030 v
= JSObjectCallAsFunction(context
, function
, NULL
, 1, arguments
, &exception
);
1031 JSStringRelease(foo
);
1032 JSStringRelease(functionBody
);
1034 string
= JSValueToStringCopy(context
, function
, NULL
);
1035 assertEqualsAsUTF8String(JSValueMakeString(context
, string
), "function foo(foo) { return foo;\n}");
1036 JSStringRelease(string
);
1038 JSStringRef print
= JSStringCreateWithUTF8CString("print");
1039 JSObjectRef printFunction
= JSObjectMakeFunctionWithCallback(context
, print
, print_callAsFunction
);
1040 JSObjectSetProperty(context
, globalObject
, print
, printFunction
, kJSPropertyAttributeNone
, NULL
);
1041 JSStringRelease(print
);
1043 ASSERT(!JSObjectSetPrivate(printFunction
, (void*)1));
1044 ASSERT(!JSObjectGetPrivate(printFunction
));
1046 JSStringRef myConstructorIString
= JSStringCreateWithUTF8CString("MyConstructor");
1047 JSObjectRef myConstructor
= JSObjectMakeConstructor(context
, NULL
, myConstructor_callAsConstructor
);
1048 JSObjectSetProperty(context
, globalObject
, myConstructorIString
, myConstructor
, kJSPropertyAttributeNone
, NULL
);
1049 JSStringRelease(myConstructorIString
);
1051 ASSERT(!JSObjectSetPrivate(myConstructor
, (void*)1));
1052 ASSERT(!JSObjectGetPrivate(myConstructor
));
1054 string
= JSStringCreateWithUTF8CString("Derived");
1055 JSObjectRef derivedConstructor
= JSObjectMakeConstructor(context
, Derived_class(context
), NULL
);
1056 JSObjectSetProperty(context
, globalObject
, string
, derivedConstructor
, kJSPropertyAttributeNone
, NULL
);
1057 JSStringRelease(string
);
1059 o
= JSObjectMake(context
, NULL
, NULL
);
1060 JSObjectSetProperty(context
, o
, jsOneIString
, JSValueMakeNumber(context
, 1), kJSPropertyAttributeNone
, NULL
);
1061 JSObjectSetProperty(context
, o
, jsCFIString
, JSValueMakeNumber(context
, 1), kJSPropertyAttributeDontEnum
, NULL
);
1062 JSPropertyNameArrayRef nameArray
= JSObjectCopyPropertyNames(context
, o
);
1063 size_t expectedCount
= JSPropertyNameArrayGetCount(nameArray
);
1065 for (count
= 0; count
< expectedCount
; ++count
)
1066 JSPropertyNameArrayGetNameAtIndex(nameArray
, count
);
1067 JSPropertyNameArrayRelease(nameArray
);
1068 ASSERT(count
== 1); // jsCFString should not be enumerated
1070 JSValueRef argumentsArrayValues
[] = { JSValueMakeNumber(context
, 10), JSValueMakeNumber(context
, 20) };
1071 o
= JSObjectMakeArray(context
, sizeof(argumentsArrayValues
) / sizeof(JSValueRef
), argumentsArrayValues
, NULL
);
1072 string
= JSStringCreateWithUTF8CString("length");
1073 v
= JSObjectGetProperty(context
, o
, string
, NULL
);
1074 assertEqualsAsNumber(v
, 2);
1075 v
= JSObjectGetPropertyAtIndex(context
, o
, 0, NULL
);
1076 assertEqualsAsNumber(v
, 10);
1077 v
= JSObjectGetPropertyAtIndex(context
, o
, 1, NULL
);
1078 assertEqualsAsNumber(v
, 20);
1080 o
= JSObjectMakeArray(context
, 0, NULL
, NULL
);
1081 v
= JSObjectGetProperty(context
, o
, string
, NULL
);
1082 assertEqualsAsNumber(v
, 0);
1083 JSStringRelease(string
);
1085 JSValueRef argumentsDateValues
[] = { JSValueMakeNumber(context
, 0) };
1086 o
= JSObjectMakeDate(context
, 1, argumentsDateValues
, NULL
);
1087 if (timeZoneIsPST())
1088 assertEqualsAsUTF8String(o
, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
1090 string
= JSStringCreateWithUTF8CString("an error message");
1091 JSValueRef argumentsErrorValues
[] = { JSValueMakeString(context
, string
) };
1092 o
= JSObjectMakeError(context
, 1, argumentsErrorValues
, NULL
);
1093 assertEqualsAsUTF8String(o
, "Error: an error message");
1094 JSStringRelease(string
);
1096 string
= JSStringCreateWithUTF8CString("foo");
1097 JSStringRef string2
= JSStringCreateWithUTF8CString("gi");
1098 JSValueRef argumentsRegExpValues
[] = { JSValueMakeString(context
, string
), JSValueMakeString(context
, string2
) };
1099 o
= JSObjectMakeRegExp(context
, 2, argumentsRegExpValues
, NULL
);
1100 assertEqualsAsUTF8String(o
, "/foo/gi");
1101 JSStringRelease(string
);
1102 JSStringRelease(string2
);
1104 JSClassDefinition nullDefinition
= kJSClassDefinitionEmpty
;
1105 nullDefinition
.attributes
= kJSClassAttributeNoAutomaticPrototype
;
1106 JSClassRef nullClass
= JSClassCreate(&nullDefinition
);
1107 JSClassRelease(nullClass
);
1109 nullDefinition
= kJSClassDefinitionEmpty
;
1110 nullClass
= JSClassCreate(&nullDefinition
);
1111 JSClassRelease(nullClass
);
1113 functionBody
= JSStringCreateWithUTF8CString("return this;");
1114 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, NULL
);
1115 JSStringRelease(functionBody
);
1116 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1117 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1118 v
= JSObjectCallAsFunction(context
, function
, o
, 0, NULL
, NULL
);
1119 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1121 functionBody
= JSStringCreateWithUTF8CString("return eval(\"this\");");
1122 function
= JSObjectMakeFunction(context
, NULL
, 0, NULL
, functionBody
, NULL
, 1, NULL
);
1123 JSStringRelease(functionBody
);
1124 v
= JSObjectCallAsFunction(context
, function
, NULL
, 0, NULL
, NULL
);
1125 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1126 v
= JSObjectCallAsFunction(context
, function
, o
, 0, NULL
, NULL
);
1127 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1129 JSStringRef script
= JSStringCreateWithUTF8CString("this;");
1130 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1131 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1132 v
= JSEvaluateScript(context
, script
, o
, NULL
, 1, NULL
);
1133 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1134 JSStringRelease(script
);
1136 script
= JSStringCreateWithUTF8CString("eval(this);");
1137 v
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, NULL
);
1138 ASSERT(JSValueIsEqual(context
, v
, globalObject
, NULL
));
1139 v
= JSEvaluateScript(context
, script
, o
, NULL
, 1, NULL
);
1140 ASSERT(JSValueIsEqual(context
, v
, o
, NULL
));
1141 JSStringRelease(script
);
1143 // Verify that creating a constructor for a class with no static functions does not trigger
1144 // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
1145 nullDefinition
= kJSClassDefinitionEmpty
;
1146 nullClass
= JSClassCreate(&nullDefinition
);
1147 myConstructor
= JSObjectMakeConstructor(context
, nullClass
, 0);
1148 JSClassRelease(nullClass
);
1150 char* scriptUTF8
= createStringWithContentsOfFile(scriptPath
);
1152 printf("FAIL: Test script could not be loaded.\n");
1155 script
= JSStringCreateWithUTF8CString(scriptUTF8
);
1156 result
= JSEvaluateScript(context
, script
, NULL
, NULL
, 1, &exception
);
1157 if (JSValueIsUndefined(context
, result
))
1158 printf("PASS: Test script executed successfully.\n");
1160 printf("FAIL: Test script returned unexpected value:\n");
1161 JSStringRef exceptionIString
= JSValueToStringCopy(context
, exception
, NULL
);
1162 CFStringRef exceptionCF
= JSStringCopyCFString(kCFAllocatorDefault
, exceptionIString
);
1163 CFShow(exceptionCF
);
1164 CFRelease(exceptionCF
);
1165 JSStringRelease(exceptionIString
);
1168 JSStringRelease(script
);
1172 // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
1176 globalObject
= NULL
;
1177 myConstructor
= NULL
;
1179 JSStringRelease(jsEmptyIString
);
1180 JSStringRelease(jsOneIString
);
1181 JSStringRelease(jsCFIString
);
1182 JSStringRelease(jsCFEmptyIString
);
1183 JSStringRelease(jsCFIStringWithCharacters
);
1184 JSStringRelease(jsCFEmptyIStringWithCharacters
);
1185 JSStringRelease(goodSyntax
);
1186 JSStringRelease(badSyntax
);
1188 JSGlobalContextRelease(context
);
1189 JSClassRelease(globalObjectClass
);
1191 // Test for an infinite prototype chain that used to be created. This test
1192 // passes if the call to JSObjectHasProperty() does not hang.
1194 JSClassDefinition prototypeLoopClassDefinition
= kJSClassDefinitionEmpty
;
1195 prototypeLoopClassDefinition
.staticFunctions
= globalObject_staticFunctions
;
1196 JSClassRef prototypeLoopClass
= JSClassCreate(&prototypeLoopClassDefinition
);
1197 JSGlobalContextRef prototypeLoopContext
= JSGlobalContextCreateInGroup(NULL
, prototypeLoopClass
);
1199 JSStringRef nameProperty
= JSStringCreateWithUTF8CString("name");
1200 JSObjectHasProperty(prototypeLoopContext
, JSContextGetGlobalObject(prototypeLoopContext
), nameProperty
);
1202 JSGlobalContextRelease(prototypeLoopContext
);
1203 JSClassRelease(prototypeLoopClass
);
1205 printf("PASS: Infinite prototype chain does not occur.\n");
1208 printf("FAIL: Some tests failed.\n");
1212 printf("PASS: Program exited normally.\n");
1216 static char* createStringWithContentsOfFile(const char* fileName
)
1220 size_t buffer_size
= 0;
1221 size_t buffer_capacity
= 1024;
1222 buffer
= (char*)malloc(buffer_capacity
);
1224 FILE* f
= fopen(fileName
, "r");
1226 fprintf(stderr
, "Could not open file: %s\n", fileName
);
1230 while (!feof(f
) && !ferror(f
)) {
1231 buffer_size
+= fread(buffer
+ buffer_size
, 1, buffer_capacity
- buffer_size
, f
);
1232 if (buffer_size
== buffer_capacity
) { // guarantees space for trailing '\0'
1233 buffer_capacity
*= 2;
1234 buffer
= (char*)realloc(buffer
, buffer_capacity
);
1238 ASSERT(buffer_size
< buffer_capacity
);
1241 buffer
[buffer_size
] = '\0';