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';