source: webkit/trunk/JavaScriptCore/API/testapi.c@ 15384

Last change on this file since 15384 was 15384, checked in by mjs, 19 years ago

4eviewed by Geoff.


  • add handling of hasInstance callback for API objects
  • API/JSCallbackObject.cpp: (KJS::JSCallbackObject::implementsHasInstance): Check if callback is present. (KJS::JSCallbackObject::hasInstance): Invoke appropriate callback.
  • API/JSCallbackObject.h:
  • API/JSClassRef.cpp:
  • API/JSObjectRef.h:
  • API/testapi.c: (MyObject_hasInstance): Test case; should match what construct would do.
  • API/testapi.js:
File size: 23.7 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "JavaScriptCore.h"
28#include <wtf/UnusedParam.h>
29
30#if defined(__APPLE__)
31#include <CoreFoundation/CoreFoundation.h>
32#endif
33
34#include <assert.h>
35#include <math.h>
36
37static JSContextRef context = 0;
38
39static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
40{
41 if (JSValueToBoolean(context, value) != expectedValue)
42 fprintf(stderr, "assertEqualsAsBoolean failed: %p, %d\n", value, expectedValue);
43}
44
45static void assertEqualsAsNumber(JSValueRef value, double expectedValue)
46{
47 double number = JSValueToNumber(context, value);
48 if (number != expectedValue && !(isnan(number) && isnan(expectedValue)))
49 fprintf(stderr, "assertEqualsAsNumber failed: %p, %lf\n", value, expectedValue);
50}
51
52static void assertEqualsAsUTF8String(JSValueRef value, const char* expectedValue)
53{
54 JSStringRef valueAsString = JSValueToStringCopy(context, value);
55
56 size_t jsSize = JSStringGetMaximumUTF8CStringSize(valueAsString);
57 char jsBuffer[jsSize];
58 JSStringGetUTF8CString(valueAsString, jsBuffer, jsSize);
59
60 if (strcmp(jsBuffer, expectedValue) != 0)
61 fprintf(stderr, "assertEqualsAsUTF8String strcmp failed: %s != %s\n", jsBuffer, expectedValue);
62
63 if (jsSize < strlen(jsBuffer) + 1)
64 fprintf(stderr, "assertEqualsAsUTF8String failed: jsSize was too small\n");
65
66 JSStringRelease(valueAsString);
67}
68
69#if defined(__APPLE__)
70static void assertEqualsAsCharactersPtr(JSValueRef value, const char* expectedValue)
71{
72 JSStringRef valueAsString = JSValueToStringCopy(context, value);
73
74 size_t jsLength = JSStringGetLength(valueAsString);
75 const JSChar* jsBuffer = JSStringGetCharactersPtr(valueAsString);
76
77 CFStringRef expectedValueAsCFString = CFStringCreateWithCString(kCFAllocatorDefault,
78 expectedValue,
79 kCFStringEncodingUTF8);
80 CFIndex cfLength = CFStringGetLength(expectedValueAsCFString);
81 UniChar cfBuffer[cfLength];
82 CFStringGetCharacters(expectedValueAsCFString, CFRangeMake(0, cfLength), cfBuffer);
83 CFRelease(expectedValueAsCFString);
84
85 if (memcmp(jsBuffer, cfBuffer, cfLength * sizeof(UniChar)) != 0)
86 fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
87
88 if (jsLength != (size_t)cfLength)
89 fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength, cfLength);
90
91 JSStringRelease(valueAsString);
92}
93
94#endif // __APPLE__
95
96static JSValueRef jsGlobalValue; // non-stack value for testing JSValueProtect()
97
98/* MyObject pseudo-class */
99
100static bool didInitialize = false;
101static void MyObject_initialize(JSContextRef context, JSObjectRef object, JSValueRef* exception)
102{
103 UNUSED_PARAM(context);
104 UNUSED_PARAM(object);
105 didInitialize = true;
106}
107
108static bool MyObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
109{
110 UNUSED_PARAM(context);
111 UNUSED_PARAM(object);
112
113 if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")
114 || JSStringIsEqualToUTF8CString(propertyName, "cantFind")
115 || JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")) {
116 return true;
117 }
118
119 return false;
120}
121
122static JSValueRef MyObject_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
123{
124 UNUSED_PARAM(context);
125 UNUSED_PARAM(object);
126
127 if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")) {
128 return JSValueMakeNumber(1);
129 }
130
131 if (JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")) {
132 return JSValueMakeNumber(1);
133 }
134
135 if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
136 return JSValueMakeUndefined();
137 }
138
139 return NULL;
140}
141
142static bool MyObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
143{
144 UNUSED_PARAM(context);
145 UNUSED_PARAM(object);
146 UNUSED_PARAM(value);
147
148 if (JSStringIsEqualToUTF8CString(propertyName, "cantSet"))
149 return true; // pretend we set the property in order to swallow it
150
151 return false;
152}
153
154static bool MyObject_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
155{
156 UNUSED_PARAM(context);
157 UNUSED_PARAM(object);
158
159 if (JSStringIsEqualToUTF8CString(propertyName, "cantDelete"))
160 return true;
161
162 return false;
163}
164
165static void MyObject_getPropertyList(JSContextRef context, JSObjectRef object, JSPropertyListRef propertyList, JSValueRef* exception)
166{
167 UNUSED_PARAM(context);
168
169 JSStringRef propertyName;
170
171 propertyName = JSStringCreateWithUTF8CString("alwaysOne");
172 JSPropertyListAdd(propertyList, object, propertyName);
173 JSStringRelease(propertyName);
174
175 propertyName = JSStringCreateWithUTF8CString("myPropertyName");
176 JSPropertyListAdd(propertyList, object, propertyName);
177 JSStringRelease(propertyName);
178}
179
180static JSValueRef MyObject_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argc, JSValueRef argv[], JSValueRef* exception)
181{
182 UNUSED_PARAM(context);
183 UNUSED_PARAM(object);
184 UNUSED_PARAM(thisObject);
185
186 if (argc > 0 && JSValueIsStrictEqual(context, argv[0], JSValueMakeNumber(0)))
187 return JSValueMakeNumber(1);
188
189 return JSValueMakeUndefined();
190}
191
192static JSObjectRef MyObject_callAsConstructor(JSContextRef context, JSObjectRef object, size_t argc, JSValueRef argv[], JSValueRef* exception)
193{
194 UNUSED_PARAM(context);
195 UNUSED_PARAM(object);
196
197 if (argc > 0 && JSValueIsStrictEqual(context, argv[0], JSValueMakeNumber(0)))
198 return JSValueToObject(context, JSValueMakeNumber(1));
199
200 return JSValueToObject(context, JSValueMakeNumber(0));
201}
202
203static bool MyObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
204{
205 UNUSED_PARAM(context);
206
207 JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
208 JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString));
209 JSStringRelease(numberString);
210
211 return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor);
212}
213
214static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
215{
216 UNUSED_PARAM(context);
217 UNUSED_PARAM(object);
218
219 switch (type) {
220 case kJSTypeBoolean:
221 return JSValueMakeBoolean(false); // default object conversion is 'true'
222 case kJSTypeNumber:
223 return JSValueMakeNumber(1);
224 default:
225 break;
226 }
227
228 // string conversion -- forward to default object class
229 return NULL;
230}
231
232static bool didFinalize = false;
233static void MyObject_finalize(JSObjectRef object)
234{
235 UNUSED_PARAM(context);
236 UNUSED_PARAM(object);
237 didFinalize = true;
238}
239
240JSObjectCallbacks MyObject_callbacks = {
241 0,
242 MyObject_initialize,
243 MyObject_finalize,
244 MyObject_hasProperty,
245 MyObject_getProperty,
246 MyObject_setProperty,
247 MyObject_deleteProperty,
248 MyObject_getPropertyList,
249 MyObject_callAsFunction,
250 MyObject_callAsConstructor,
251 MyObject_hasInstance,
252 MyObject_convertToType,
253};
254
255static JSClassRef MyObject_class(JSContextRef context)
256{
257 static JSClassRef jsClass;
258 if (!jsClass) {
259 jsClass = JSClassCreate(NULL, NULL, &MyObject_callbacks, NULL);
260 }
261
262 return jsClass;
263}
264
265static JSValueRef print_callAsFunction(JSContextRef context, JSObjectRef functionObject, JSObjectRef thisObject, size_t argc, JSValueRef argv[], JSValueRef* exception)
266{
267 UNUSED_PARAM(functionObject);
268 UNUSED_PARAM(thisObject);
269
270 if (argc > 0) {
271 JSStringRef string = JSValueToStringCopy(context, argv[0]);
272 size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
273 char stringUTF8[sizeUTF8];
274 JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
275 printf("%s\n", stringUTF8);
276 JSStringRelease(string);
277 }
278
279 return JSValueMakeUndefined();
280}
281
282static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argc, JSValueRef argv[], JSValueRef* exception)
283{
284 UNUSED_PARAM(constructorObject);
285
286 JSObjectRef result = JSObjectMake(context, NULL, 0);
287 if (argc > 0) {
288 JSStringRef value = JSStringCreateWithUTF8CString("value");
289 JSObjectSetProperty(context, result, value, argv[0], kJSPropertyAttributeNone);
290 JSStringRelease(value);
291 }
292
293 return result;
294}
295
296static char* createStringWithContentsOfFile(const char* fileName);
297
298int main(int argc, char* argv[])
299{
300 UNUSED_PARAM(argc);
301 UNUSED_PARAM(argv);
302
303 context = JSContextCreate(NULL);
304
305 JSValueRef jsUndefined = JSValueMakeUndefined();
306 JSValueRef jsNull = JSValueMakeNull();
307 JSValueRef jsTrue = JSValueMakeBoolean(true);
308 JSValueRef jsFalse = JSValueMakeBoolean(false);
309 JSValueRef jsZero = JSValueMakeNumber(0);
310 JSValueRef jsOne = JSValueMakeNumber(1);
311 JSValueRef jsOneThird = JSValueMakeNumber(1.0 / 3.0);
312 JSObjectRef jsObjectNoProto = JSObjectMake(context, NULL, JSValueMakeNull());
313
314 // FIXME: test funny utf8 characters
315 JSStringRef jsEmptyIString = JSStringCreateWithUTF8CString("");
316 JSValueRef jsEmptyString = JSValueMakeString(jsEmptyIString);
317
318 JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
319 JSValueRef jsOneString = JSValueMakeString(jsOneIString);
320
321#if defined(__APPLE__)
322 UniChar singleUniChar = 65; // Capital A
323 CFMutableStringRef cfString =
324 CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault,
325 &singleUniChar,
326 1,
327 1,
328 kCFAllocatorNull);
329
330 JSStringRef jsCFIString = JSStringCreateWithCFString(cfString);
331 JSValueRef jsCFString = JSValueMakeString(jsCFIString);
332
333 CFStringRef cfEmptyString = CFStringCreateWithCString(kCFAllocatorDefault, "", kCFStringEncodingUTF8);
334
335 JSStringRef jsCFEmptyIString = JSStringCreateWithCFString(cfEmptyString);
336 JSValueRef jsCFEmptyString = JSValueMakeString(jsCFEmptyIString);
337
338 CFIndex cfStringLength = CFStringGetLength(cfString);
339 UniChar buffer[cfStringLength];
340 CFStringGetCharacters(cfString,
341 CFRangeMake(0, cfStringLength),
342 buffer);
343 JSStringRef jsCFIStringWithCharacters = JSStringCreateWithCharacters(buffer, cfStringLength);
344 JSValueRef jsCFStringWithCharacters = JSValueMakeString(jsCFIStringWithCharacters);
345
346 JSStringRef jsCFEmptyIStringWithCharacters = JSStringCreateWithCharacters(buffer, CFStringGetLength(cfEmptyString));
347 JSValueRef jsCFEmptyStringWithCharacters = JSValueMakeString(jsCFEmptyIStringWithCharacters);
348#endif // __APPLE__
349
350 assert(JSValueGetType(jsUndefined) == kJSTypeUndefined);
351 assert(JSValueGetType(jsNull) == kJSTypeNull);
352 assert(JSValueGetType(jsTrue) == kJSTypeBoolean);
353 assert(JSValueGetType(jsFalse) == kJSTypeBoolean);
354 assert(JSValueGetType(jsZero) == kJSTypeNumber);
355 assert(JSValueGetType(jsOne) == kJSTypeNumber);
356 assert(JSValueGetType(jsOneThird) == kJSTypeNumber);
357 assert(JSValueGetType(jsEmptyString) == kJSTypeString);
358 assert(JSValueGetType(jsOneString) == kJSTypeString);
359#if defined(__APPLE__)
360 assert(JSValueGetType(jsCFString) == kJSTypeString);
361 assert(JSValueGetType(jsCFStringWithCharacters) == kJSTypeString);
362 assert(JSValueGetType(jsCFEmptyString) == kJSTypeString);
363 assert(JSValueGetType(jsCFEmptyStringWithCharacters) == kJSTypeString);
364#endif // __APPLE__
365
366 // Conversions that throw exceptions
367 assert(NULL == JSValueToObject(context, jsNull));
368 assert(isnan(JSValueToNumber(context, jsObjectNoProto)));
369 assertEqualsAsCharactersPtr(jsObjectNoProto, "");
370
371 assertEqualsAsBoolean(jsUndefined, false);
372 assertEqualsAsBoolean(jsNull, false);
373 assertEqualsAsBoolean(jsTrue, true);
374 assertEqualsAsBoolean(jsFalse, false);
375 assertEqualsAsBoolean(jsZero, false);
376 assertEqualsAsBoolean(jsOne, true);
377 assertEqualsAsBoolean(jsOneThird, true);
378 assertEqualsAsBoolean(jsEmptyString, false);
379 assertEqualsAsBoolean(jsOneString, true);
380#if defined(__APPLE__)
381 assertEqualsAsBoolean(jsCFString, true);
382 assertEqualsAsBoolean(jsCFStringWithCharacters, true);
383 assertEqualsAsBoolean(jsCFEmptyString, false);
384 assertEqualsAsBoolean(jsCFEmptyStringWithCharacters, false);
385#endif // __APPLE__
386
387 assertEqualsAsNumber(jsUndefined, nan(""));
388 assertEqualsAsNumber(jsNull, 0);
389 assertEqualsAsNumber(jsTrue, 1);
390 assertEqualsAsNumber(jsFalse, 0);
391 assertEqualsAsNumber(jsZero, 0);
392 assertEqualsAsNumber(jsOne, 1);
393 assertEqualsAsNumber(jsOneThird, 1.0 / 3.0);
394 assertEqualsAsNumber(jsEmptyString, 0);
395 assertEqualsAsNumber(jsOneString, 1);
396#if defined(__APPLE__)
397 assertEqualsAsNumber(jsCFString, nan(""));
398 assertEqualsAsNumber(jsCFStringWithCharacters, nan(""));
399 assertEqualsAsNumber(jsCFEmptyString, 0);
400 assertEqualsAsNumber(jsCFEmptyStringWithCharacters, 0);
401 assert(sizeof(JSChar) == sizeof(UniChar));
402#endif // __APPLE__
403
404 assertEqualsAsCharactersPtr(jsUndefined, "undefined");
405 assertEqualsAsCharactersPtr(jsNull, "null");
406 assertEqualsAsCharactersPtr(jsTrue, "true");
407 assertEqualsAsCharactersPtr(jsFalse, "false");
408 assertEqualsAsCharactersPtr(jsZero, "0");
409 assertEqualsAsCharactersPtr(jsOne, "1");
410 assertEqualsAsCharactersPtr(jsOneThird, "0.3333333333333333");
411 assertEqualsAsCharactersPtr(jsEmptyString, "");
412 assertEqualsAsCharactersPtr(jsOneString, "1");
413#if defined(__APPLE__)
414 assertEqualsAsCharactersPtr(jsCFString, "A");
415 assertEqualsAsCharactersPtr(jsCFStringWithCharacters, "A");
416 assertEqualsAsCharactersPtr(jsCFEmptyString, "");
417 assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters, "");
418#endif // __APPLE__
419
420 assertEqualsAsUTF8String(jsUndefined, "undefined");
421 assertEqualsAsUTF8String(jsNull, "null");
422 assertEqualsAsUTF8String(jsTrue, "true");
423 assertEqualsAsUTF8String(jsFalse, "false");
424 assertEqualsAsUTF8String(jsZero, "0");
425 assertEqualsAsUTF8String(jsOne, "1");
426 assertEqualsAsUTF8String(jsOneThird, "0.3333333333333333");
427 assertEqualsAsUTF8String(jsEmptyString, "");
428 assertEqualsAsUTF8String(jsOneString, "1");
429#if defined(__APPLE__)
430 assertEqualsAsUTF8String(jsCFString, "A");
431 assertEqualsAsUTF8String(jsCFStringWithCharacters, "A");
432 assertEqualsAsUTF8String(jsCFEmptyString, "");
433 assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
434#endif // __APPLE__
435
436 assert(JSValueIsStrictEqual(context, jsTrue, jsTrue));
437 assert(!JSValueIsStrictEqual(context, jsOne, jsOneString));
438
439 assert(JSValueIsEqual(context, jsOne, jsOneString));
440 assert(!JSValueIsEqual(context, jsTrue, jsFalse));
441
442#if defined(__APPLE__)
443 CFStringRef cfJSString = JSStringCopyCFString(kCFAllocatorDefault, jsCFIString);
444 CFStringRef cfJSEmptyString = JSStringCopyCFString(kCFAllocatorDefault, jsCFEmptyIString);
445 assert(CFEqual(cfJSString, cfString));
446 assert(CFEqual(cfJSEmptyString, cfEmptyString));
447 CFRelease(cfJSString);
448 CFRelease(cfJSEmptyString);
449
450 CFRelease(cfString);
451 CFRelease(cfEmptyString);
452#endif // __APPLE__
453
454 jsGlobalValue = JSObjectMake(context, NULL, NULL);
455 JSValueProtect(jsGlobalValue);
456 JSGarbageCollect();
457 assert(JSValueIsObject(jsGlobalValue));
458 JSValueUnprotect(jsGlobalValue);
459
460 /* JSInterpreter.h */
461
462 JSObjectRef globalObject = JSContextGetGlobalObject(context);
463 assert(JSValueIsObject(globalObject));
464
465 JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
466 JSStringRef badSyntax = JSStringCreateWithUTF8CString("x := 1;");
467 assert(JSCheckSyntax(context, goodSyntax, NULL, 0, NULL));
468 assert(!JSCheckSyntax(context, badSyntax, NULL, 0, NULL));
469
470 JSValueRef result;
471 JSValueRef exception;
472 JSValueRef v;
473 JSObjectRef o;
474
475 result = JSEvaluate(context, goodSyntax, NULL, NULL, 1, NULL);
476 assert(result);
477 assert(JSValueIsEqual(context, result, jsOne));
478
479 exception = NULL;
480 result = JSEvaluate(context, badSyntax, NULL, NULL, 1, &exception);
481 assert(!result);
482 assert(JSValueIsObject(exception));
483
484 JSStringRef array = JSStringCreateWithUTF8CString("Array");
485 v = JSObjectGetProperty(context, globalObject, array);
486 assert(v);
487 JSObjectRef arrayConstructor = JSValueToObject(context, v);
488 JSStringRelease(array);
489 result = JSObjectCallAsConstructor(context, arrayConstructor, 0, NULL, NULL);
490 assert(result);
491 assert(JSValueIsInstanceOfConstructor(context, result, arrayConstructor));
492 assert(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(), arrayConstructor));
493
494 JSStringRef functionBody;
495
496 exception = NULL;
497 functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
498 JSStringRef line = JSStringCreateWithUTF8CString("line");
499 assert(!JSObjectMakeFunctionWithBody(context, functionBody, NULL, 1, &exception));
500 assert(JSValueIsObject(exception));
501 v = JSObjectGetProperty(context, JSValueToObject(context, exception), line);
502 assert(v);
503 assertEqualsAsNumber(v, 2); // FIXME: Lexer::setCode bumps startingLineNumber by 1 -- we need to change internal callers so that it doesn't have to (saying '0' to mean '1' in the API would be really confusing -- it's really confusing internally, in fact)
504 JSStringRelease(functionBody);
505 JSStringRelease(line);
506
507 functionBody = JSStringCreateWithUTF8CString("return Array;");
508 JSObjectRef function = JSObjectMakeFunctionWithBody(context, functionBody, NULL, 1, NULL);
509 JSStringRelease(functionBody);
510
511 assert(JSObjectIsFunction(function));
512 v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
513 assert(JSValueIsEqual(context, v, arrayConstructor));
514
515 JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
516 assert(didInitialize);
517 JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
518 JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone);
519 JSStringRelease(myObjectIString);
520
521 JSStringRef print = JSStringCreateWithUTF8CString("print");
522 JSObjectRef printFunction = JSObjectMakeFunction(context, print_callAsFunction);
523 JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone);
524 JSStringRelease(print);
525
526 assert(JSObjectSetPrivate(printFunction, (void*)1));
527 assert(JSObjectGetPrivate(printFunction) == (void*)1);
528
529 JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyConstructor");
530 JSObjectRef myConstructor = JSObjectMakeConstructor(context, myConstructor_callAsConstructor);
531 JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone);
532 JSStringRelease(myConstructorIString);
533
534 assert(JSObjectSetPrivate(myConstructor, (void*)1));
535 assert(JSObjectGetPrivate(myConstructor) == (void*)1);
536
537 o = JSObjectMake(context, NULL, NULL);
538 JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(1), kJSPropertyAttributeNone);
539 JSObjectSetProperty(context, o, jsCFIString, JSValueMakeNumber(1), kJSPropertyAttributeDontEnum);
540 JSPropertyEnumeratorRef enumerator = JSObjectCreatePropertyEnumerator(context, o);
541 int count = 0;
542 while (JSPropertyEnumeratorGetNextName(enumerator))
543 ++count;
544 JSPropertyEnumeratorRelease(enumerator);
545 assert(count == 1); // jsCFString should not be enumerated
546
547 JSClassRef nullCallbacksClass = JSClassCreate(NULL, NULL, NULL, NULL);
548 JSClassRelease(nullCallbacksClass);
549
550 functionBody = JSStringCreateWithUTF8CString("return this;");
551 function = JSObjectMakeFunctionWithBody(context, functionBody, NULL, 1, NULL);
552 JSStringRelease(functionBody);
553 v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
554 assert(JSValueIsEqual(context, v, globalObject));
555 v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
556 assert(JSValueIsEqual(context, v, o));
557
558 char* scriptUTF8 = createStringWithContentsOfFile("testapi.js");
559 JSStringRef script = JSStringCreateWithUTF8CString(scriptUTF8);
560 result = JSEvaluate(context, script, NULL, NULL, 1, &exception);
561 if (JSValueIsUndefined(result))
562 printf("PASS: Test script executed successfully.\n");
563 else {
564 printf("FAIL: Test script returned unexcpected value:\n");
565 JSStringRef exceptionIString = JSValueToStringCopy(context, exception);
566 CFStringRef exceptionCF = JSStringCopyCFString(kCFAllocatorDefault, exceptionIString);
567 CFShow(exceptionCF);
568 CFRelease(exceptionCF);
569 JSStringRelease(exceptionIString);
570 }
571 JSStringRelease(script);
572 free(scriptUTF8);
573
574 // Allocate a few dummies so that at least one will be collected
575 JSObjectMake(context, MyObject_class(context), 0);
576 JSObjectMake(context, MyObject_class(context), 0);
577 JSGarbageCollect();
578 assert(didFinalize);
579
580 JSStringRelease(jsEmptyIString);
581 JSStringRelease(jsOneIString);
582#if defined(__APPLE__)
583 JSStringRelease(jsCFIString);
584 JSStringRelease(jsCFEmptyIString);
585 JSStringRelease(jsCFIStringWithCharacters);
586 JSStringRelease(jsCFEmptyIStringWithCharacters);
587#endif // __APPLE__
588 JSStringRelease(goodSyntax);
589 JSStringRelease(badSyntax);
590
591 JSContextDestroy(context);
592 printf("PASS: Program exited normally.\n");
593 return 0;
594}
595
596static char* createStringWithContentsOfFile(const char* fileName)
597{
598 char* buffer;
599
600 int buffer_size = 0;
601 int buffer_capacity = 1024;
602 buffer = (char*)malloc(buffer_capacity);
603
604 FILE* f = fopen(fileName, "r");
605 if (!f) {
606 fprintf(stderr, "Could not open file: %s\n", fileName);
607 return 0;
608 }
609
610 while (!feof(f) && !ferror(f)) {
611 buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
612 if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
613 buffer_capacity *= 2;
614 buffer = (char*)realloc(buffer, buffer_capacity);
615 assert(buffer);
616 }
617
618 assert(buffer_size < buffer_capacity);
619 }
620 fclose(f);
621 buffer[buffer_size] = '\0';
622
623 return buffer;
624}
Note: See TracBrowser for help on using the repository browser.