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