]> git.saurik.com Git - apple/javascriptcore.git/blame - API/tests/testapi.c
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / API / tests / testapi.c
CommitLineData
b37bf2e1
A
1/*
2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#include "JavaScriptCore.h"
9dae56ea 27#include "JSBasePrivate.h"
f9bf01c6 28#include "JSContextRefPrivate.h"
4e4e5a6f 29#include "JSObjectRefPrivate.h"
93a37866
A
30#include "JSScriptRefPrivate.h"
31#include "JSStringRefPrivate.h"
b37bf2e1 32#include <math.h>
ba379fdc 33#define ASSERT_DISABLED 0
b37bf2e1 34#include <wtf/Assertions.h>
93a37866
A
35
36#if PLATFORM(MAC) || PLATFORM(IOS)
37#include <mach/mach.h>
38#include <mach/mach_time.h>
39#include <sys/time.h>
40#endif
b37bf2e1 41
14957cd0
A
42#if OS(WINDOWS)
43#include <windows.h>
44#endif
45
9dae56ea
A
46#if COMPILER(MSVC)
47
48#include <wtf/MathExtras.h>
49
50static double nan(const char*)
51{
52 return std::numeric_limits<double>::quiet_NaN();
53}
54
93a37866
A
55using std::isinf;
56using std::isnan;
57
9dae56ea
A
58#endif
59
93a37866
A
60#if JSC_OBJC_API_ENABLED
61void testObjectiveCAPI(void);
62#endif
63
64extern void JSSynchronousGarbageCollectForDebugging(JSContextRef);
65
f9bf01c6 66static JSGlobalContextRef context;
93a37866 67int failed;
b37bf2e1
A
68static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
69{
ba379fdc 70 if (JSValueToBoolean(context, value) != expectedValue) {
b37bf2e1 71 fprintf(stderr, "assertEqualsAsBoolean failed: %p, %d\n", value, expectedValue);
ba379fdc
A
72 failed = 1;
73 }
b37bf2e1
A
74}
75
76static void assertEqualsAsNumber(JSValueRef value, double expectedValue)
77{
78 double number = JSValueToNumber(context, value, NULL);
79
80 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
81 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
82 // After that's resolved, we can remove these casts
ba379fdc 83 if (number != expectedValue && !(isnan((float)number) && isnan((float)expectedValue))) {
b37bf2e1 84 fprintf(stderr, "assertEqualsAsNumber failed: %p, %lf\n", value, expectedValue);
ba379fdc
A
85 failed = 1;
86 }
b37bf2e1
A
87}
88
89static void assertEqualsAsUTF8String(JSValueRef value, const char* expectedValue)
90{
91 JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
92
93 size_t jsSize = JSStringGetMaximumUTF8CStringSize(valueAsString);
9dae56ea 94 char* jsBuffer = (char*)malloc(jsSize);
b37bf2e1
A
95 JSStringGetUTF8CString(valueAsString, jsBuffer, jsSize);
96
97 unsigned i;
ba379fdc
A
98 for (i = 0; jsBuffer[i]; i++) {
99 if (jsBuffer[i] != expectedValue[i]) {
b37bf2e1 100 fprintf(stderr, "assertEqualsAsUTF8String failed at character %d: %c(%d) != %c(%d)\n", i, jsBuffer[i], jsBuffer[i], expectedValue[i], expectedValue[i]);
ba379fdc
A
101 failed = 1;
102 }
103 }
104
105 if (jsSize < strlen(jsBuffer) + 1) {
b37bf2e1 106 fprintf(stderr, "assertEqualsAsUTF8String failed: jsSize was too small\n");
ba379fdc
A
107 failed = 1;
108 }
b37bf2e1 109
9dae56ea 110 free(jsBuffer);
b37bf2e1
A
111 JSStringRelease(valueAsString);
112}
113
114static void assertEqualsAsCharactersPtr(JSValueRef value, const char* expectedValue)
115{
116 JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
117
118 size_t jsLength = JSStringGetLength(valueAsString);
119 const JSChar* jsBuffer = JSStringGetCharactersPtr(valueAsString);
120
121 CFStringRef expectedValueAsCFString = CFStringCreateWithCString(kCFAllocatorDefault,
122 expectedValue,
123 kCFStringEncodingUTF8);
124 CFIndex cfLength = CFStringGetLength(expectedValueAsCFString);
9dae56ea 125 UniChar* cfBuffer = (UniChar*)malloc(cfLength * sizeof(UniChar));
b37bf2e1
A
126 CFStringGetCharacters(expectedValueAsCFString, CFRangeMake(0, cfLength), cfBuffer);
127 CFRelease(expectedValueAsCFString);
128
ba379fdc 129 if (memcmp(jsBuffer, cfBuffer, cfLength * sizeof(UniChar)) != 0) {
b37bf2e1 130 fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
ba379fdc
A
131 failed = 1;
132 }
b37bf2e1 133
ba379fdc 134 if (jsLength != (size_t)cfLength) {
b37bf2e1 135 fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength, cfLength);
ba379fdc
A
136 failed = 1;
137 }
138
9dae56ea 139 free(cfBuffer);
b37bf2e1
A
140 JSStringRelease(valueAsString);
141}
142
ba379fdc
A
143static bool timeZoneIsPST()
144{
145 char timeZoneName[70];
146 struct tm gtm;
147 memset(&gtm, 0, sizeof(gtm));
148 strftime(timeZoneName, sizeof(timeZoneName), "%Z", &gtm);
149
150 return 0 == strcmp("PST", timeZoneName);
151}
152
b37bf2e1
A
153static JSValueRef jsGlobalValue; // non-stack value for testing JSValueProtect()
154
155/* MyObject pseudo-class */
156
157static bool MyObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
158{
159 UNUSED_PARAM(context);
160 UNUSED_PARAM(object);
161
162 if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")
163 || JSStringIsEqualToUTF8CString(propertyName, "cantFind")
ba379fdc 164 || JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")
b37bf2e1
A
165 || JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")
166 || JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")
167 || JSStringIsEqualToUTF8CString(propertyName, "0")) {
168 return true;
169 }
170
171 return false;
172}
173
174static JSValueRef MyObject_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
175{
176 UNUSED_PARAM(context);
177 UNUSED_PARAM(object);
178
179 if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")) {
180 return JSValueMakeNumber(context, 1);
181 }
182
183 if (JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")) {
184 return JSValueMakeNumber(context, 1);
185 }
186
187 if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
188 return JSValueMakeUndefined(context);
189 }
f9bf01c6
A
190
191 if (JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")) {
192 return 0;
193 }
ba379fdc
A
194
195 if (JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")) {
196 return JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
197 }
198
b37bf2e1
A
199 if (JSStringIsEqualToUTF8CString(propertyName, "0")) {
200 *exception = JSValueMakeNumber(context, 1);
201 return JSValueMakeNumber(context, 1);
202 }
203
f9bf01c6 204 return JSValueMakeNull(context);
b37bf2e1
A
205}
206
207static bool MyObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
208{
209 UNUSED_PARAM(context);
210 UNUSED_PARAM(object);
211 UNUSED_PARAM(value);
212 UNUSED_PARAM(exception);
213
214 if (JSStringIsEqualToUTF8CString(propertyName, "cantSet"))
215 return true; // pretend we set the property in order to swallow it
216
ba379fdc
A
217 if (JSStringIsEqualToUTF8CString(propertyName, "throwOnSet")) {
218 JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
219 }
220
b37bf2e1
A
221 return false;
222}
223
224static bool MyObject_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
225{
226 UNUSED_PARAM(context);
227 UNUSED_PARAM(object);
228
229 if (JSStringIsEqualToUTF8CString(propertyName, "cantDelete"))
230 return true;
231
232 if (JSStringIsEqualToUTF8CString(propertyName, "throwOnDelete")) {
ba379fdc 233 JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
b37bf2e1
A
234 return false;
235 }
236
237 return false;
238}
239
240static void MyObject_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
241{
242 UNUSED_PARAM(context);
243 UNUSED_PARAM(object);
244
245 JSStringRef propertyName;
246
247 propertyName = JSStringCreateWithUTF8CString("alwaysOne");
248 JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
249 JSStringRelease(propertyName);
250
251 propertyName = JSStringCreateWithUTF8CString("myPropertyName");
252 JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
253 JSStringRelease(propertyName);
254}
255
256static JSValueRef MyObject_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
257{
258 UNUSED_PARAM(context);
259 UNUSED_PARAM(object);
260 UNUSED_PARAM(thisObject);
261 UNUSED_PARAM(exception);
262
ba379fdc
A
263 if (argumentCount > 0 && JSValueIsString(context, arguments[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, arguments[0], 0), "throwOnCall")) {
264 JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
265 return JSValueMakeUndefined(context);
266 }
267
b37bf2e1
A
268 if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
269 return JSValueMakeNumber(context, 1);
270
271 return JSValueMakeUndefined(context);
272}
273
274static JSObjectRef MyObject_callAsConstructor(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
275{
276 UNUSED_PARAM(context);
277 UNUSED_PARAM(object);
278
ba379fdc
A
279 if (argumentCount > 0 && JSValueIsString(context, arguments[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, arguments[0], 0), "throwOnConstruct")) {
280 JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
281 return object;
282 }
283
b37bf2e1
A
284 if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
285 return JSValueToObject(context, JSValueMakeNumber(context, 1), exception);
286
287 return JSValueToObject(context, JSValueMakeNumber(context, 0), exception);
288}
289
290static bool MyObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
291{
292 UNUSED_PARAM(context);
293 UNUSED_PARAM(constructor);
294
ba379fdc
A
295 if (JSValueIsString(context, possibleValue) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, possibleValue, 0), "throwOnHasInstance")) {
296 JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), constructor, JSStringCreateWithUTF8CString("test script"), 1, exception);
297 return false;
298 }
299
b37bf2e1
A
300 JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
301 JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString, exception), exception);
302 JSStringRelease(numberString);
303
304 return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor, exception);
305}
306
307static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
308{
309 UNUSED_PARAM(object);
310 UNUSED_PARAM(exception);
311
312 switch (type) {
313 case kJSTypeNumber:
314 return JSValueMakeNumber(context, 1);
9dae56ea
A
315 case kJSTypeString:
316 {
317 JSStringRef string = JSStringCreateWithUTF8CString("MyObjectAsString");
318 JSValueRef result = JSValueMakeString(context, string);
319 JSStringRelease(string);
320 return result;
321 }
b37bf2e1
A
322 default:
323 break;
324 }
325
326 // string conversion -- forward to default object class
f9bf01c6 327 return JSValueMakeNull(context);
b37bf2e1
A
328}
329
6fe7ccc8
A
330static JSValueRef MyObject_convertToTypeWrapper(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
331{
332 UNUSED_PARAM(context);
333 UNUSED_PARAM(object);
334 UNUSED_PARAM(type);
335 UNUSED_PARAM(exception);
336 // Forward to default object class
337 return 0;
338}
339
14957cd0
A
340static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
341{
342 UNUSED_PARAM(ctx);
343 UNUSED_PARAM(object);
344 UNUSED_PARAM(propertyName);
345 UNUSED_PARAM(value);
346 UNUSED_PARAM(exception);
347 return false; // Forward to parent class.
348}
349
b37bf2e1
A
350static JSStaticValue evilStaticValues[] = {
351 { "nullGetSet", 0, 0, kJSPropertyAttributeNone },
14957cd0 352 { "nullGetForwardSet", 0, MyObject_set_nullGetForwardSet, kJSPropertyAttributeNone },
b37bf2e1
A
353 { 0, 0, 0, 0 }
354};
355
356static JSStaticFunction evilStaticFunctions[] = {
357 { "nullCall", 0, kJSPropertyAttributeNone },
358 { 0, 0, 0 }
359};
360
361JSClassDefinition MyObject_definition = {
362 0,
363 kJSClassAttributeNone,
364
365 "MyObject",
366 NULL,
367
368 evilStaticValues,
369 evilStaticFunctions,
370
371 NULL,
372 NULL,
373 MyObject_hasProperty,
374 MyObject_getProperty,
375 MyObject_setProperty,
376 MyObject_deleteProperty,
377 MyObject_getPropertyNames,
378 MyObject_callAsFunction,
379 MyObject_callAsConstructor,
380 MyObject_hasInstance,
381 MyObject_convertToType,
382};
383
6fe7ccc8
A
384JSClassDefinition MyObject_convertToTypeWrapperDefinition = {
385 0,
386 kJSClassAttributeNone,
387
388 "MyObject",
389 NULL,
390
391 NULL,
392 NULL,
393
394 NULL,
395 NULL,
396 NULL,
397 NULL,
398 NULL,
399 NULL,
400 NULL,
401 NULL,
402 NULL,
403 NULL,
404 MyObject_convertToTypeWrapper,
405};
406
407JSClassDefinition MyObject_nullWrapperDefinition = {
408 0,
409 kJSClassAttributeNone,
410
411 "MyObject",
412 NULL,
413
414 NULL,
415 NULL,
416
417 NULL,
418 NULL,
419 NULL,
420 NULL,
421 NULL,
422 NULL,
423 NULL,
424 NULL,
425 NULL,
426 NULL,
427 NULL,
428};
429
b37bf2e1
A
430static JSClassRef MyObject_class(JSContextRef context)
431{
432 UNUSED_PARAM(context);
433
434 static JSClassRef jsClass;
6fe7ccc8
A
435 if (!jsClass) {
436 JSClassRef baseClass = JSClassCreate(&MyObject_definition);
437 MyObject_convertToTypeWrapperDefinition.parentClass = baseClass;
438 JSClassRef wrapperClass = JSClassCreate(&MyObject_convertToTypeWrapperDefinition);
439 MyObject_nullWrapperDefinition.parentClass = wrapperClass;
440 jsClass = JSClassCreate(&MyObject_nullWrapperDefinition);
441 }
442
b37bf2e1
A
443 return jsClass;
444}
445
14957cd0
A
446static JSValueRef PropertyCatchalls_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
447{
448 UNUSED_PARAM(context);
449 UNUSED_PARAM(object);
450 UNUSED_PARAM(propertyName);
451 UNUSED_PARAM(exception);
452
453 if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
454 static size_t count;
455 if (count++ < 5)
456 return NULL;
457
458 // Swallow all .x gets after 5, returning null.
459 return JSValueMakeNull(context);
460 }
461
462 if (JSStringIsEqualToUTF8CString(propertyName, "y")) {
463 static size_t count;
464 if (count++ < 5)
465 return NULL;
466
467 // Swallow all .y gets after 5, returning null.
468 return JSValueMakeNull(context);
469 }
470
471 if (JSStringIsEqualToUTF8CString(propertyName, "z")) {
472 static size_t count;
473 if (count++ < 5)
474 return NULL;
475
476 // Swallow all .y gets after 5, returning null.
477 return JSValueMakeNull(context);
478 }
479
480 return NULL;
481}
482
483static bool PropertyCatchalls_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
484{
485 UNUSED_PARAM(context);
486 UNUSED_PARAM(object);
487 UNUSED_PARAM(propertyName);
488 UNUSED_PARAM(value);
489 UNUSED_PARAM(exception);
490
491 if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
492 static size_t count;
493 if (count++ < 5)
494 return false;
495
496 // Swallow all .x sets after 4.
497 return true;
498 }
499
93a37866
A
500 if (JSStringIsEqualToUTF8CString(propertyName, "make_throw") || JSStringIsEqualToUTF8CString(propertyName, "0")) {
501 *exception = JSValueMakeNumber(context, 5);
502 return true;
503 }
504
14957cd0
A
505 return false;
506}
507
508static void PropertyCatchalls_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
509{
510 UNUSED_PARAM(context);
511 UNUSED_PARAM(object);
512
513 static size_t count;
514 static const char* numbers[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
515
516 // Provide a property of a different name every time.
517 JSStringRef propertyName = JSStringCreateWithUTF8CString(numbers[count++ % 10]);
518 JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
519 JSStringRelease(propertyName);
520}
521
522JSClassDefinition PropertyCatchalls_definition = {
523 0,
524 kJSClassAttributeNone,
525
526 "PropertyCatchalls",
527 NULL,
528
529 NULL,
530 NULL,
531
532 NULL,
533 NULL,
534 NULL,
535 PropertyCatchalls_getProperty,
536 PropertyCatchalls_setProperty,
537 NULL,
538 PropertyCatchalls_getPropertyNames,
539 NULL,
540 NULL,
541 NULL,
542 NULL,
543};
544
545static JSClassRef PropertyCatchalls_class(JSContextRef context)
546{
547 UNUSED_PARAM(context);
548
549 static JSClassRef jsClass;
550 if (!jsClass)
551 jsClass = JSClassCreate(&PropertyCatchalls_definition);
552
553 return jsClass;
554}
555
ba379fdc
A
556static bool EvilExceptionObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
557{
558 UNUSED_PARAM(context);
559 UNUSED_PARAM(constructor);
560
561 JSStringRef hasInstanceName = JSStringCreateWithUTF8CString("hasInstance");
562 JSValueRef hasInstance = JSObjectGetProperty(context, constructor, hasInstanceName, exception);
563 JSStringRelease(hasInstanceName);
564 if (!hasInstance)
565 return false;
566 JSObjectRef function = JSValueToObject(context, hasInstance, exception);
567 JSValueRef result = JSObjectCallAsFunction(context, function, constructor, 1, &possibleValue, exception);
568 return result && JSValueToBoolean(context, result);
569}
570
571static JSValueRef EvilExceptionObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
572{
573 UNUSED_PARAM(object);
574 UNUSED_PARAM(exception);
575 JSStringRef funcName;
576 switch (type) {
577 case kJSTypeNumber:
578 funcName = JSStringCreateWithUTF8CString("toNumber");
579 break;
580 case kJSTypeString:
581 funcName = JSStringCreateWithUTF8CString("toStringExplicit");
582 break;
583 default:
f9bf01c6 584 return JSValueMakeNull(context);
ba379fdc
A
585 break;
586 }
587
588 JSValueRef func = JSObjectGetProperty(context, object, funcName, exception);
589 JSStringRelease(funcName);
590 JSObjectRef function = JSValueToObject(context, func, exception);
591 if (!function)
f9bf01c6 592 return JSValueMakeNull(context);
ba379fdc
A
593 JSValueRef value = JSObjectCallAsFunction(context, function, object, 0, NULL, exception);
594 if (!value) {
595 JSStringRef errorString = JSStringCreateWithUTF8CString("convertToType failed");
596 JSValueRef errorStringRef = JSValueMakeString(context, errorString);
597 JSStringRelease(errorString);
598 return errorStringRef;
599 }
600 return value;
601}
602
603JSClassDefinition EvilExceptionObject_definition = {
604 0,
605 kJSClassAttributeNone,
606
607 "EvilExceptionObject",
608 NULL,
609
610 NULL,
611 NULL,
612
613 NULL,
614 NULL,
615 NULL,
616 NULL,
617 NULL,
618 NULL,
619 NULL,
620 NULL,
621 NULL,
622 EvilExceptionObject_hasInstance,
623 EvilExceptionObject_convertToType,
624};
625
626static JSClassRef EvilExceptionObject_class(JSContextRef context)
627{
628 UNUSED_PARAM(context);
629
630 static JSClassRef jsClass;
631 if (!jsClass)
632 jsClass = JSClassCreate(&EvilExceptionObject_definition);
633
634 return jsClass;
635}
636
637JSClassDefinition EmptyObject_definition = {
638 0,
639 kJSClassAttributeNone,
640
641 NULL,
642 NULL,
643
644 NULL,
645 NULL,
646
647 NULL,
648 NULL,
649 NULL,
650 NULL,
651 NULL,
652 NULL,
653 NULL,
654 NULL,
655 NULL,
656 NULL,
657 NULL,
658};
659
660static JSClassRef EmptyObject_class(JSContextRef context)
661{
662 UNUSED_PARAM(context);
663
664 static JSClassRef jsClass;
665 if (!jsClass)
666 jsClass = JSClassCreate(&EmptyObject_definition);
667
668 return jsClass;
669}
670
671
b37bf2e1
A
672static JSValueRef Base_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
673{
674 UNUSED_PARAM(object);
675 UNUSED_PARAM(propertyName);
676 UNUSED_PARAM(exception);
677
678 return JSValueMakeNumber(ctx, 1); // distinguish base get form derived get
679}
680
681static bool Base_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
682{
683 UNUSED_PARAM(object);
684 UNUSED_PARAM(propertyName);
685 UNUSED_PARAM(value);
686
687 *exception = JSValueMakeNumber(ctx, 1); // distinguish base set from derived set
688 return true;
689}
690
691static JSValueRef Base_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
692{
693 UNUSED_PARAM(function);
694 UNUSED_PARAM(thisObject);
695 UNUSED_PARAM(argumentCount);
696 UNUSED_PARAM(arguments);
697 UNUSED_PARAM(exception);
698
699 return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call
700}
701
6fe7ccc8
A
702static JSValueRef Base_returnHardNull(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
703{
704 UNUSED_PARAM(ctx);
705 UNUSED_PARAM(function);
706 UNUSED_PARAM(thisObject);
707 UNUSED_PARAM(argumentCount);
708 UNUSED_PARAM(arguments);
709 UNUSED_PARAM(exception);
710
711 return 0; // should convert to undefined!
712}
713
b37bf2e1
A
714static JSStaticFunction Base_staticFunctions[] = {
715 { "baseProtoDup", NULL, kJSPropertyAttributeNone },
716 { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone },
6fe7ccc8 717 { "baseHardNull", Base_returnHardNull, kJSPropertyAttributeNone },
b37bf2e1
A
718 { 0, 0, 0 }
719};
720
721static JSStaticValue Base_staticValues[] = {
722 { "baseDup", Base_get, Base_set, kJSPropertyAttributeNone },
723 { "baseOnly", Base_get, Base_set, kJSPropertyAttributeNone },
724 { 0, 0, 0, 0 }
725};
726
727static bool TestInitializeFinalize;
728static void Base_initialize(JSContextRef context, JSObjectRef object)
729{
730 UNUSED_PARAM(context);
731
732 if (TestInitializeFinalize) {
733 ASSERT((void*)1 == JSObjectGetPrivate(object));
734 JSObjectSetPrivate(object, (void*)2);
735 }
736}
737
738static unsigned Base_didFinalize;
739static void Base_finalize(JSObjectRef object)
740{
741 UNUSED_PARAM(object);
742 if (TestInitializeFinalize) {
743 ASSERT((void*)4 == JSObjectGetPrivate(object));
744 Base_didFinalize = true;
745 }
746}
747
748static JSClassRef Base_class(JSContextRef context)
749{
750 UNUSED_PARAM(context);
751
752 static JSClassRef jsClass;
753 if (!jsClass) {
754 JSClassDefinition definition = kJSClassDefinitionEmpty;
755 definition.staticValues = Base_staticValues;
756 definition.staticFunctions = Base_staticFunctions;
757 definition.initialize = Base_initialize;
758 definition.finalize = Base_finalize;
759 jsClass = JSClassCreate(&definition);
760 }
761 return jsClass;
762}
763
764static JSValueRef Derived_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
765{
766 UNUSED_PARAM(object);
767 UNUSED_PARAM(propertyName);
768 UNUSED_PARAM(exception);
769
770 return JSValueMakeNumber(ctx, 2); // distinguish base get form derived get
771}
772
773static bool Derived_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
774{
775 UNUSED_PARAM(ctx);
776 UNUSED_PARAM(object);
777 UNUSED_PARAM(propertyName);
778 UNUSED_PARAM(value);
779
780 *exception = JSValueMakeNumber(ctx, 2); // distinguish base set from derived set
781 return true;
782}
783
784static JSValueRef Derived_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
785{
786 UNUSED_PARAM(function);
787 UNUSED_PARAM(thisObject);
788 UNUSED_PARAM(argumentCount);
789 UNUSED_PARAM(arguments);
790 UNUSED_PARAM(exception);
791
792 return JSValueMakeNumber(ctx, 2); // distinguish base call from derived call
793}
794
795static JSStaticFunction Derived_staticFunctions[] = {
796 { "protoOnly", Derived_callAsFunction, kJSPropertyAttributeNone },
797 { "protoDup", NULL, kJSPropertyAttributeNone },
798 { "baseProtoDup", Derived_callAsFunction, kJSPropertyAttributeNone },
799 { 0, 0, 0 }
800};
801
802static JSStaticValue Derived_staticValues[] = {
803 { "derivedOnly", Derived_get, Derived_set, kJSPropertyAttributeNone },
804 { "protoDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
805 { "baseDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
806 { 0, 0, 0, 0 }
807};
808
809static void Derived_initialize(JSContextRef context, JSObjectRef object)
810{
811 UNUSED_PARAM(context);
812
813 if (TestInitializeFinalize) {
814 ASSERT((void*)2 == JSObjectGetPrivate(object));
815 JSObjectSetPrivate(object, (void*)3);
816 }
817}
818
819static void Derived_finalize(JSObjectRef object)
820{
821 if (TestInitializeFinalize) {
822 ASSERT((void*)3 == JSObjectGetPrivate(object));
823 JSObjectSetPrivate(object, (void*)4);
824 }
825}
826
827static JSClassRef Derived_class(JSContextRef context)
828{
829 static JSClassRef jsClass;
830 if (!jsClass) {
831 JSClassDefinition definition = kJSClassDefinitionEmpty;
832 definition.parentClass = Base_class(context);
833 definition.staticValues = Derived_staticValues;
834 definition.staticFunctions = Derived_staticFunctions;
835 definition.initialize = Derived_initialize;
836 definition.finalize = Derived_finalize;
837 jsClass = JSClassCreate(&definition);
838 }
839 return jsClass;
840}
841
f9bf01c6
A
842static JSClassRef Derived2_class(JSContextRef context)
843{
844 static JSClassRef jsClass;
845 if (!jsClass) {
846 JSClassDefinition definition = kJSClassDefinitionEmpty;
847 definition.parentClass = Derived_class(context);
848 jsClass = JSClassCreate(&definition);
849 }
850 return jsClass;
851}
852
853static JSValueRef print_callAsFunction(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
b37bf2e1
A
854{
855 UNUSED_PARAM(functionObject);
856 UNUSED_PARAM(thisObject);
857 UNUSED_PARAM(exception);
f9bf01c6
A
858
859 ASSERT(JSContextGetGlobalContext(ctx) == context);
b37bf2e1
A
860
861 if (argumentCount > 0) {
f9bf01c6 862 JSStringRef string = JSValueToStringCopy(ctx, arguments[0], NULL);
b37bf2e1 863 size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
9dae56ea 864 char* stringUTF8 = (char*)malloc(sizeUTF8);
b37bf2e1
A
865 JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
866 printf("%s\n", stringUTF8);
9dae56ea 867 free(stringUTF8);
b37bf2e1
A
868 JSStringRelease(string);
869 }
870
f9bf01c6 871 return JSValueMakeUndefined(ctx);
b37bf2e1
A
872}
873
874static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
875{
876 UNUSED_PARAM(constructorObject);
877 UNUSED_PARAM(exception);
878
879 JSObjectRef result = JSObjectMake(context, NULL, NULL);
880 if (argumentCount > 0) {
881 JSStringRef value = JSStringCreateWithUTF8CString("value");
882 JSObjectSetProperty(context, result, value, arguments[0], kJSPropertyAttributeNone, NULL);
883 JSStringRelease(value);
884 }
885
886 return result;
887}
888
6fe7ccc8
A
889static JSObjectRef myBadConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
890{
891 UNUSED_PARAM(context);
892 UNUSED_PARAM(constructorObject);
893 UNUSED_PARAM(argumentCount);
894 UNUSED_PARAM(arguments);
895 UNUSED_PARAM(exception);
896
897 return 0;
898}
899
b37bf2e1
A
900
901static void globalObject_initialize(JSContextRef context, JSObjectRef object)
902{
903 UNUSED_PARAM(object);
904 // Ensure that an execution context is passed in
905 ASSERT(context);
906
907 // Ensure that the global object is set to the object that we were passed
908 JSObjectRef globalObject = JSContextGetGlobalObject(context);
909 ASSERT(globalObject);
910 ASSERT(object == globalObject);
911
912 // Ensure that the standard global properties have been set on the global object
913 JSStringRef array = JSStringCreateWithUTF8CString("Array");
914 JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
915 JSStringRelease(array);
916
917 UNUSED_PARAM(arrayConstructor);
918 ASSERT(arrayConstructor);
919}
920
921static JSValueRef globalObject_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
922{
923 UNUSED_PARAM(object);
924 UNUSED_PARAM(propertyName);
925 UNUSED_PARAM(exception);
926
927 return JSValueMakeNumber(ctx, 3);
928}
929
930static bool globalObject_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
931{
932 UNUSED_PARAM(object);
933 UNUSED_PARAM(propertyName);
934 UNUSED_PARAM(value);
935
936 *exception = JSValueMakeNumber(ctx, 3);
937 return true;
938}
939
940static JSValueRef globalObject_call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
941{
942 UNUSED_PARAM(function);
943 UNUSED_PARAM(thisObject);
944 UNUSED_PARAM(argumentCount);
945 UNUSED_PARAM(arguments);
946 UNUSED_PARAM(exception);
947
948 return JSValueMakeNumber(ctx, 3);
949}
950
ba379fdc
A
951static JSValueRef functionGC(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
952{
953 UNUSED_PARAM(function);
954 UNUSED_PARAM(thisObject);
955 UNUSED_PARAM(argumentCount);
956 UNUSED_PARAM(arguments);
957 UNUSED_PARAM(exception);
958 JSGarbageCollect(context);
959 return JSValueMakeUndefined(context);
960}
961
b37bf2e1
A
962static JSStaticValue globalObject_staticValues[] = {
963 { "globalStaticValue", globalObject_get, globalObject_set, kJSPropertyAttributeNone },
964 { 0, 0, 0, 0 }
965};
966
967static JSStaticFunction globalObject_staticFunctions[] = {
968 { "globalStaticFunction", globalObject_call, kJSPropertyAttributeNone },
ba379fdc 969 { "gc", functionGC, kJSPropertyAttributeNone },
b37bf2e1
A
970 { 0, 0, 0 }
971};
972
973static char* createStringWithContentsOfFile(const char* fileName);
974
975static void testInitializeFinalize()
976{
977 JSObjectRef o = JSObjectMake(context, Derived_class(context), (void*)1);
978 UNUSED_PARAM(o);
979 ASSERT(JSObjectGetPrivate(o) == (void*)3);
980}
981
f9bf01c6
A
982static JSValueRef jsNumberValue = NULL;
983
4e4e5a6f
A
984static JSObjectRef aHeapRef = NULL;
985
f9bf01c6
A
986static void makeGlobalNumberValue(JSContextRef context) {
987 JSValueRef v = JSValueMakeNumber(context, 420);
988 JSValueProtect(context, v);
989 jsNumberValue = v;
990 v = NULL;
991}
992
14957cd0
A
993static bool assertTrue(bool value, const char* message)
994{
995 if (!value) {
996 if (message)
997 fprintf(stderr, "assertTrue failed: '%s'\n", message);
998 else
999 fprintf(stderr, "assertTrue failed.\n");
1000 failed = 1;
1001 }
1002 return value;
1003}
1004
1005static bool checkForCycleInPrototypeChain()
1006{
1007 bool result = true;
1008 JSGlobalContextRef context = JSGlobalContextCreate(0);
1009 JSObjectRef object1 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
1010 JSObjectRef object2 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
1011 JSObjectRef object3 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
1012
1013 JSObjectSetPrototype(context, object1, JSValueMakeNull(context));
1014 ASSERT(JSValueIsNull(context, JSObjectGetPrototype(context, object1)));
1015
1016 // object1 -> object1
1017 JSObjectSetPrototype(context, object1, object1);
1018 result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to assign self as a prototype");
1019
1020 // object1 -> object2 -> object1
1021 JSObjectSetPrototype(context, object2, object1);
1022 ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object1));
1023 JSObjectSetPrototype(context, object1, object2);
1024 result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to close a prototype chain cycle");
1025
1026 // object1 -> object2 -> object3 -> object1
1027 JSObjectSetPrototype(context, object2, object3);
1028 ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object3));
1029 JSObjectSetPrototype(context, object1, object2);
1030 ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object1), object2));
1031 JSObjectSetPrototype(context, object3, object1);
1032 result &= assertTrue(!JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object3), object1), "It is possible to close a prototype chain cycle");
1033
1034 JSValueRef exception;
1035 JSStringRef code = JSStringCreateWithUTF8CString("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
1036 JSStringRef file = JSStringCreateWithUTF8CString("");
1037 result &= assertTrue(!JSEvaluateScript(context, code, /* thisObject*/ 0, file, 1, &exception)
1038 , "An exception should be thrown");
1039
1040 JSStringRelease(code);
1041 JSStringRelease(file);
1042 JSGlobalContextRelease(context);
1043 return result;
1044}
1045
6fe7ccc8
A
1046static void checkConstnessInJSObjectNames()
1047{
1048 JSStaticFunction fun;
1049 fun.name = "something";
1050 JSStaticValue val;
1051 val.name = "something";
1052}
1053
93a37866
A
1054#if PLATFORM(MAC) || PLATFORM(IOS)
1055static double currentCPUTime()
1056{
1057 mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
1058 thread_basic_info_data_t info;
1059
1060 /* Get thread information */
1061 mach_port_t threadPort = mach_thread_self();
1062 thread_info(threadPort, THREAD_BASIC_INFO, (thread_info_t)(&info), &infoCount);
1063 mach_port_deallocate(mach_task_self(), threadPort);
1064
1065 double time = info.user_time.seconds + info.user_time.microseconds / 1000000.;
1066 time += info.system_time.seconds + info.system_time.microseconds / 1000000.;
1067
1068 return time;
1069}
1070
1071static JSValueRef currentCPUTime_callAsFunction(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1072{
1073 UNUSED_PARAM(functionObject);
1074 UNUSED_PARAM(thisObject);
1075 UNUSED_PARAM(argumentCount);
1076 UNUSED_PARAM(arguments);
1077 UNUSED_PARAM(exception);
1078
1079 ASSERT(JSContextGetGlobalContext(ctx) == context);
1080 return JSValueMakeNumber(ctx, currentCPUTime());
1081}
1082
1083bool shouldTerminateCallbackWasCalled = false;
1084static bool shouldTerminateCallback(JSContextRef ctx, void* context)
1085{
1086 UNUSED_PARAM(ctx);
1087 UNUSED_PARAM(context);
1088 shouldTerminateCallbackWasCalled = true;
1089 return true;
1090}
1091
1092bool cancelTerminateCallbackWasCalled = false;
1093static bool cancelTerminateCallback(JSContextRef ctx, void* context)
1094{
1095 UNUSED_PARAM(ctx);
1096 UNUSED_PARAM(context);
1097 cancelTerminateCallbackWasCalled = true;
1098 return false;
1099}
1100
1101int extendTerminateCallbackCalled = 0;
1102static bool extendTerminateCallback(JSContextRef ctx, void* context)
1103{
1104 UNUSED_PARAM(context);
1105 extendTerminateCallbackCalled++;
1106 if (extendTerminateCallbackCalled == 1) {
1107 JSContextGroupRef contextGroup = JSContextGetGroup(ctx);
1108 JSContextGroupSetExecutionTimeLimit(contextGroup, .200f, extendTerminateCallback, 0);
1109 return false;
1110 }
1111 return true;
1112}
1113#endif /* PLATFORM(MAC) || PLATFORM(IOS) */
1114
1115
b37bf2e1
A
1116int main(int argc, char* argv[])
1117{
14957cd0
A
1118#if OS(WINDOWS)
1119 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1120 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1121 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1122 ::SetErrorMode(0);
1123#endif
1124
93a37866
A
1125#if JSC_OBJC_API_ENABLED
1126 testObjectiveCAPI();
1127#endif
1128
b37bf2e1
A
1129 const char *scriptPath = "testapi.js";
1130 if (argc > 1) {
1131 scriptPath = argv[1];
1132 }
1133
1134 // Test garbage collection with a fresh context
9dae56ea 1135 context = JSGlobalContextCreateInGroup(NULL, NULL);
b37bf2e1
A
1136 TestInitializeFinalize = true;
1137 testInitializeFinalize();
1138 JSGlobalContextRelease(context);
b37bf2e1
A
1139 TestInitializeFinalize = false;
1140
1141 ASSERT(Base_didFinalize);
1142
1143 JSClassDefinition globalObjectClassDefinition = kJSClassDefinitionEmpty;
1144 globalObjectClassDefinition.initialize = globalObject_initialize;
1145 globalObjectClassDefinition.staticValues = globalObject_staticValues;
1146 globalObjectClassDefinition.staticFunctions = globalObject_staticFunctions;
1147 globalObjectClassDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
1148 JSClassRef globalObjectClass = JSClassCreate(&globalObjectClassDefinition);
9dae56ea
A
1149 context = JSGlobalContextCreateInGroup(NULL, globalObjectClass);
1150
93a37866
A
1151 JSContextGroupRef contextGroup = JSContextGetGroup(context);
1152
9dae56ea
A
1153 JSGlobalContextRetain(context);
1154 JSGlobalContextRelease(context);
f9bf01c6 1155 ASSERT(JSContextGetGlobalContext(context) == context);
b37bf2e1 1156
9dae56ea
A
1157 JSReportExtraMemoryCost(context, 0);
1158 JSReportExtraMemoryCost(context, 1);
1159 JSReportExtraMemoryCost(context, 1024);
1160
b37bf2e1
A
1161 JSObjectRef globalObject = JSContextGetGlobalObject(context);
1162 ASSERT(JSValueIsObject(context, globalObject));
1163
1164 JSValueRef jsUndefined = JSValueMakeUndefined(context);
1165 JSValueRef jsNull = JSValueMakeNull(context);
1166 JSValueRef jsTrue = JSValueMakeBoolean(context, true);
1167 JSValueRef jsFalse = JSValueMakeBoolean(context, false);
1168 JSValueRef jsZero = JSValueMakeNumber(context, 0);
1169 JSValueRef jsOne = JSValueMakeNumber(context, 1);
1170 JSValueRef jsOneThird = JSValueMakeNumber(context, 1.0 / 3.0);
1171 JSObjectRef jsObjectNoProto = JSObjectMake(context, NULL, NULL);
1172 JSObjectSetPrototype(context, jsObjectNoProto, JSValueMakeNull(context));
1173
1174 // FIXME: test funny utf8 characters
1175 JSStringRef jsEmptyIString = JSStringCreateWithUTF8CString("");
1176 JSValueRef jsEmptyString = JSValueMakeString(context, jsEmptyIString);
1177
1178 JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
1179 JSValueRef jsOneString = JSValueMakeString(context, jsOneIString);
1180
1181 UniChar singleUniChar = 65; // Capital A
1182 CFMutableStringRef cfString =
1183 CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault,
1184 &singleUniChar,
1185 1,
1186 1,
1187 kCFAllocatorNull);
1188
1189 JSStringRef jsCFIString = JSStringCreateWithCFString(cfString);
1190 JSValueRef jsCFString = JSValueMakeString(context, jsCFIString);
1191
1192 CFStringRef cfEmptyString = CFStringCreateWithCString(kCFAllocatorDefault, "", kCFStringEncodingUTF8);
1193
1194 JSStringRef jsCFEmptyIString = JSStringCreateWithCFString(cfEmptyString);
1195 JSValueRef jsCFEmptyString = JSValueMakeString(context, jsCFEmptyIString);
1196
1197 CFIndex cfStringLength = CFStringGetLength(cfString);
9dae56ea 1198 UniChar* buffer = (UniChar*)malloc(cfStringLength * sizeof(UniChar));
b37bf2e1
A
1199 CFStringGetCharacters(cfString,
1200 CFRangeMake(0, cfStringLength),
1201 buffer);
9dae56ea 1202 JSStringRef jsCFIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, cfStringLength);
b37bf2e1
A
1203 JSValueRef jsCFStringWithCharacters = JSValueMakeString(context, jsCFIStringWithCharacters);
1204
9dae56ea
A
1205 JSStringRef jsCFEmptyIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, CFStringGetLength(cfEmptyString));
1206 free(buffer);
b37bf2e1
A
1207 JSValueRef jsCFEmptyStringWithCharacters = JSValueMakeString(context, jsCFEmptyIStringWithCharacters);
1208
93a37866
A
1209 JSChar constantString[] = { 'H', 'e', 'l', 'l', 'o', };
1210 JSStringRef constantStringRef = JSStringCreateWithCharactersNoCopy(constantString, sizeof(constantString) / sizeof(constantString[0]));
1211 ASSERT(JSStringGetCharactersPtr(constantStringRef) == constantString);
1212 JSStringRelease(constantStringRef);
1213
1214 ASSERT(JSValueGetType(context, NULL) == kJSTypeNull);
b37bf2e1
A
1215 ASSERT(JSValueGetType(context, jsUndefined) == kJSTypeUndefined);
1216 ASSERT(JSValueGetType(context, jsNull) == kJSTypeNull);
1217 ASSERT(JSValueGetType(context, jsTrue) == kJSTypeBoolean);
1218 ASSERT(JSValueGetType(context, jsFalse) == kJSTypeBoolean);
1219 ASSERT(JSValueGetType(context, jsZero) == kJSTypeNumber);
1220 ASSERT(JSValueGetType(context, jsOne) == kJSTypeNumber);
1221 ASSERT(JSValueGetType(context, jsOneThird) == kJSTypeNumber);
1222 ASSERT(JSValueGetType(context, jsEmptyString) == kJSTypeString);
1223 ASSERT(JSValueGetType(context, jsOneString) == kJSTypeString);
1224 ASSERT(JSValueGetType(context, jsCFString) == kJSTypeString);
1225 ASSERT(JSValueGetType(context, jsCFStringWithCharacters) == kJSTypeString);
1226 ASSERT(JSValueGetType(context, jsCFEmptyString) == kJSTypeString);
1227 ASSERT(JSValueGetType(context, jsCFEmptyStringWithCharacters) == kJSTypeString);
1228
93a37866
A
1229 ASSERT(!JSValueIsBoolean(context, NULL));
1230 ASSERT(!JSValueIsObject(context, NULL));
1231 ASSERT(!JSValueIsString(context, NULL));
1232 ASSERT(!JSValueIsNumber(context, NULL));
1233 ASSERT(!JSValueIsUndefined(context, NULL));
1234 ASSERT(JSValueIsNull(context, NULL));
1235 ASSERT(!JSObjectCallAsFunction(context, NULL, NULL, 0, NULL, NULL));
1236 ASSERT(!JSObjectCallAsConstructor(context, NULL, 0, NULL, NULL));
1237 ASSERT(!JSObjectIsConstructor(context, NULL));
1238 ASSERT(!JSObjectIsFunction(context, NULL));
1239
1240 JSStringRef nullString = JSStringCreateWithUTF8CString(0);
1241 const JSChar* characters = JSStringGetCharactersPtr(nullString);
1242 if (characters) {
1243 printf("FAIL: Didn't return null when accessing character pointer of a null String.\n");
1244 failed = 1;
1245 } else
1246 printf("PASS: returned null when accessing character pointer of a null String.\n");
1247
1248 size_t length = JSStringGetLength(nullString);
1249 if (length) {
1250 printf("FAIL: Didn't return 0 length for null String.\n");
1251 failed = 1;
1252 } else
1253 printf("PASS: returned 0 length for null String.\n");
1254 JSStringRelease(nullString);
1255
14957cd0
A
1256 JSObjectRef propertyCatchalls = JSObjectMake(context, PropertyCatchalls_class(context), NULL);
1257 JSStringRef propertyCatchallsString = JSStringCreateWithUTF8CString("PropertyCatchalls");
1258 JSObjectSetProperty(context, globalObject, propertyCatchallsString, propertyCatchalls, kJSPropertyAttributeNone, NULL);
1259 JSStringRelease(propertyCatchallsString);
1260
b37bf2e1
A
1261 JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
1262 JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
1263 JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
1264 JSStringRelease(myObjectIString);
1265
ba379fdc
A
1266 JSObjectRef EvilExceptionObject = JSObjectMake(context, EvilExceptionObject_class(context), NULL);
1267 JSStringRef EvilExceptionObjectIString = JSStringCreateWithUTF8CString("EvilExceptionObject");
1268 JSObjectSetProperty(context, globalObject, EvilExceptionObjectIString, EvilExceptionObject, kJSPropertyAttributeNone, NULL);
1269 JSStringRelease(EvilExceptionObjectIString);
1270
1271 JSObjectRef EmptyObject = JSObjectMake(context, EmptyObject_class(context), NULL);
1272 JSStringRef EmptyObjectIString = JSStringCreateWithUTF8CString("EmptyObject");
1273 JSObjectSetProperty(context, globalObject, EmptyObjectIString, EmptyObject, kJSPropertyAttributeNone, NULL);
1274 JSStringRelease(EmptyObjectIString);
1275
4e4e5a6f 1276 JSStringRef lengthStr = JSStringCreateWithUTF8CString("length");
14957cd0
A
1277 JSObjectRef aStackRef = JSObjectMakeArray(context, 0, 0, 0);
1278 aHeapRef = aStackRef;
4e4e5a6f
A
1279 JSObjectSetProperty(context, aHeapRef, lengthStr, JSValueMakeNumber(context, 10), 0, 0);
1280 JSStringRef privatePropertyName = JSStringCreateWithUTF8CString("privateProperty");
1281 if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, aHeapRef)) {
1282 printf("FAIL: Could not set private property.\n");
14957cd0
A
1283 failed = 1;
1284 } else
4e4e5a6f 1285 printf("PASS: Set private property.\n");
14957cd0 1286 aStackRef = 0;
4e4e5a6f
A
1287 if (JSObjectSetPrivateProperty(context, aHeapRef, privatePropertyName, aHeapRef)) {
1288 printf("FAIL: JSObjectSetPrivateProperty should fail on non-API objects.\n");
14957cd0
A
1289 failed = 1;
1290 } else
4e4e5a6f 1291 printf("PASS: Did not allow JSObjectSetPrivateProperty on a non-API object.\n");
4e4e5a6f
A
1292 if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName) != aHeapRef) {
1293 printf("FAIL: Could not retrieve private property.\n");
1294 failed = 1;
1295 } else
1296 printf("PASS: Retrieved private property.\n");
1297 if (JSObjectGetPrivateProperty(context, aHeapRef, privatePropertyName)) {
1298 printf("FAIL: JSObjectGetPrivateProperty should return NULL when called on a non-API object.\n");
1299 failed = 1;
1300 } else
1301 printf("PASS: JSObjectGetPrivateProperty return NULL.\n");
14957cd0 1302
4e4e5a6f
A
1303 if (JSObjectGetProperty(context, myObject, privatePropertyName, 0) == aHeapRef) {
1304 printf("FAIL: Accessed private property through ordinary property lookup.\n");
1305 failed = 1;
1306 } else
1307 printf("PASS: Cannot access private property through ordinary property lookup.\n");
14957cd0 1308
4e4e5a6f 1309 JSGarbageCollect(context);
14957cd0 1310
4e4e5a6f
A
1311 for (int i = 0; i < 10000; i++)
1312 JSObjectMake(context, 0, 0);
1313
14957cd0 1314 aHeapRef = JSValueToObject(context, JSObjectGetPrivateProperty(context, myObject, privatePropertyName), 0);
4e4e5a6f
A
1315 if (JSValueToNumber(context, JSObjectGetProperty(context, aHeapRef, lengthStr, 0), 0) != 10) {
1316 printf("FAIL: Private property has been collected.\n");
1317 failed = 1;
1318 } else
1319 printf("PASS: Private property does not appear to have been collected.\n");
1320 JSStringRelease(lengthStr);
14957cd0
A
1321
1322 if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, 0)) {
1323 printf("FAIL: Could not set private property to NULL.\n");
1324 failed = 1;
1325 } else
1326 printf("PASS: Set private property to NULL.\n");
1327 if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName)) {
1328 printf("FAIL: Could not retrieve private property.\n");
1329 failed = 1;
1330 } else
1331 printf("PASS: Retrieved private property.\n");
1332
93a37866
A
1333 JSStringRef nullJSON = JSStringCreateWithUTF8CString(0);
1334 JSValueRef nullJSONObject = JSValueMakeFromJSONString(context, nullJSON);
1335 if (nullJSONObject) {
1336 printf("FAIL: Did not parse null String as JSON correctly\n");
1337 failed = 1;
1338 } else
1339 printf("PASS: Parsed null String as JSON correctly.\n");
1340 JSStringRelease(nullJSON);
1341
4e4e5a6f
A
1342 JSStringRef validJSON = JSStringCreateWithUTF8CString("{\"aProperty\":true}");
1343 JSValueRef jsonObject = JSValueMakeFromJSONString(context, validJSON);
1344 JSStringRelease(validJSON);
1345 if (!JSValueIsObject(context, jsonObject)) {
1346 printf("FAIL: Did not parse valid JSON correctly\n");
1347 failed = 1;
1348 } else
1349 printf("PASS: Parsed valid JSON string.\n");
1350 JSStringRef propertyName = JSStringCreateWithUTF8CString("aProperty");
1351 assertEqualsAsBoolean(JSObjectGetProperty(context, JSValueToObject(context, jsonObject, 0), propertyName, 0), true);
1352 JSStringRelease(propertyName);
1353 JSStringRef invalidJSON = JSStringCreateWithUTF8CString("fail!");
1354 if (JSValueMakeFromJSONString(context, invalidJSON)) {
1355 printf("FAIL: Should return null for invalid JSON data\n");
1356 failed = 1;
1357 } else
1358 printf("PASS: Correctly returned null for invalid JSON data.\n");
b37bf2e1 1359 JSValueRef exception;
4e4e5a6f
A
1360 JSStringRef str = JSValueCreateJSONString(context, jsonObject, 0, 0);
1361 if (!JSStringIsEqualToUTF8CString(str, "{\"aProperty\":true}")) {
1362 printf("FAIL: Did not correctly serialise with indent of 0.\n");
1363 failed = 1;
1364 } else
1365 printf("PASS: Correctly serialised with indent of 0.\n");
1366 JSStringRelease(str);
b37bf2e1 1367
4e4e5a6f
A
1368 str = JSValueCreateJSONString(context, jsonObject, 4, 0);
1369 if (!JSStringIsEqualToUTF8CString(str, "{\n \"aProperty\": true\n}")) {
1370 printf("FAIL: Did not correctly serialise with indent of 4.\n");
1371 failed = 1;
1372 } else
1373 printf("PASS: Correctly serialised with indent of 4.\n");
1374 JSStringRelease(str);
1375 JSStringRef src = JSStringCreateWithUTF8CString("({get a(){ throw '';}})");
1376 JSValueRef unstringifiableObj = JSEvaluateScript(context, src, NULL, NULL, 1, NULL);
1377
1378 str = JSValueCreateJSONString(context, unstringifiableObj, 4, 0);
1379 if (str) {
1380 printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
1381 JSStringRelease(str);
1382 failed = 1;
1383 } else
1384 printf("PASS: returned null when attempting to serialize unserializable value.\n");
1385
1386 str = JSValueCreateJSONString(context, unstringifiableObj, 4, &exception);
1387 if (str) {
1388 printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n");
1389 JSStringRelease(str);
1390 failed = 1;
1391 } else
1392 printf("PASS: returned null when attempting to serialize unserializable value.\n");
1393 if (!exception) {
1394 printf("FAIL: Did not set exception on serialisation error\n");
1395 failed = 1;
1396 } else
1397 printf("PASS: set exception on serialisation error\n");
b37bf2e1
A
1398 // Conversions that throw exceptions
1399 exception = NULL;
1400 ASSERT(NULL == JSValueToObject(context, jsNull, &exception));
1401 ASSERT(exception);
1402
1403 exception = NULL;
1404 // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
1405 // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
1406 // After that's resolved, we can remove these casts
1407 ASSERT(isnan((float)JSValueToNumber(context, jsObjectNoProto, &exception)));
1408 ASSERT(exception);
1409
1410 exception = NULL;
1411 ASSERT(!JSValueToStringCopy(context, jsObjectNoProto, &exception));
1412 ASSERT(exception);
1413
1414 ASSERT(JSValueToBoolean(context, myObject));
1415
1416 exception = NULL;
1417 ASSERT(!JSValueIsEqual(context, jsObjectNoProto, JSValueMakeNumber(context, 1), &exception));
1418 ASSERT(exception);
1419
1420 exception = NULL;
1421 JSObjectGetPropertyAtIndex(context, myObject, 0, &exception);
1422 ASSERT(1 == JSValueToNumber(context, exception, NULL));
1423
1424 assertEqualsAsBoolean(jsUndefined, false);
1425 assertEqualsAsBoolean(jsNull, false);
1426 assertEqualsAsBoolean(jsTrue, true);
1427 assertEqualsAsBoolean(jsFalse, false);
1428 assertEqualsAsBoolean(jsZero, false);
1429 assertEqualsAsBoolean(jsOne, true);
1430 assertEqualsAsBoolean(jsOneThird, true);
1431 assertEqualsAsBoolean(jsEmptyString, false);
1432 assertEqualsAsBoolean(jsOneString, true);
1433 assertEqualsAsBoolean(jsCFString, true);
1434 assertEqualsAsBoolean(jsCFStringWithCharacters, true);
1435 assertEqualsAsBoolean(jsCFEmptyString, false);
1436 assertEqualsAsBoolean(jsCFEmptyStringWithCharacters, false);
1437
1438 assertEqualsAsNumber(jsUndefined, nan(""));
1439 assertEqualsAsNumber(jsNull, 0);
1440 assertEqualsAsNumber(jsTrue, 1);
1441 assertEqualsAsNumber(jsFalse, 0);
1442 assertEqualsAsNumber(jsZero, 0);
1443 assertEqualsAsNumber(jsOne, 1);
1444 assertEqualsAsNumber(jsOneThird, 1.0 / 3.0);
1445 assertEqualsAsNumber(jsEmptyString, 0);
1446 assertEqualsAsNumber(jsOneString, 1);
1447 assertEqualsAsNumber(jsCFString, nan(""));
1448 assertEqualsAsNumber(jsCFStringWithCharacters, nan(""));
1449 assertEqualsAsNumber(jsCFEmptyString, 0);
1450 assertEqualsAsNumber(jsCFEmptyStringWithCharacters, 0);
1451 ASSERT(sizeof(JSChar) == sizeof(UniChar));
1452
1453 assertEqualsAsCharactersPtr(jsUndefined, "undefined");
1454 assertEqualsAsCharactersPtr(jsNull, "null");
1455 assertEqualsAsCharactersPtr(jsTrue, "true");
1456 assertEqualsAsCharactersPtr(jsFalse, "false");
1457 assertEqualsAsCharactersPtr(jsZero, "0");
1458 assertEqualsAsCharactersPtr(jsOne, "1");
1459 assertEqualsAsCharactersPtr(jsOneThird, "0.3333333333333333");
1460 assertEqualsAsCharactersPtr(jsEmptyString, "");
1461 assertEqualsAsCharactersPtr(jsOneString, "1");
1462 assertEqualsAsCharactersPtr(jsCFString, "A");
1463 assertEqualsAsCharactersPtr(jsCFStringWithCharacters, "A");
1464 assertEqualsAsCharactersPtr(jsCFEmptyString, "");
1465 assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters, "");
1466
1467 assertEqualsAsUTF8String(jsUndefined, "undefined");
1468 assertEqualsAsUTF8String(jsNull, "null");
1469 assertEqualsAsUTF8String(jsTrue, "true");
1470 assertEqualsAsUTF8String(jsFalse, "false");
1471 assertEqualsAsUTF8String(jsZero, "0");
1472 assertEqualsAsUTF8String(jsOne, "1");
1473 assertEqualsAsUTF8String(jsOneThird, "0.3333333333333333");
1474 assertEqualsAsUTF8String(jsEmptyString, "");
1475 assertEqualsAsUTF8String(jsOneString, "1");
1476 assertEqualsAsUTF8String(jsCFString, "A");
1477 assertEqualsAsUTF8String(jsCFStringWithCharacters, "A");
1478 assertEqualsAsUTF8String(jsCFEmptyString, "");
1479 assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
1480
6fe7ccc8
A
1481 checkConstnessInJSObjectNames();
1482
b37bf2e1
A
1483 ASSERT(JSValueIsStrictEqual(context, jsTrue, jsTrue));
1484 ASSERT(!JSValueIsStrictEqual(context, jsOne, jsOneString));
1485
1486 ASSERT(JSValueIsEqual(context, jsOne, jsOneString, NULL));
1487 ASSERT(!JSValueIsEqual(context, jsTrue, jsFalse, NULL));
1488
1489 CFStringRef cfJSString = JSStringCopyCFString(kCFAllocatorDefault, jsCFIString);
1490 CFStringRef cfJSEmptyString = JSStringCopyCFString(kCFAllocatorDefault, jsCFEmptyIString);
1491 ASSERT(CFEqual(cfJSString, cfString));
1492 ASSERT(CFEqual(cfJSEmptyString, cfEmptyString));
1493 CFRelease(cfJSString);
1494 CFRelease(cfJSEmptyString);
1495
1496 CFRelease(cfString);
1497 CFRelease(cfEmptyString);
1498
1499 jsGlobalValue = JSObjectMake(context, NULL, NULL);
f9bf01c6 1500 makeGlobalNumberValue(context);
b37bf2e1
A
1501 JSValueProtect(context, jsGlobalValue);
1502 JSGarbageCollect(context);
1503 ASSERT(JSValueIsObject(context, jsGlobalValue));
1504 JSValueUnprotect(context, jsGlobalValue);
f9bf01c6 1505 JSValueUnprotect(context, jsNumberValue);
b37bf2e1
A
1506
1507 JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
93a37866
A
1508 const char* badSyntaxConstant = "x := 1;";
1509 JSStringRef badSyntax = JSStringCreateWithUTF8CString(badSyntaxConstant);
b37bf2e1
A
1510 ASSERT(JSCheckScriptSyntax(context, goodSyntax, NULL, 0, NULL));
1511 ASSERT(!JSCheckScriptSyntax(context, badSyntax, NULL, 0, NULL));
93a37866
A
1512 ASSERT(!JSScriptCreateFromString(contextGroup, 0, 0, badSyntax, 0, 0));
1513 ASSERT(!JSScriptCreateReferencingImmortalASCIIText(contextGroup, 0, 0, badSyntaxConstant, strlen(badSyntaxConstant), 0, 0));
b37bf2e1
A
1514
1515 JSValueRef result;
1516 JSValueRef v;
1517 JSObjectRef o;
1518 JSStringRef string;
1519
1520 result = JSEvaluateScript(context, goodSyntax, NULL, NULL, 1, NULL);
1521 ASSERT(result);
1522 ASSERT(JSValueIsEqual(context, result, jsOne, NULL));
1523
1524 exception = NULL;
1525 result = JSEvaluateScript(context, badSyntax, NULL, NULL, 1, &exception);
1526 ASSERT(!result);
1527 ASSERT(JSValueIsObject(context, exception));
1528
1529 JSStringRef array = JSStringCreateWithUTF8CString("Array");
1530 JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
1531 JSStringRelease(array);
1532 result = JSObjectCallAsConstructor(context, arrayConstructor, 0, NULL, NULL);
1533 ASSERT(result);
1534 ASSERT(JSValueIsObject(context, result));
1535 ASSERT(JSValueIsInstanceOfConstructor(context, result, arrayConstructor, NULL));
1536 ASSERT(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(context), arrayConstructor, NULL));
1537
1538 o = JSValueToObject(context, result, NULL);
1539 exception = NULL;
1540 ASSERT(JSValueIsUndefined(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception)));
1541 ASSERT(!exception);
1542
1543 JSObjectSetPropertyAtIndex(context, o, 0, JSValueMakeNumber(context, 1), &exception);
1544 ASSERT(!exception);
1545
1546 exception = NULL;
1547 ASSERT(1 == JSValueToNumber(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception), &exception));
1548 ASSERT(!exception);
1549
1550 JSStringRef functionBody;
1551 JSObjectRef function;
1552
1553 exception = NULL;
1554 functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
1555 JSStringRef line = JSStringCreateWithUTF8CString("line");
1556 ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception));
1557 ASSERT(JSValueIsObject(context, exception));
1558 v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
9dae56ea 1559 assertEqualsAsNumber(v, 1);
b37bf2e1
A
1560 JSStringRelease(functionBody);
1561 JSStringRelease(line);
1562
1563 exception = NULL;
1564 functionBody = JSStringCreateWithUTF8CString("return Array;");
1565 function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception);
1566 JSStringRelease(functionBody);
1567 ASSERT(!exception);
1568 ASSERT(JSObjectIsFunction(context, function));
1569 v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
1570 ASSERT(v);
1571 ASSERT(JSValueIsEqual(context, v, arrayConstructor, NULL));
1572
1573 exception = NULL;
1574 function = JSObjectMakeFunction(context, NULL, 0, NULL, jsEmptyIString, NULL, 0, &exception);
1575 ASSERT(!exception);
1576 v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, &exception);
1577 ASSERT(v && !exception);
1578 ASSERT(JSValueIsUndefined(context, v));
1579
1580 exception = NULL;
1581 v = NULL;
1582 JSStringRef foo = JSStringCreateWithUTF8CString("foo");
1583 JSStringRef argumentNames[] = { foo };
1584 functionBody = JSStringCreateWithUTF8CString("return foo;");
1585 function = JSObjectMakeFunction(context, foo, 1, argumentNames, functionBody, NULL, 1, &exception);
1586 ASSERT(function && !exception);
1587 JSValueRef arguments[] = { JSValueMakeNumber(context, 2) };
6fe7ccc8 1588 JSObjectCallAsFunction(context, function, NULL, 1, arguments, &exception);
b37bf2e1
A
1589 JSStringRelease(foo);
1590 JSStringRelease(functionBody);
1591
1592 string = JSValueToStringCopy(context, function, NULL);
ba379fdc 1593 assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) { return foo;\n}");
b37bf2e1
A
1594 JSStringRelease(string);
1595
1596 JSStringRef print = JSStringCreateWithUTF8CString("print");
1597 JSObjectRef printFunction = JSObjectMakeFunctionWithCallback(context, print, print_callAsFunction);
1598 JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone, NULL);
1599 JSStringRelease(print);
1600
1601 ASSERT(!JSObjectSetPrivate(printFunction, (void*)1));
1602 ASSERT(!JSObjectGetPrivate(printFunction));
1603
1604 JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyConstructor");
1605 JSObjectRef myConstructor = JSObjectMakeConstructor(context, NULL, myConstructor_callAsConstructor);
1606 JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
1607 JSStringRelease(myConstructorIString);
1608
6fe7ccc8
A
1609 JSStringRef myBadConstructorIString = JSStringCreateWithUTF8CString("MyBadConstructor");
1610 JSObjectRef myBadConstructor = JSObjectMakeConstructor(context, NULL, myBadConstructor_callAsConstructor);
1611 JSObjectSetProperty(context, globalObject, myBadConstructorIString, myBadConstructor, kJSPropertyAttributeNone, NULL);
1612 JSStringRelease(myBadConstructorIString);
1613
b37bf2e1
A
1614 ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
1615 ASSERT(!JSObjectGetPrivate(myConstructor));
1616
f9bf01c6
A
1617 string = JSStringCreateWithUTF8CString("Base");
1618 JSObjectRef baseConstructor = JSObjectMakeConstructor(context, Base_class(context), NULL);
1619 JSObjectSetProperty(context, globalObject, string, baseConstructor, kJSPropertyAttributeNone, NULL);
1620 JSStringRelease(string);
1621
b37bf2e1
A
1622 string = JSStringCreateWithUTF8CString("Derived");
1623 JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL);
1624 JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL);
1625 JSStringRelease(string);
1626
f9bf01c6
A
1627 string = JSStringCreateWithUTF8CString("Derived2");
1628 JSObjectRef derived2Constructor = JSObjectMakeConstructor(context, Derived2_class(context), NULL);
1629 JSObjectSetProperty(context, globalObject, string, derived2Constructor, kJSPropertyAttributeNone, NULL);
1630 JSStringRelease(string);
1631
b37bf2e1
A
1632 o = JSObjectMake(context, NULL, NULL);
1633 JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeNone, NULL);
1634 JSObjectSetProperty(context, o, jsCFIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeDontEnum, NULL);
1635 JSPropertyNameArrayRef nameArray = JSObjectCopyPropertyNames(context, o);
1636 size_t expectedCount = JSPropertyNameArrayGetCount(nameArray);
1637 size_t count;
1638 for (count = 0; count < expectedCount; ++count)
1639 JSPropertyNameArrayGetNameAtIndex(nameArray, count);
1640 JSPropertyNameArrayRelease(nameArray);
1641 ASSERT(count == 1); // jsCFString should not be enumerated
1642
9dae56ea
A
1643 JSValueRef argumentsArrayValues[] = { JSValueMakeNumber(context, 10), JSValueMakeNumber(context, 20) };
1644 o = JSObjectMakeArray(context, sizeof(argumentsArrayValues) / sizeof(JSValueRef), argumentsArrayValues, NULL);
1645 string = JSStringCreateWithUTF8CString("length");
1646 v = JSObjectGetProperty(context, o, string, NULL);
1647 assertEqualsAsNumber(v, 2);
1648 v = JSObjectGetPropertyAtIndex(context, o, 0, NULL);
1649 assertEqualsAsNumber(v, 10);
1650 v = JSObjectGetPropertyAtIndex(context, o, 1, NULL);
1651 assertEqualsAsNumber(v, 20);
1652
1653 o = JSObjectMakeArray(context, 0, NULL, NULL);
1654 v = JSObjectGetProperty(context, o, string, NULL);
1655 assertEqualsAsNumber(v, 0);
1656 JSStringRelease(string);
1657
1658 JSValueRef argumentsDateValues[] = { JSValueMakeNumber(context, 0) };
1659 o = JSObjectMakeDate(context, 1, argumentsDateValues, NULL);
ba379fdc
A
1660 if (timeZoneIsPST())
1661 assertEqualsAsUTF8String(o, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
9dae56ea
A
1662
1663 string = JSStringCreateWithUTF8CString("an error message");
1664 JSValueRef argumentsErrorValues[] = { JSValueMakeString(context, string) };
1665 o = JSObjectMakeError(context, 1, argumentsErrorValues, NULL);
1666 assertEqualsAsUTF8String(o, "Error: an error message");
1667 JSStringRelease(string);
1668
1669 string = JSStringCreateWithUTF8CString("foo");
1670 JSStringRef string2 = JSStringCreateWithUTF8CString("gi");
1671 JSValueRef argumentsRegExpValues[] = { JSValueMakeString(context, string), JSValueMakeString(context, string2) };
1672 o = JSObjectMakeRegExp(context, 2, argumentsRegExpValues, NULL);
1673 assertEqualsAsUTF8String(o, "/foo/gi");
1674 JSStringRelease(string);
1675 JSStringRelease(string2);
1676
b37bf2e1
A
1677 JSClassDefinition nullDefinition = kJSClassDefinitionEmpty;
1678 nullDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
1679 JSClassRef nullClass = JSClassCreate(&nullDefinition);
1680 JSClassRelease(nullClass);
1681
1682 nullDefinition = kJSClassDefinitionEmpty;
1683 nullClass = JSClassCreate(&nullDefinition);
1684 JSClassRelease(nullClass);
1685
1686 functionBody = JSStringCreateWithUTF8CString("return this;");
1687 function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
1688 JSStringRelease(functionBody);
1689 v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
1690 ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1691 v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
1692 ASSERT(JSValueIsEqual(context, v, o, NULL));
9dae56ea
A
1693
1694 functionBody = JSStringCreateWithUTF8CString("return eval(\"this\");");
1695 function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
1696 JSStringRelease(functionBody);
1697 v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
1698 ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1699 v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
1700 ASSERT(JSValueIsEqual(context, v, o, NULL));
1701
93a37866
A
1702 const char* thisScript = "this;";
1703 JSStringRef script = JSStringCreateWithUTF8CString(thisScript);
9dae56ea
A
1704 v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
1705 ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1706 v = JSEvaluateScript(context, script, o, NULL, 1, NULL);
1707 ASSERT(JSValueIsEqual(context, v, o, NULL));
1708 JSStringRelease(script);
1709
93a37866
A
1710 JSScriptRef scriptObject = JSScriptCreateReferencingImmortalASCIIText(contextGroup, 0, 0, thisScript, strlen(thisScript), 0, 0);
1711 v = JSScriptEvaluate(context, scriptObject, NULL, NULL);
1712 ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1713 v = JSScriptEvaluate(context, scriptObject, o, NULL);
1714 ASSERT(JSValueIsEqual(context, v, o, NULL));
1715 JSScriptRelease(scriptObject);
1716
9dae56ea
A
1717 script = JSStringCreateWithUTF8CString("eval(this);");
1718 v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
1719 ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
1720 v = JSEvaluateScript(context, script, o, NULL, 1, NULL);
1721 ASSERT(JSValueIsEqual(context, v, o, NULL));
1722 JSStringRelease(script);
1723
ba379fdc
A
1724 // Verify that creating a constructor for a class with no static functions does not trigger
1725 // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
1726 nullDefinition = kJSClassDefinitionEmpty;
1727 nullClass = JSClassCreate(&nullDefinition);
6fe7ccc8 1728 JSObjectMakeConstructor(context, nullClass, 0);
ba379fdc
A
1729 JSClassRelease(nullClass);
1730
9dae56ea 1731 char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
ba379fdc 1732 if (!scriptUTF8) {
b37bf2e1 1733 printf("FAIL: Test script could not be loaded.\n");
ba379fdc
A
1734 failed = 1;
1735 } else {
93a37866
A
1736 JSStringRef url = JSStringCreateWithUTF8CString(scriptPath);
1737 JSStringRef script = JSStringCreateWithUTF8CString(scriptUTF8);
1738 JSStringRef errorMessage = 0;
1739 int errorLine = 0;
1740 JSScriptRef scriptObject = JSScriptCreateFromString(contextGroup, url, 1, script, &errorMessage, &errorLine);
1741 ASSERT((!scriptObject) != (!errorMessage));
1742 if (!scriptObject) {
1743 printf("FAIL: Test script did not parse\n\t%s:%d\n\t", scriptPath, errorLine);
1744 CFStringRef errorCF = JSStringCopyCFString(kCFAllocatorDefault, errorMessage);
1745 CFShow(errorCF);
1746 CFRelease(errorCF);
1747 JSStringRelease(errorMessage);
1748 failed = 1;
1749 }
1750
1751 JSStringRelease(script);
1752 result = scriptObject ? JSScriptEvaluate(context, scriptObject, 0, &exception) : 0;
f9bf01c6 1753 if (result && JSValueIsUndefined(context, result))
b37bf2e1
A
1754 printf("PASS: Test script executed successfully.\n");
1755 else {
1756 printf("FAIL: Test script returned unexpected value:\n");
1757 JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
1758 CFStringRef exceptionCF = JSStringCopyCFString(kCFAllocatorDefault, exceptionIString);
1759 CFShow(exceptionCF);
1760 CFRelease(exceptionCF);
1761 JSStringRelease(exceptionIString);
ba379fdc 1762 failed = 1;
b37bf2e1 1763 }
93a37866 1764 JSScriptRelease(scriptObject);
b37bf2e1
A
1765 free(scriptUTF8);
1766 }
1767
93a37866
A
1768#if PLATFORM(MAC) || PLATFORM(IOS)
1769 JSStringRef currentCPUTimeStr = JSStringCreateWithUTF8CString("currentCPUTime");
1770 JSObjectRef currentCPUTimeFunction = JSObjectMakeFunctionWithCallback(context, currentCPUTimeStr, currentCPUTime_callAsFunction);
1771 JSObjectSetProperty(context, globalObject, currentCPUTimeStr, currentCPUTimeFunction, kJSPropertyAttributeNone, NULL);
1772 JSStringRelease(currentCPUTimeStr);
1773
1774 /* Test script timeout: */
1775 JSContextGroupSetExecutionTimeLimit(contextGroup, .10f, shouldTerminateCallback, 0);
1776 {
1777 const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
1778 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
1779 double startTime;
1780 double endTime;
1781 exception = NULL;
1782 shouldTerminateCallbackWasCalled = false;
1783 startTime = currentCPUTime();
1784 v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
1785 endTime = currentCPUTime();
1786
1787 if (((endTime - startTime) < .150f) && shouldTerminateCallbackWasCalled)
1788 printf("PASS: script timed out as expected.\n");
1789 else {
1790 if (!((endTime - startTime) < .150f))
1791 printf("FAIL: script did not timed out as expected.\n");
1792 if (!shouldTerminateCallbackWasCalled)
1793 printf("FAIL: script timeout callback was not called.\n");
1794 failed = true;
1795 }
1796
1797 if (!exception) {
1798 printf("FAIL: TerminatedExecutionException was not thrown.\n");
1799 failed = true;
1800 }
1801 }
1802
1803 /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */
1804 JSContextGroupSetExecutionTimeLimit(contextGroup, 0.10f, shouldTerminateCallback, 0);
1805 {
1806 const char* loopForeverScript = "var startTime = currentCPUTime(); try { while (true) { if (currentCPUTime() - startTime > .150) break; } } catch(e) { }";
1807 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
1808 double startTime;
1809 double endTime;
1810 exception = NULL;
1811 shouldTerminateCallbackWasCalled = false;
1812 startTime = currentCPUTime();
1813 v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
1814 endTime = currentCPUTime();
1815
1816 if (((endTime - startTime) >= .150f) || !shouldTerminateCallbackWasCalled) {
1817 if (!((endTime - startTime) < .150f))
1818 printf("FAIL: script did not timed out as expected.\n");
1819 if (!shouldTerminateCallbackWasCalled)
1820 printf("FAIL: script timeout callback was not called.\n");
1821 failed = true;
1822 }
1823
1824 if (exception)
1825 printf("PASS: TerminatedExecutionException was not catchable as expected.\n");
1826 else {
1827 printf("FAIL: TerminatedExecutionException was caught.\n");
1828 failed = true;
1829 }
1830 }
1831
1832 /* Test script timeout with no callback: */
1833 JSContextGroupSetExecutionTimeLimit(contextGroup, .10f, 0, 0);
1834 {
1835 const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
1836 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
1837 double startTime;
1838 double endTime;
1839 exception = NULL;
1840 startTime = currentCPUTime();
1841 v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
1842 endTime = currentCPUTime();
1843
1844 if (((endTime - startTime) < .150f) && shouldTerminateCallbackWasCalled)
1845 printf("PASS: script timed out as expected when no callback is specified.\n");
1846 else {
1847 if (!((endTime - startTime) < .150f))
1848 printf("FAIL: script did not timed out as expected when no callback is specified.\n");
1849 failed = true;
1850 }
1851
1852 if (!exception) {
1853 printf("FAIL: TerminatedExecutionException was not thrown.\n");
1854 failed = true;
1855 }
1856 }
1857
1858 /* Test script timeout cancellation: */
1859 JSContextGroupSetExecutionTimeLimit(contextGroup, 0.10f, cancelTerminateCallback, 0);
1860 {
1861 const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
1862 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
1863 double startTime;
1864 double endTime;
1865 exception = NULL;
1866 startTime = currentCPUTime();
1867 v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
1868 endTime = currentCPUTime();
1869
1870 if (((endTime - startTime) >= .150f) && cancelTerminateCallbackWasCalled && !exception)
1871 printf("PASS: script timeout was cancelled as expected.\n");
1872 else {
1873 if (((endTime - startTime) < .150) || exception)
1874 printf("FAIL: script timeout was not cancelled.\n");
1875 if (!cancelTerminateCallbackWasCalled)
1876 printf("FAIL: script timeout callback was not called.\n");
1877 failed = true;
1878 }
1879
1880 if (exception) {
1881 printf("FAIL: Unexpected TerminatedExecutionException thrown.\n");
1882 failed = true;
1883 }
1884 }
1885
1886 /* Test script timeout extension: */
1887 JSContextGroupSetExecutionTimeLimit(contextGroup, 0.100f, extendTerminateCallback, 0);
1888 {
1889 const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .500) break; } ";
1890 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
1891 double startTime;
1892 double endTime;
1893 double deltaTime;
1894 exception = NULL;
1895 startTime = currentCPUTime();
1896 v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
1897 endTime = currentCPUTime();
1898 deltaTime = endTime - startTime;
1899
1900 if ((deltaTime >= .300f) && (deltaTime < .500f) && (extendTerminateCallbackCalled == 2) && exception)
1901 printf("PASS: script timeout was extended as expected.\n");
1902 else {
1903 if (deltaTime < .200f)
1904 printf("FAIL: script timeout was not extended as expected.\n");
1905 else if (deltaTime >= .500f)
1906 printf("FAIL: script did not timeout.\n");
1907
1908 if (extendTerminateCallbackCalled < 1)
1909 printf("FAIL: script timeout callback was not called.\n");
1910 if (extendTerminateCallbackCalled < 2)
1911 printf("FAIL: script timeout callback was not called after timeout extension.\n");
1912
1913 if (!exception)
1914 printf("FAIL: TerminatedExecutionException was not thrown during timeout extension test.\n");
1915
1916 failed = true;
1917 }
1918 }
1919#endif /* PLATFORM(MAC) || PLATFORM(IOS) */
1920
b37bf2e1
A
1921 // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
1922 function = NULL;
1923 v = NULL;
1924 o = NULL;
1925 globalObject = NULL;
ba379fdc 1926 myConstructor = NULL;
b37bf2e1
A
1927
1928 JSStringRelease(jsEmptyIString);
1929 JSStringRelease(jsOneIString);
1930 JSStringRelease(jsCFIString);
1931 JSStringRelease(jsCFEmptyIString);
1932 JSStringRelease(jsCFIStringWithCharacters);
1933 JSStringRelease(jsCFEmptyIStringWithCharacters);
1934 JSStringRelease(goodSyntax);
1935 JSStringRelease(badSyntax);
1936
1937 JSGlobalContextRelease(context);
b37bf2e1
A
1938 JSClassRelease(globalObjectClass);
1939
ba379fdc
A
1940 // Test for an infinite prototype chain that used to be created. This test
1941 // passes if the call to JSObjectHasProperty() does not hang.
1942
1943 JSClassDefinition prototypeLoopClassDefinition = kJSClassDefinitionEmpty;
1944 prototypeLoopClassDefinition.staticFunctions = globalObject_staticFunctions;
1945 JSClassRef prototypeLoopClass = JSClassCreate(&prototypeLoopClassDefinition);
1946 JSGlobalContextRef prototypeLoopContext = JSGlobalContextCreateInGroup(NULL, prototypeLoopClass);
1947
1948 JSStringRef nameProperty = JSStringCreateWithUTF8CString("name");
1949 JSObjectHasProperty(prototypeLoopContext, JSContextGetGlobalObject(prototypeLoopContext), nameProperty);
1950
1951 JSGlobalContextRelease(prototypeLoopContext);
1952 JSClassRelease(prototypeLoopClass);
1953
1954 printf("PASS: Infinite prototype chain does not occur.\n");
1955
14957cd0
A
1956 if (checkForCycleInPrototypeChain())
1957 printf("PASS: A cycle in a prototype chain can't be created.\n");
1958 else {
1959 printf("FAIL: A cycle in a prototype chain can be created.\n");
1960 failed = true;
1961 }
1962
ba379fdc
A
1963 if (failed) {
1964 printf("FAIL: Some tests failed.\n");
1965 return 1;
1966 }
1967
b37bf2e1
A
1968 printf("PASS: Program exited normally.\n");
1969 return 0;
1970}
1971
1972static char* createStringWithContentsOfFile(const char* fileName)
1973{
1974 char* buffer;
1975
1976 size_t buffer_size = 0;
1977 size_t buffer_capacity = 1024;
1978 buffer = (char*)malloc(buffer_capacity);
1979
1980 FILE* f = fopen(fileName, "r");
1981 if (!f) {
1982 fprintf(stderr, "Could not open file: %s\n", fileName);
12899fa2 1983 free(buffer);
b37bf2e1
A
1984 return 0;
1985 }
1986
1987 while (!feof(f) && !ferror(f)) {
1988 buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
1989 if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
1990 buffer_capacity *= 2;
1991 buffer = (char*)realloc(buffer, buffer_capacity);
1992 ASSERT(buffer);
1993 }
1994
1995 ASSERT(buffer_size < buffer_capacity);
1996 }
1997 fclose(f);
1998 buffer[buffer_size] = '\0';
1999
2000 return buffer;
2001}