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

Last change on this file since 15437 was 15437, checked in by ggaren, 19 years ago

JavaScriptCore:

Reviewed by Maciej.


  • Implemented ref-counting of JSContexts by splitting into two datatypes: JSGlobalContext, which you can create/retain/release, and JSContext, which you can't.


Internally, you retain a JSGlobalContext/ExecState by retaining its
interpreter, which, in the case of a global ExecState, owns it.


  • Also made ~Interpreter() protected to catch places where Interpreter is manually deleted. (Can't make it private because some crazy fool decided it would be a good idea to subclass Interpreter in other frameworks. I pity da fool.)
  • API/APICast.h: (toJS): Added cast for new JSGlobalContext
  • API/JSStringRef.h: Changed vague "you must" language to more specific (but, ultimately, equally vague) "behavior is undefined if you don't" language. (KJS::Interpreter::Interpreter): Factored more common initialization into init()
  • kjs/interpreter.h: (KJS::Interpreter::ref): new (KJS::Interpreter::deref): new (KJS::Interpreter::refCount): new
  • kjs/testkjs.cpp: (doIt): Ref-count the interpreter.

JavaScriptGlue:

Reviewed by Maciej.


  • Updated JSInterpreter to work with Interpreter ref-counting in JavaScriptCore.

(JSInterpreter::JSInterpreter::~JSInterpreter): Now protected to catch
manual delete.

WebCore:

Reviewed by Maciej.

  • Updated ScriptInterpreter to work with Interpreter ref-counting in JavaScriptCore.

(KJS::ScriptInterpreter::~ScriptInterpreter): Now protected to catch
manual delete.

File size: 24.2 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 JSGlobalContextRef context = 0;
38
39static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
40{
41 if (JSValueToBoolean(context, value, NULL) != 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, NULL);
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, NULL);
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, NULL);
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_addPropertiesToList(JSObjectRef object, JSPropertyListRef propertyList)
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), NULL);
199
200 return JSValueToObject(context, JSValueMakeNumber(0), NULL);
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), NULL);
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 *exception = JSValueMakeNumber(2);
222 return NULL;
223 case kJSTypeNumber:
224 return JSValueMakeNumber(1);
225 default:
226 break;
227 }
228
229 // string conversion -- forward to default object class
230 return NULL;
231}
232
233static bool didFinalize = false;
234static void MyObject_finalize(JSObjectRef object)
235{
236 UNUSED_PARAM(context);
237 UNUSED_PARAM(object);
238 didFinalize = true;
239}
240
241JSObjectCallbacks MyObject_callbacks = {
242 0,
243 MyObject_initialize,
244 MyObject_finalize,
245 MyObject_hasProperty,
246 MyObject_getProperty,
247 MyObject_setProperty,
248 MyObject_deleteProperty,
249 MyObject_addPropertiesToList,
250 MyObject_callAsFunction,
251 MyObject_callAsConstructor,
252 MyObject_hasInstance,
253 MyObject_convertToType,
254};
255
256static JSClassRef MyObject_class(JSContextRef context)
257{
258 static JSClassRef jsClass;
259 if (!jsClass) {
260 jsClass = JSClassCreate(NULL, NULL, &MyObject_callbacks, NULL);
261 }
262
263 return jsClass;
264}
265
266static JSValueRef print_callAsFunction(JSContextRef context, JSObjectRef functionObject, JSObjectRef thisObject, size_t argc, JSValueRef argv[], JSValueRef* exception)
267{
268 UNUSED_PARAM(functionObject);
269 UNUSED_PARAM(thisObject);
270
271 if (argc > 0) {
272 JSStringRef string = JSValueToStringCopy(context, argv[0], NULL);
273 size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
274 char stringUTF8[sizeUTF8];
275 JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
276 printf("%s\n", stringUTF8);
277 JSStringRelease(string);
278 }
279
280 return JSValueMakeUndefined();
281}
282
283static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argc, JSValueRef argv[], JSValueRef* exception)
284{
285 UNUSED_PARAM(constructorObject);
286
287 JSObjectRef result = JSObjectMake(context, NULL, 0);
288 if (argc > 0) {
289 JSStringRef value = JSStringCreateWithUTF8CString("value");
290 JSObjectSetProperty(context, result, value, argv[0], kJSPropertyAttributeNone);
291 JSStringRelease(value);
292 }
293
294 return result;
295}
296
297static char* createStringWithContentsOfFile(const char* fileName);
298
299int main(int argc, char* argv[])
300{
301 UNUSED_PARAM(argc);
302 UNUSED_PARAM(argv);
303
304 context = JSGlobalContextCreate(NULL);
305
306 JSObjectRef globalObject = JSContextGetGlobalObject(context);
307 assert(JSValueIsObject(globalObject));
308
309 JSValueRef jsUndefined = JSValueMakeUndefined();
310 JSValueRef jsNull = JSValueMakeNull();
311 JSValueRef jsTrue = JSValueMakeBoolean(true);
312 JSValueRef jsFalse = JSValueMakeBoolean(false);
313 JSValueRef jsZero = JSValueMakeNumber(0);
314 JSValueRef jsOne = JSValueMakeNumber(1);
315 JSValueRef jsOneThird = JSValueMakeNumber(1.0 / 3.0);
316 JSObjectRef jsObjectNoProto = JSObjectMake(context, NULL, JSValueMakeNull());
317
318 // FIXME: test funny utf8 characters
319 JSStringRef jsEmptyIString = JSStringCreateWithUTF8CString("");
320 JSValueRef jsEmptyString = JSValueMakeString(jsEmptyIString);
321
322 JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
323 JSValueRef jsOneString = JSValueMakeString(jsOneIString);
324
325#if defined(__APPLE__)
326 UniChar singleUniChar = 65; // Capital A
327 CFMutableStringRef cfString =
328 CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault,
329 &singleUniChar,
330 1,
331 1,
332 kCFAllocatorNull);
333
334 JSStringRef jsCFIString = JSStringCreateWithCFString(cfString);
335 JSValueRef jsCFString = JSValueMakeString(jsCFIString);
336
337 CFStringRef cfEmptyString = CFStringCreateWithCString(kCFAllocatorDefault, "", kCFStringEncodingUTF8);
338
339 JSStringRef jsCFEmptyIString = JSStringCreateWithCFString(cfEmptyString);
340 JSValueRef jsCFEmptyString = JSValueMakeString(jsCFEmptyIString);
341
342 CFIndex cfStringLength = CFStringGetLength(cfString);
343 UniChar buffer[cfStringLength];
344 CFStringGetCharacters(cfString,
345 CFRangeMake(0, cfStringLength),
346 buffer);
347 JSStringRef jsCFIStringWithCharacters = JSStringCreateWithCharacters(buffer, cfStringLength);
348 JSValueRef jsCFStringWithCharacters = JSValueMakeString(jsCFIStringWithCharacters);
349
350 JSStringRef jsCFEmptyIStringWithCharacters = JSStringCreateWithCharacters(buffer, CFStringGetLength(cfEmptyString));
351 JSValueRef jsCFEmptyStringWithCharacters = JSValueMakeString(jsCFEmptyIStringWithCharacters);
352#endif // __APPLE__
353
354 assert(JSValueGetType(jsUndefined) == kJSTypeUndefined);
355 assert(JSValueGetType(jsNull) == kJSTypeNull);
356 assert(JSValueGetType(jsTrue) == kJSTypeBoolean);
357 assert(JSValueGetType(jsFalse) == kJSTypeBoolean);
358 assert(JSValueGetType(jsZero) == kJSTypeNumber);
359 assert(JSValueGetType(jsOne) == kJSTypeNumber);
360 assert(JSValueGetType(jsOneThird) == kJSTypeNumber);
361 assert(JSValueGetType(jsEmptyString) == kJSTypeString);
362 assert(JSValueGetType(jsOneString) == kJSTypeString);
363#if defined(__APPLE__)
364 assert(JSValueGetType(jsCFString) == kJSTypeString);
365 assert(JSValueGetType(jsCFStringWithCharacters) == kJSTypeString);
366 assert(JSValueGetType(jsCFEmptyString) == kJSTypeString);
367 assert(JSValueGetType(jsCFEmptyStringWithCharacters) == kJSTypeString);
368#endif // __APPLE__
369
370 JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
371 assert(didInitialize);
372 JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
373 JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone);
374 JSStringRelease(myObjectIString);
375
376 JSValueRef exception;
377
378 // Conversions that throw exceptions
379 exception = NULL;
380 assert(NULL == JSValueToObject(context, jsNull, &exception));
381 assert(exception);
382
383 exception = NULL;
384 assert(isnan(JSValueToNumber(context, jsObjectNoProto, &exception)));
385 assert(exception);
386
387 exception = NULL;
388 assert(!JSValueToStringCopy(context, jsObjectNoProto, &exception));
389 assert(exception);
390
391 exception = NULL;
392 assert(!JSValueToBoolean(context, myObject, &exception));
393 assert(exception);
394
395 exception = NULL;
396 assert(!JSValueIsEqual(context, jsObjectNoProto, JSValueMakeNumber(1), &exception));
397 assert(exception);
398
399 assertEqualsAsBoolean(jsUndefined, false);
400 assertEqualsAsBoolean(jsNull, false);
401 assertEqualsAsBoolean(jsTrue, true);
402 assertEqualsAsBoolean(jsFalse, false);
403 assertEqualsAsBoolean(jsZero, false);
404 assertEqualsAsBoolean(jsOne, true);
405 assertEqualsAsBoolean(jsOneThird, true);
406 assertEqualsAsBoolean(jsEmptyString, false);
407 assertEqualsAsBoolean(jsOneString, true);
408#if defined(__APPLE__)
409 assertEqualsAsBoolean(jsCFString, true);
410 assertEqualsAsBoolean(jsCFStringWithCharacters, true);
411 assertEqualsAsBoolean(jsCFEmptyString, false);
412 assertEqualsAsBoolean(jsCFEmptyStringWithCharacters, false);
413#endif // __APPLE__
414
415 assertEqualsAsNumber(jsUndefined, nan(""));
416 assertEqualsAsNumber(jsNull, 0);
417 assertEqualsAsNumber(jsTrue, 1);
418 assertEqualsAsNumber(jsFalse, 0);
419 assertEqualsAsNumber(jsZero, 0);
420 assertEqualsAsNumber(jsOne, 1);
421 assertEqualsAsNumber(jsOneThird, 1.0 / 3.0);
422 assertEqualsAsNumber(jsEmptyString, 0);
423 assertEqualsAsNumber(jsOneString, 1);
424#if defined(__APPLE__)
425 assertEqualsAsNumber(jsCFString, nan(""));
426 assertEqualsAsNumber(jsCFStringWithCharacters, nan(""));
427 assertEqualsAsNumber(jsCFEmptyString, 0);
428 assertEqualsAsNumber(jsCFEmptyStringWithCharacters, 0);
429 assert(sizeof(JSChar) == sizeof(UniChar));
430#endif // __APPLE__
431
432 assertEqualsAsCharactersPtr(jsUndefined, "undefined");
433 assertEqualsAsCharactersPtr(jsNull, "null");
434 assertEqualsAsCharactersPtr(jsTrue, "true");
435 assertEqualsAsCharactersPtr(jsFalse, "false");
436 assertEqualsAsCharactersPtr(jsZero, "0");
437 assertEqualsAsCharactersPtr(jsOne, "1");
438 assertEqualsAsCharactersPtr(jsOneThird, "0.3333333333333333");
439 assertEqualsAsCharactersPtr(jsEmptyString, "");
440 assertEqualsAsCharactersPtr(jsOneString, "1");
441#if defined(__APPLE__)
442 assertEqualsAsCharactersPtr(jsCFString, "A");
443 assertEqualsAsCharactersPtr(jsCFStringWithCharacters, "A");
444 assertEqualsAsCharactersPtr(jsCFEmptyString, "");
445 assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters, "");
446#endif // __APPLE__
447
448 assertEqualsAsUTF8String(jsUndefined, "undefined");
449 assertEqualsAsUTF8String(jsNull, "null");
450 assertEqualsAsUTF8String(jsTrue, "true");
451 assertEqualsAsUTF8String(jsFalse, "false");
452 assertEqualsAsUTF8String(jsZero, "0");
453 assertEqualsAsUTF8String(jsOne, "1");
454 assertEqualsAsUTF8String(jsOneThird, "0.3333333333333333");
455 assertEqualsAsUTF8String(jsEmptyString, "");
456 assertEqualsAsUTF8String(jsOneString, "1");
457#if defined(__APPLE__)
458 assertEqualsAsUTF8String(jsCFString, "A");
459 assertEqualsAsUTF8String(jsCFStringWithCharacters, "A");
460 assertEqualsAsUTF8String(jsCFEmptyString, "");
461 assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
462#endif // __APPLE__
463
464 assert(JSValueIsStrictEqual(context, jsTrue, jsTrue));
465 assert(!JSValueIsStrictEqual(context, jsOne, jsOneString));
466
467 assert(JSValueIsEqual(context, jsOne, jsOneString, NULL));
468 assert(!JSValueIsEqual(context, jsTrue, jsFalse, NULL));
469
470#if defined(__APPLE__)
471 CFStringRef cfJSString = JSStringCopyCFString(kCFAllocatorDefault, jsCFIString);
472 CFStringRef cfJSEmptyString = JSStringCopyCFString(kCFAllocatorDefault, jsCFEmptyIString);
473 assert(CFEqual(cfJSString, cfString));
474 assert(CFEqual(cfJSEmptyString, cfEmptyString));
475 CFRelease(cfJSString);
476 CFRelease(cfJSEmptyString);
477
478 CFRelease(cfString);
479 CFRelease(cfEmptyString);
480#endif // __APPLE__
481
482 jsGlobalValue = JSObjectMake(context, NULL, NULL);
483 JSValueProtect(jsGlobalValue);
484 JSGarbageCollect();
485 assert(JSValueIsObject(jsGlobalValue));
486 JSValueUnprotect(jsGlobalValue);
487
488 JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
489 JSStringRef badSyntax = JSStringCreateWithUTF8CString("x := 1;");
490 assert(JSCheckScriptSyntax(context, goodSyntax, NULL, 0, NULL));
491 assert(!JSCheckScriptSyntax(context, badSyntax, NULL, 0, NULL));
492
493 JSValueRef result;
494 JSValueRef v;
495 JSObjectRef o;
496
497 result = JSEvaluateScript(context, goodSyntax, NULL, NULL, 1, NULL);
498 assert(result);
499 assert(JSValueIsEqual(context, result, jsOne, NULL));
500
501 exception = NULL;
502 result = JSEvaluateScript(context, badSyntax, NULL, NULL, 1, &exception);
503 assert(!result);
504 assert(JSValueIsObject(exception));
505
506 JSStringRef array = JSStringCreateWithUTF8CString("Array");
507 v = JSObjectGetProperty(context, globalObject, array);
508 assert(v);
509 JSObjectRef arrayConstructor = JSValueToObject(context, v, NULL);
510 JSStringRelease(array);
511 result = JSObjectCallAsConstructor(context, arrayConstructor, 0, NULL, NULL);
512 assert(result);
513 assert(JSValueIsInstanceOfConstructor(context, result, arrayConstructor));
514 assert(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(), arrayConstructor));
515
516 JSStringRef functionBody;
517
518 exception = NULL;
519 functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
520 JSStringRef line = JSStringCreateWithUTF8CString("line");
521 assert(!JSObjectMakeFunctionWithBody(context, functionBody, NULL, 1, &exception));
522 assert(JSValueIsObject(exception));
523 v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line);
524 assert(v);
525 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)
526 JSStringRelease(functionBody);
527 JSStringRelease(line);
528
529 functionBody = JSStringCreateWithUTF8CString("return Array;");
530 JSObjectRef function = JSObjectMakeFunctionWithBody(context, functionBody, NULL, 1, NULL);
531 JSStringRelease(functionBody);
532
533 assert(JSObjectIsFunction(function));
534 v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
535 assert(JSValueIsEqual(context, v, arrayConstructor, NULL));
536
537 JSStringRef print = JSStringCreateWithUTF8CString("print");
538 JSObjectRef printFunction = JSObjectMakeFunction(context, print_callAsFunction);
539 JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone);
540 JSStringRelease(print);
541
542 assert(JSObjectSetPrivate(printFunction, (void*)1));
543 assert(JSObjectGetPrivate(printFunction) == (void*)1);
544
545 JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyConstructor");
546 JSObjectRef myConstructor = JSObjectMakeConstructor(context, myConstructor_callAsConstructor);
547 JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone);
548 JSStringRelease(myConstructorIString);
549
550 assert(JSObjectSetPrivate(myConstructor, (void*)1));
551 assert(JSObjectGetPrivate(myConstructor) == (void*)1);
552
553 o = JSObjectMake(context, NULL, NULL);
554 JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(1), kJSPropertyAttributeNone);
555 JSObjectSetProperty(context, o, jsCFIString, JSValueMakeNumber(1), kJSPropertyAttributeDontEnum);
556 JSPropertyEnumeratorRef enumerator = JSObjectCreatePropertyEnumerator(o);
557 int count = 0;
558 while (JSPropertyEnumeratorGetNextName(enumerator))
559 ++count;
560 JSPropertyEnumeratorRelease(enumerator);
561 assert(count == 1); // jsCFString should not be enumerated
562
563 JSClassRef nullCallbacksClass = JSClassCreate(NULL, NULL, NULL, NULL);
564 JSClassRelease(nullCallbacksClass);
565
566 functionBody = JSStringCreateWithUTF8CString("return this;");
567 function = JSObjectMakeFunctionWithBody(context, functionBody, NULL, 1, NULL);
568 JSStringRelease(functionBody);
569 v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
570 assert(JSValueIsEqual(context, v, globalObject, NULL));
571 v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
572 assert(JSValueIsEqual(context, v, o, NULL));
573
574 char* scriptUTF8 = createStringWithContentsOfFile("testapi.js");
575 JSStringRef script = JSStringCreateWithUTF8CString(scriptUTF8);
576 result = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
577 if (JSValueIsUndefined(result))
578 printf("PASS: Test script executed successfully.\n");
579 else {
580 printf("FAIL: Test script returned unexcpected value:\n");
581 JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
582 CFStringRef exceptionCF = JSStringCopyCFString(kCFAllocatorDefault, exceptionIString);
583 CFShow(exceptionCF);
584 CFRelease(exceptionCF);
585 JSStringRelease(exceptionIString);
586 }
587 JSStringRelease(script);
588 free(scriptUTF8);
589
590 // Allocate a few dummies so that at least one will be collected
591 JSObjectMake(context, MyObject_class(context), 0);
592 JSObjectMake(context, MyObject_class(context), 0);
593 JSGarbageCollect();
594 assert(didFinalize);
595
596 JSStringRelease(jsEmptyIString);
597 JSStringRelease(jsOneIString);
598#if defined(__APPLE__)
599 JSStringRelease(jsCFIString);
600 JSStringRelease(jsCFEmptyIString);
601 JSStringRelease(jsCFIStringWithCharacters);
602 JSStringRelease(jsCFEmptyIStringWithCharacters);
603#endif // __APPLE__
604 JSStringRelease(goodSyntax);
605 JSStringRelease(badSyntax);
606
607 JSGlobalContextRelease(context);
608 printf("PASS: Program exited normally.\n");
609 return 0;
610}
611
612static char* createStringWithContentsOfFile(const char* fileName)
613{
614 char* buffer;
615
616 int buffer_size = 0;
617 int buffer_capacity = 1024;
618 buffer = (char*)malloc(buffer_capacity);
619
620 FILE* f = fopen(fileName, "r");
621 if (!f) {
622 fprintf(stderr, "Could not open file: %s\n", fileName);
623 return 0;
624 }
625
626 while (!feof(f) && !ferror(f)) {
627 buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
628 if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
629 buffer_capacity *= 2;
630 buffer = (char*)realloc(buffer, buffer_capacity);
631 assert(buffer);
632 }
633
634 assert(buffer_size < buffer_capacity);
635 }
636 fclose(f);
637 buffer[buffer_size] = '\0';
638
639 return buffer;
640}
Note: See TracBrowser for help on using the repository browser.