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