]> git.saurik.com Git - cycript.git/blob - Library.mm
aa0b42c2698ffa0fe9ccf6a87c0b2f2e203b0162
[cycript.git] / Library.mm
1 /* Cyrker - Remove Execution Server and Disassembler
2 * Copyright (C) 2009 Jay Freeman (saurik)
3 */
4
5 /* Modified BSD License {{{ */
6 /*
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
18 * distribution.
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38 /* }}} */
39
40 #define _GNU_SOURCE
41
42 #include <substrate.h>
43 #include "Struct.hpp"
44
45 #include "sig/parse.hpp"
46 #include "sig/ffi_type.hpp"
47
48 #include <apr-1/apr_pools.h>
49 #include <apr-1/apr_strings.h>
50
51 #include <unistd.h>
52
53 #include <CoreFoundation/CoreFoundation.h>
54 #include <CoreFoundation/CFLogUtilities.h>
55
56 #include <CFNetwork/CFNetwork.h>
57 #include <Foundation/Foundation.h>
58
59 #include <JavaScriptCore/JSBase.h>
60 #include <JavaScriptCore/JSValueRef.h>
61 #include <JavaScriptCore/JSObjectRef.h>
62 #include <JavaScriptCore/JSContextRef.h>
63 #include <JavaScriptCore/JSStringRef.h>
64 #include <JavaScriptCore/JSStringRefCF.h>
65
66 #include <WebKit/WebScriptObject.h>
67
68 #include <sys/types.h>
69 #include <sys/socket.h>
70 #include <netinet/in.h>
71
72 #include <iostream>
73 #include <ext/stdio_filebuf.h>
74 #include <set>
75 #include <map>
76
77 #undef _assert
78 #undef _trace
79
80 #define _assert(test) do { \
81 if (!(test)) \
82 @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"_assert(%s):%s(%u):%s", #test, __FILE__, __LINE__, __FUNCTION__] userInfo:nil]; \
83 } while (false)
84
85 #define _trace() do { \
86 CFLog(kCFLogLevelNotice, CFSTR("_trace():%u"), __LINE__); \
87 } while (false)
88
89 /* Objective-C Handle<> {{{ */
90 template <typename Type_>
91 class _H {
92 typedef _H<Type_> This_;
93
94 private:
95 Type_ *value_;
96
97 _finline void Retain_() {
98 if (value_ != nil)
99 [value_ retain];
100 }
101
102 _finline void Clear_() {
103 if (value_ != nil)
104 [value_ release];
105 }
106
107 public:
108 _finline _H(const This_ &rhs) :
109 value_(rhs.value_ == nil ? nil : [rhs.value_ retain])
110 {
111 }
112
113 _finline _H(Type_ *value = NULL, bool mended = false) :
114 value_(value)
115 {
116 if (!mended)
117 Retain_();
118 }
119
120 _finline ~_H() {
121 Clear_();
122 }
123
124 _finline operator Type_ *() const {
125 return value_;
126 }
127
128 _finline This_ &operator =(Type_ *value) {
129 if (value_ != value) {
130 Type_ *old(value_);
131 value_ = value;
132 Retain_();
133 if (old != nil)
134 [old release];
135 } return *this;
136 }
137 };
138 /* }}} */
139 /* APR Pool Helpers {{{ */
140 void *operator new(size_t size, apr_pool_t *pool) {
141 return apr_palloc(pool, size);
142 }
143
144 void *operator new [](size_t size, apr_pool_t *pool) {
145 return apr_palloc(pool, size);
146 }
147
148 class CYPool {
149 private:
150 apr_pool_t *pool_;
151
152 public:
153 CYPool() {
154 apr_pool_create(&pool_, NULL);
155 }
156
157 ~CYPool() {
158 apr_pool_destroy(pool_);
159 }
160
161 operator apr_pool_t *() const {
162 return pool_;
163 }
164 };
165 /* }}} */
166
167 #define _pooled _H<NSAutoreleasePool> _pool([[NSAutoreleasePool alloc] init], true);
168
169 static JSContextRef Context_;
170
171 static JSClassRef Functor_;
172 static JSClassRef Instance_;
173 static JSClassRef Pointer_;
174 static JSClassRef Selector_;
175
176 static JSObjectRef Array_;
177
178 static JSStringRef name_;
179 static JSStringRef message_;
180 static JSStringRef length_;
181
182 static Class NSCFBoolean_;
183
184 static NSMutableDictionary *Bridge_;
185
186 struct Client {
187 CFHTTPMessageRef message_;
188 CFSocketRef socket_;
189 };
190
191 JSObjectRef CYMakeObject(JSContextRef context, id object) {
192 return JSObjectMake(context, Instance_, [object retain]);
193 }
194
195 @interface NSMethodSignature (Cycript)
196 - (NSString *) _typeString;
197 @end
198
199 @interface NSObject (Cycript)
200 - (NSString *) cy$toJSON;
201 - (JSValueRef) cy$JSValueInContext:(JSContextRef)context;
202 @end
203
204 @interface NSString (Cycript)
205 - (void *) cy$symbol;
206 @end
207
208 @interface NSNumber (Cycript)
209 - (void *) cy$symbol;
210 @end
211
212 @implementation NSObject (Cycript)
213
214 - (NSString *) cy$toJSON {
215 return [self description];
216 }
217
218 - (JSValueRef) cy$JSValueInContext:(JSContextRef)context {
219 return CYMakeObject(context, self);
220 }
221
222 @end
223
224 @implementation WebUndefined (Cycript)
225
226 - (NSString *) cy$toJSON {
227 return @"undefined";
228 }
229
230 - (JSValueRef) cy$JSValueInContext:(JSContextRef)context {
231 return JSValueMakeUndefined(context);
232 }
233
234 @end
235
236 @implementation NSArray (Cycript)
237
238 - (NSString *) cy$toJSON {
239 NSMutableString *json([[[NSMutableString alloc] init] autorelease]);
240 [json appendString:@"["];
241
242 bool comma(false);
243 for (id object in self) {
244 if (comma)
245 [json appendString:@","];
246 else
247 comma = true;
248 [json appendString:[object cy$toJSON]];
249 }
250
251 [json appendString:@"]"];
252 return json;
253 }
254
255 @end
256
257 @implementation NSDictionary (Cycript)
258
259 - (NSString *) cy$toJSON {
260 NSMutableString *json([[[NSMutableString alloc] init] autorelease]);
261 [json appendString:@"("];
262 [json appendString:@"{"];
263
264 bool comma(false);
265 for (id key in self) {
266 if (comma)
267 [json appendString:@","];
268 else
269 comma = true;
270 [json appendString:[key cy$toJSON]];
271 [json appendString:@":"];
272 NSObject *object([self objectForKey:key]);
273 [json appendString:[object cy$toJSON]];
274 }
275
276 [json appendString:@"})"];
277 return json;
278 }
279
280 @end
281
282 @implementation NSNumber (Cycript)
283
284 - (NSString *) cy$toJSON {
285 return [self class] != NSCFBoolean_ ? [self stringValue] : [self boolValue] ? @"true" : @"false";
286 }
287
288 - (JSValueRef) cy$JSValueInContext:(JSContextRef)context {
289 return [self class] != NSCFBoolean_ ? JSValueMakeNumber(context, [self doubleValue]) : JSValueMakeBoolean(context, [self boolValue]);
290 }
291
292 - (void *) cy$symbol {
293 return [self pointerValue];
294 }
295
296 @end
297
298 @implementation NSString (Cycript)
299
300 - (NSString *) cy$toJSON {
301 CFMutableStringRef json(CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (CFStringRef) self));
302
303 CFStringFindAndReplace(json, CFSTR("\\"), CFSTR("\\\\"), CFRangeMake(0, CFStringGetLength(json)), 0);
304 CFStringFindAndReplace(json, CFSTR("\""), CFSTR("\\\""), CFRangeMake(0, CFStringGetLength(json)), 0);
305 CFStringFindAndReplace(json, CFSTR("\t"), CFSTR("\\t"), CFRangeMake(0, CFStringGetLength(json)), 0);
306 CFStringFindAndReplace(json, CFSTR("\r"), CFSTR("\\r"), CFRangeMake(0, CFStringGetLength(json)), 0);
307 CFStringFindAndReplace(json, CFSTR("\n"), CFSTR("\\n"), CFRangeMake(0, CFStringGetLength(json)), 0);
308
309 CFStringInsert(json, 0, CFSTR("\""));
310 CFStringAppend(json, CFSTR("\""));
311
312 return [reinterpret_cast<const NSString *>(json) autorelease];
313 }
314
315 - (void *) cy$symbol {
316 return dlsym(RTLD_DEFAULT, [self UTF8String]);
317 }
318
319 @end
320
321 @interface CYJSObject : NSDictionary {
322 JSObjectRef object_;
323 JSContextRef context_;
324 }
325
326 - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context;
327
328 - (NSUInteger) count;
329 - (id) objectForKey:(id)key;
330 - (NSEnumerator *) keyEnumerator;
331 - (void) setObject:(id)object forKey:(id)key;
332 - (void) removeObjectForKey:(id)key;
333
334 @end
335
336 @interface CYJSArray : NSArray {
337 JSObjectRef object_;
338 JSContextRef context_;
339 }
340
341 - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context;
342
343 - (NSUInteger) count;
344 - (id) objectAtIndex:(NSUInteger)index;
345
346 @end
347
348 JSContextRef JSGetContext() {
349 return Context_;
350 }
351
352 #define CYCatch \
353 @catch (id error) { \
354 CYThrow(context, error, exception); \
355 return NULL; \
356 }
357
358 void CYThrow(JSContextRef context, JSValueRef value);
359
360 id CYCastNSObject(JSContextRef context, JSObjectRef object) {
361 if (JSValueIsObjectOfClass(context, object, Instance_))
362 return reinterpret_cast<id>(JSObjectGetPrivate(object));
363 JSValueRef exception(NULL);
364 bool array(JSValueIsInstanceOfConstructor(context, object, Array_, &exception));
365 CYThrow(context, exception);
366 if (array)
367 return [[[CYJSArray alloc] initWithJSObject:object inContext:context] autorelease];
368 return [[[CYJSObject alloc] initWithJSObject:object inContext:context] autorelease];
369 }
370
371 JSStringRef CYCopyJSString(id value) {
372 return JSStringCreateWithCFString(reinterpret_cast<CFStringRef>([value description]));
373 }
374
375 JSStringRef CYCopyJSString(const char *value) {
376 return JSStringCreateWithUTF8CString(value);
377 }
378
379 JSStringRef CYCopyJSString(JSStringRef value) {
380 return JSStringRetain(value);
381 }
382
383 JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value) {
384 JSValueRef exception(NULL);
385 JSStringRef string(JSValueToStringCopy(context, value, &exception));
386 CYThrow(context, exception);
387 return string;
388 }
389
390 // XXX: this is not a safe handle
391 class CYString {
392 private:
393 JSStringRef string_;
394
395 public:
396 template <typename Arg0_>
397 CYString(Arg0_ arg0) {
398 string_ = CYCopyJSString(arg0);
399 }
400
401 template <typename Arg0_, typename Arg1_>
402 CYString(Arg0_ arg0, Arg1_ arg1) {
403 string_ = CYCopyJSString(arg0, arg1);
404 }
405
406 ~CYString() {
407 JSStringRelease(string_);
408 }
409
410 operator JSStringRef() const {
411 return string_;
412 }
413 };
414
415 CFStringRef CYCopyCFString(JSStringRef value) {
416 return JSStringCopyCFString(kCFAllocatorDefault, value);
417 }
418
419 CFStringRef CYCopyCFString(JSContextRef context, JSValueRef value) {
420 return CYCopyCFString(CYString(context, value));
421 }
422
423 double CYCastDouble(JSContextRef context, JSValueRef value) {
424 JSValueRef exception(NULL);
425 double number(JSValueToNumber(context, value, &exception));
426 CYThrow(context, exception);
427 return number;
428 }
429
430 CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef value) {
431 double number(CYCastDouble(context, value));
432 return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &number);
433 }
434
435 NSString *CYCastNSString(JSStringRef value) {
436 return [reinterpret_cast<const NSString *>(CYCopyCFString(value)) autorelease];
437 }
438
439 CFTypeRef CYCopyCFType(JSContextRef context, JSValueRef value) {
440 switch (JSType type = JSValueGetType(context, value)) {
441 case kJSTypeUndefined:
442 return CFRetain([WebUndefined undefined]);
443 case kJSTypeNull:
444 return nil;
445 case kJSTypeBoolean:
446 return CFRetain(JSValueToBoolean(context, value) ? kCFBooleanTrue : kCFBooleanFalse);
447 case kJSTypeNumber:
448 return CYCopyCFNumber(context, value);
449 case kJSTypeString:
450 return CYCopyCFString(context, value);
451 case kJSTypeObject:
452 return CFRetain((CFTypeRef) CYCastNSObject(context, (JSObjectRef) value));
453 default:
454 @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"JSValueGetType() == 0x%x", type] userInfo:nil];
455 }
456 }
457
458 NSArray *CYCastNSArray(JSPropertyNameArrayRef names) {
459 size_t size(JSPropertyNameArrayGetCount(names));
460 NSMutableArray *array([NSMutableArray arrayWithCapacity:size]);
461 for (size_t index(0); index != size; ++index)
462 [array addObject:CYCastNSString(JSPropertyNameArrayGetNameAtIndex(names, index))];
463 return array;
464 }
465
466 id CYCastNSObject(JSContextRef context, JSValueRef value) {
467 const NSObject *object(reinterpret_cast<const NSObject *>(CYCopyCFType(context, value)));
468 return object == nil ? nil : [object autorelease];
469 }
470
471 void CYThrow(JSContextRef context, JSValueRef value) {
472 if (value == NULL)
473 return;
474 @throw CYCastNSObject(context, value);
475 }
476
477 JSValueRef CYCastJSValue(JSContextRef context, id value) {
478 return value == nil ? JSValueMakeNull(context) : [value cy$JSValueInContext:context];
479 }
480
481 void CYThrow(JSContextRef context, id error, JSValueRef *exception) {
482 *exception = CYCastJSValue(context, error);
483 }
484
485 @implementation CYJSObject
486
487 - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context {
488 if ((self = [super init]) != nil) {
489 object_ = object;
490 context_ = context;
491 } return self;
492 }
493
494 - (NSUInteger) count {
495 JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_));
496 size_t size(JSPropertyNameArrayGetCount(names));
497 JSPropertyNameArrayRelease(names);
498 return size;
499 }
500
501 - (id) objectForKey:(id)key {
502 JSValueRef exception(NULL);
503 JSValueRef value(JSObjectGetProperty(context_, object_, CYString(key), &exception));
504 CYThrow(context_, exception);
505 return CYCastNSObject(context_, value);
506 }
507
508 - (NSEnumerator *) keyEnumerator {
509 JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_));
510 NSEnumerator *enumerator([CYCastNSArray(names) objectEnumerator]);
511 JSPropertyNameArrayRelease(names);
512 return enumerator;
513 }
514
515 - (void) setObject:(id)object forKey:(id)key {
516 JSValueRef exception(NULL);
517 JSObjectSetProperty(context_, object_, CYString(key), CYCastJSValue(context_, object), kJSPropertyAttributeNone, &exception);
518 CYThrow(context_, exception);
519 }
520
521 - (void) removeObjectForKey:(id)key {
522 JSValueRef exception(NULL);
523 // XXX: this returns a bool... throw exception, or ignore?
524 JSObjectDeleteProperty(context_, object_, CYString(key), &exception);
525 CYThrow(context_, exception);
526 }
527
528 @end
529
530 @implementation CYJSArray
531
532 - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context {
533 if ((self = [super init]) != nil) {
534 object_ = object;
535 context_ = context;
536 } return self;
537 }
538
539 - (NSUInteger) count {
540 JSValueRef exception(NULL);
541 JSValueRef value(JSObjectGetProperty(context_, object_, length_, &exception));
542 CYThrow(context_, exception);
543 return CYCastDouble(context_, value);
544 }
545
546 - (id) objectAtIndex:(NSUInteger)index {
547 JSValueRef exception(NULL);
548 JSValueRef value(JSObjectGetPropertyAtIndex(context_, object_, index, &exception));
549 CYThrow(context_, exception);
550 id object(CYCastNSObject(context_, value));
551 return object == nil ? [NSNull null] : object;
552 }
553
554 @end
555
556 CFStringRef JSValueToJSONCopy(JSContextRef context, JSValueRef value) {
557 id object(CYCastNSObject(context, value));
558 return reinterpret_cast<CFStringRef>([(object == nil ? @"null" : [object cy$toJSON]) retain]);
559 }
560
561 static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) {
562 switch (type) {
563 case kCFSocketDataCallBack:
564 CFDataRef data(reinterpret_cast<CFDataRef>(value));
565 Client *client(reinterpret_cast<Client *>(info));
566
567 if (client->message_ == NULL)
568 client->message_ = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
569
570 if (!CFHTTPMessageAppendBytes(client->message_, CFDataGetBytePtr(data), CFDataGetLength(data)))
571 CFLog(kCFLogLevelError, CFSTR("CFHTTPMessageAppendBytes()"));
572 else if (CFHTTPMessageIsHeaderComplete(client->message_)) {
573 CFURLRef url(CFHTTPMessageCopyRequestURL(client->message_));
574 Boolean absolute;
575 CFStringRef path(CFURLCopyStrictPath(url, &absolute));
576 CFRelease(client->message_);
577
578 CFStringRef code(CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault, path, CFSTR("")));
579 CFRelease(path);
580
581 JSStringRef script(JSStringCreateWithCFString(code));
582 CFRelease(code);
583
584 JSValueRef result(JSEvaluateScript(JSGetContext(), script, NULL, NULL, 0, NULL));
585 JSStringRelease(script);
586
587 CFHTTPMessageRef response(CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1));
588 CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8"));
589
590 CFStringRef json(JSValueToJSONCopy(JSGetContext(), result));
591 CFDataRef body(CFStringCreateExternalRepresentation(kCFAllocatorDefault, json, kCFStringEncodingUTF8, NULL));
592 CFRelease(json);
593
594 CFStringRef length(CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), CFDataGetLength(body)));
595 CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Length"), length);
596 CFRelease(length);
597
598 CFHTTPMessageSetBody(response, body);
599 CFRelease(body);
600
601 CFDataRef serialized(CFHTTPMessageCopySerializedMessage(response));
602 CFRelease(response);
603
604 CFSocketSendData(socket, NULL, serialized, 0);
605 CFRelease(serialized);
606
607 CFRelease(url);
608 }
609 break;
610 }
611 }
612
613 static void OnAccept(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) {
614 switch (type) {
615 case kCFSocketAcceptCallBack:
616 Client *client(new Client());
617
618 client->message_ = NULL;
619
620 CFSocketContext context;
621 context.version = 0;
622 context.info = client;
623 context.retain = NULL;
624 context.release = NULL;
625 context.copyDescription = NULL;
626
627 client->socket_ = CFSocketCreateWithNative(kCFAllocatorDefault, *reinterpret_cast<const CFSocketNativeHandle *>(value), kCFSocketDataCallBack, &OnData, &context);
628
629 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, client->socket_, 0), kCFRunLoopDefaultMode);
630 break;
631 }
632 }
633
634 static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { _pooled
635 @try {
636 NSString *name(CYCastNSString(property));
637 NSLog(@"%@", name);
638 return NULL;
639 } CYCatch
640 }
641
642 typedef id jocData;
643
644 static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { _pooled
645 @try {
646 id data(reinterpret_cast<jocData>(JSObjectGetPrivate(object)));
647 return CYMakeObject(context, [[data alloc] autorelease]);
648 } CYCatch
649 }
650
651 struct ptrData {
652 apr_pool_t *pool_;
653 void *value_;
654 sig::Type type_;
655
656 void *operator new(size_t size) {
657 apr_pool_t *pool;
658 apr_pool_create(&pool, NULL);
659 void *data(apr_palloc(pool, size));
660 reinterpret_cast<ptrData *>(data)->pool_ = pool;
661 return data;;
662 }
663
664 ptrData(void *value) :
665 value_(value)
666 {
667 }
668 };
669
670 struct ffiData : ptrData {
671 sig::Signature signature_;
672 ffi_cif cif_;
673
674 ffiData(void (*value)(), const char *type) :
675 ptrData(reinterpret_cast<void *>(value))
676 {
677 sig::Parse(pool_, &signature_, type);
678 sig::sig_ffi_cif(pool_, &sig::ObjectiveC, &signature_, &cif_);
679 }
680 };
681
682 struct selData : ptrData {
683 selData(SEL value) :
684 ptrData(value)
685 {
686 }
687 };
688
689 static void Pointer_finalize(JSObjectRef object) {
690 ptrData *data(reinterpret_cast<ptrData *>(JSObjectGetPrivate(object)));
691 apr_pool_destroy(data->pool_);
692 }
693
694 static void Instance_finalize(JSObjectRef object) {
695 id data(reinterpret_cast<jocData>(JSObjectGetPrivate(object)));
696 [data release];
697 }
698
699 JSObjectRef CYMakeFunction(JSContextRef context, void (*function)(), const char *type) {
700 ffiData *data(new ffiData(function, type));
701 return JSObjectMake(context, Functor_, data);
702 }
703
704
705 JSObjectRef CYMakeFunction(JSContextRef context, void *function, const char *type) {
706 return CYMakeFunction(context, reinterpret_cast<void (*)()>(function), type);
707 }
708
709 void CYSetProperty(JSContextRef context, JSObjectRef object, const char *name, JSValueRef value) {
710 JSValueRef exception(NULL);
711 JSObjectSetProperty(context, object, CYString(name), value, kJSPropertyAttributeNone, &exception);
712 CYThrow(context, exception);
713 }
714
715 char *CYPoolCString(apr_pool_t *pool, JSStringRef value) {
716 size_t size(JSStringGetMaximumUTF8CStringSize(value));
717 char *string(new(pool) char[size]);
718 JSStringGetUTF8CString(value, string, size);
719 JSStringRelease(value);
720 return string;
721 }
722
723 char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
724 return CYPoolCString(pool, CYString(context, value));
725 }
726
727 // XXX: this macro is unhygenic
728 #define CYCastCString(context, value) ({ \
729 JSValueRef exception(NULL); \
730 JSStringRef string(JSValueToStringCopy(context, value, &exception)); \
731 CYThrow(context, exception); \
732 size_t size(JSStringGetMaximumUTF8CStringSize(string)); \
733 char *utf8(reinterpret_cast<char *>(alloca(size))); \
734 JSStringGetUTF8CString(string, utf8, size); \
735 JSStringRelease(string); \
736 utf8; \
737 })
738
739 SEL CYCastSEL(JSContextRef context, JSValueRef value) {
740 if (JSValueIsNull(context, value))
741 return NULL;
742 else if (JSValueIsObjectOfClass(context, value, Selector_)) {
743 selData *data(reinterpret_cast<selData *>(JSObjectGetPrivate((JSObjectRef) value)));
744 return reinterpret_cast<SEL>(data->value_);
745 } else
746 return sel_registerName(CYCastCString(context, value));
747 }
748
749 void *CYCastPointer(JSContextRef context, JSValueRef value) {
750 switch (JSValueGetType(context, value)) {
751 case kJSTypeNull:
752 return NULL;
753 case kJSTypeString:
754 return dlsym(RTLD_DEFAULT, CYCastCString(context, value));
755 case kJSTypeObject:
756 if (JSValueIsObjectOfClass(context, value, Pointer_)) {
757 ptrData *data(reinterpret_cast<ptrData *>(JSObjectGetPrivate((JSObjectRef) value)));
758 return data->value_;
759 }
760 default:
761 return reinterpret_cast<void *>(static_cast<uintptr_t>(CYCastDouble(context, value)));
762 }
763 }
764
765 void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, void *data, JSValueRef value) {
766 switch (type->primitive) {
767 case sig::boolean_P:
768 *reinterpret_cast<bool *>(data) = JSValueToBoolean(context, value);
769 break;
770
771 #define CYPoolFFI_(primitive, native) \
772 case sig::primitive ## _P: \
773 *reinterpret_cast<native *>(data) = CYCastDouble(context, value); \
774 break;
775
776 CYPoolFFI_(uchar, unsigned char)
777 CYPoolFFI_(char, char)
778 CYPoolFFI_(ushort, unsigned short)
779 CYPoolFFI_(short, short)
780 CYPoolFFI_(ulong, unsigned long)
781 CYPoolFFI_(long, long)
782 CYPoolFFI_(uint, unsigned int)
783 CYPoolFFI_(int, int)
784 CYPoolFFI_(ulonglong, unsigned long long)
785 CYPoolFFI_(longlong, long long)
786 CYPoolFFI_(float, float)
787 CYPoolFFI_(double, double)
788
789 case sig::object_P:
790 case sig::typename_P:
791 *reinterpret_cast<id *>(data) = CYCastNSObject(context, value);
792 break;
793
794 case sig::selector_P:
795 *reinterpret_cast<SEL *>(data) = CYCastSEL(context, value);
796 break;
797
798 case sig::pointer_P:
799 *reinterpret_cast<void **>(data) = CYCastPointer(context, value);
800 break;
801
802 case sig::string_P:
803 *reinterpret_cast<char **>(data) = CYPoolCString(pool, context, value);
804 break;
805
806 case sig::struct_P:
807 goto fail;
808
809 case sig::void_P:
810 break;
811
812 default: fail:
813 NSLog(@"CYPoolFFI(%c)\n", type->primitive);
814 _assert(false);
815 }
816 }
817
818 JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) {
819 JSValueRef value;
820
821 switch (type->primitive) {
822 case sig::boolean_P:
823 value = JSValueMakeBoolean(context, *reinterpret_cast<bool *>(data));
824 break;
825
826 #define CYFromFFI_(primitive, native) \
827 case sig::primitive ## _P: \
828 value = JSValueMakeNumber(context, *reinterpret_cast<native *>(data)); \
829 break;
830
831 CYFromFFI_(uchar, unsigned char)
832 CYFromFFI_(char, char)
833 CYFromFFI_(ushort, unsigned short)
834 CYFromFFI_(short, short)
835 CYFromFFI_(ulong, unsigned long)
836 CYFromFFI_(long, long)
837 CYFromFFI_(uint, unsigned int)
838 CYFromFFI_(int, int)
839 CYFromFFI_(ulonglong, unsigned long long)
840 CYFromFFI_(longlong, long long)
841 CYFromFFI_(float, float)
842 CYFromFFI_(double, double)
843
844 case sig::object_P:
845 case sig::typename_P: {
846 value = CYCastJSValue(context, *reinterpret_cast<id *>(data));
847 } break;
848
849 case sig::selector_P: {
850 if (SEL sel = *reinterpret_cast<SEL *>(data)) {
851 selData *data(new selData(sel));
852 value = JSObjectMake(context, Selector_, data);
853 } else goto null;
854 } break;
855
856 case sig::pointer_P: {
857 if (void *pointer = *reinterpret_cast<void **>(data)) {
858 ptrData *data(new ptrData(pointer));
859 value = JSObjectMake(context, Pointer_, data);
860 } else goto null;
861 } break;
862
863 case sig::string_P: {
864 if (char *utf8 = *reinterpret_cast<char **>(data))
865 value = JSValueMakeString(context, CYString(utf8));
866 else goto null;
867 } break;
868
869 case sig::struct_P:
870 goto fail;
871
872 case sig::void_P:
873 value = JSValueMakeUndefined(context);
874 break;
875
876 null:
877 value = JSValueMakeNull(context);
878 break;
879
880 default: fail:
881 NSLog(@"CYFromFFI(%c)\n", type->primitive);
882 _assert(false);
883 }
884
885 return value;
886 }
887
888 static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSValueRef *arguments, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { _pooled
889 @try {
890 if (count != signature->count - 1)
891 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to ffi function" userInfo:nil];
892
893 CYPool pool;
894 void *values[count];
895
896 for (unsigned index(0); index != count; ++index) {
897 sig::Element *element(&signature->elements[index + 1]);
898 // XXX: alignment?
899 values[index] = new(pool) uint8_t[cif->arg_types[index]->size];
900 CYPoolFFI(pool, context, element->type, values[index], arguments[index]);
901 }
902
903 uint8_t value[cif->rtype->size];
904 ffi_call(cif, function, value, values);
905
906 return CYFromFFI(context, signature->elements[0].type, value);
907 } CYCatch
908 }
909
910 static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { _pooled
911 @try {
912 NSString *name(CYCastNSString(property));
913 if (Class _class = NSClassFromString(name))
914 return CYMakeObject(context, _class);
915 if (NSMutableArray *entry = [Bridge_ objectForKey:name])
916 switch ([[entry objectAtIndex:0] intValue]) {
917 case 0:
918 return JSEvaluateScript(JSGetContext(), CYString([entry objectAtIndex:1]), NULL, NULL, 0, NULL);
919 case 1:
920 return CYMakeFunction(context, [name cy$symbol], [[entry objectAtIndex:1] UTF8String]);
921 case 2:
922 CYPool pool;
923 sig::Signature signature;
924 sig::Parse(pool, &signature, [[entry objectAtIndex:1] UTF8String]);
925 return CYFromFFI(context, signature.elements[0].type, [name cy$symbol]);
926 }
927 return NULL;
928 } CYCatch
929 }
930
931 bool stret(ffi_type *ffi_type) {
932 return ffi_type->type == FFI_TYPE_STRUCT && (
933 ffi_type->size > OBJC_MAX_STRUCT_BY_VALUE ||
934 struct_forward_array[ffi_type->size] != 0
935 );
936 }
937
938 static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { _pooled
939 const char *type;
940
941 @try {
942 if (count < 2)
943 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"too few arguments to objc_msgSend" userInfo:nil];
944
945 id self(CYCastNSObject(context, arguments[0]));
946 if (self == nil)
947 return JSValueMakeNull(context);
948
949 SEL _cmd(CYCastSEL(context, arguments[1]));
950 NSMethodSignature *method([self methodSignatureForSelector:_cmd]);
951 if (method == nil)
952 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self] userInfo:nil];
953
954 type = [[method _typeString] UTF8String];
955 } CYCatch
956
957 CYPool pool;
958
959 sig::Signature signature;
960 sig::Parse(pool, &signature, type);
961
962 ffi_cif cif;
963 sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
964
965 void (*function)() = stret(cif.rtype) ? reinterpret_cast<void (*)()>(&objc_msgSend_stret) : reinterpret_cast<void (*)()>(&objc_msgSend);
966 return CYCallFunction(context, count, arguments, exception, &signature, &cif, function);
967 }
968
969 static JSValueRef ffi_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
970 ffiData *data(reinterpret_cast<ffiData *>(JSObjectGetPrivate(object)));
971 return CYCallFunction(context, count, arguments, exception, &data->signature_, &data->cif_, reinterpret_cast<void (*)()>(data->value_));
972 }
973
974 JSObjectRef ffi(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
975 @try {
976 if (count != 2)
977 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to ffi constructor" userInfo:nil];
978 void *function(CYCastPointer(context, arguments[0]));
979 const char *type(CYCastCString(context, arguments[1]));
980 return CYMakeFunction(context, function, type);
981 } CYCatch
982 }
983
984 JSValueRef Pointer_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
985 ptrData *data(reinterpret_cast<ptrData *>(JSObjectGetPrivate(object)));
986 return JSValueMakeNumber(context, reinterpret_cast<uintptr_t>(data->value_));
987 }
988
989 static JSStaticValue Pointer_staticValues[2] = {
990 {"value", &Pointer_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete},
991 {NULL, NULL, NULL, 0}
992 };
993
994 enum CYTokenType {
995 CYTokenBreak, CYTokenCase, CYTokenCatch, CYTokenContinue, CYTokenDefault,
996 CYTokenDelete, CYTokenDo, CYTokenElse, CYTokenFinally, CYTokenFor,
997 CYTokenFunction, CYTokenIf, CYTokenIn, CYTokenInstanceOf, CYTokenNew,
998 CYTokenReturn, CYTokenSwitch, CYTokenThis, CYTokenThrow, CYTokenTry,
999 CYTokenTypeOf, CYTokenVar, CYTokenVoid, CYTokenWhile, CYTokenWith,
1000
1001 CYTokenOpenBrace, CYTokenOpenParen, CYTokenOpenBracket,
1002 CYTokenCloseBrace, CYTokenCloseParen, CYTokenCloseBracket,
1003
1004 CYTokenPeriod, CYTokenSemiColon, CYTokenComma, CYTokenLeft, CYTokenRight,
1005 CYTokenLeftEqual, CYTokenRightEqual, CYTokenEqualEqual, CYTokenExclamationEqual,
1006 CYTokenEqualEqualEqual, CYTokenExclamationEqualEqual, CYTokenPlus, CYTokenHyphen,
1007 CYTokenStar, CYTokenPercent, CYTokenPlusPlus, CYTokenHyphenHyphen, CYTokenLeftLeft,
1008 CYTokenRightRight, CYTokenRightRightRight, CYTokenAmpersand, CYTokenPipe,
1009 CYTokenCarrot, CYTokenExclamation, CYTokenTilde, CYTokenAmpersandAmpersand,
1010 CYTokenPipePipe, CYTokenQuestion, CYTokenColon, CYTokenEqual, CYTokenPlusEqual,
1011 CYTokenHyphenEqual, CYTokenStarEqual, CYTokenPercentEqual, CYTokenLeftLeftEqual,
1012 CYTokenRightRightEqual, CYTokenRightRightRightEqual, CYTokenAmpersandEqual,
1013 CYTokenPipeEqual, CYTokenCarrotEqual, CYTokenSlash, CYTokenSlashEqual,
1014
1015 CYTokenIdentifier, CYTokenLiteral
1016 };
1017
1018 typedef std::map<const char *, CYTokenType> TokenMap;
1019 TokenMap Tokens_;
1020
1021 struct CYToken {
1022 enum CYTokenType type_;
1023 char *value_;
1024 CYToken *next_;
1025 CYToken **prev_;
1026 };
1027
1028 struct CYExpression {
1029 };
1030
1031 struct CYRange {
1032 uint64_t lo_;
1033 uint64_t hi_;
1034
1035 CYRange(uint64_t lo, uint64_t hi) :
1036 lo_(lo), hi_(hi)
1037 {
1038 }
1039
1040 bool operator [](uint8_t value) const {
1041 return !(value >> 7) && (value >> 6 ? hi_ : lo_) >> (value & 0x3f) & 0x1;
1042 }
1043
1044 void operator()(uint8_t value) {
1045 if (value >> 7)
1046 return;
1047 (value >> 6 ? hi_ : lo_) |= uint64_t(0x1) << (value & 0x3f);
1048 }
1049 };
1050
1051 CYRange WordStartRange_(0x1000000000LLU,0x7fffffe87fffffeLLU); // A-Za-z_$
1052 CYRange WordEndRange_(0x3ff001000000000LLU,0x7fffffe87fffffeLLU); // A-Za-z_$0-9
1053 CYRange NumberRange_(0x3ff400000000000LLU,0x100007e0100007eLLU); // 0-9.eExXA-Fa-f
1054 CYRange PunctuationRange_(0xfc00fc6200000000LLU,0x5000000040000000LLU); // -.,;<>=!+*/%&|^~?:
1055
1056 struct CStringMapLess :
1057 std::binary_function<const char *, const char *, bool>
1058 {
1059 _finline bool operator ()(const char *lhs, const char *rhs) const {
1060 return strcmp(lhs, rhs) < 0;
1061 }
1062 };
1063
1064 std::set<const char *, CStringMapLess> OperatorWords_;
1065
1066 struct CYParser {
1067 FILE *fin_;
1068 FILE *fout_;
1069
1070 size_t capacity_;
1071 char *data_;
1072
1073 size_t offset_;
1074 size_t size_;
1075
1076 CYParser(FILE *fin, FILE *fout) :
1077 fin_(fin),
1078 fout_(fout),
1079 capacity_(1024),
1080 data_(reinterpret_cast<char *>(malloc(capacity_))),
1081 offset_(0),
1082 size_(0)
1083 {
1084 }
1085
1086 ~CYParser() {
1087 // XXX: this will not deconstruct in constructor failures
1088 free(data_);
1089 }
1090
1091 bool ReadLine(const char *prompt) {
1092 offset_ = 0;
1093 data_[capacity_ - 1] = ~'\0';
1094
1095 start:
1096 if (fout_ != NULL) {
1097 fputs(prompt, fout_);
1098 fputs(" ", fout_);
1099 fflush(fout_);
1100 }
1101
1102 if (fgets(data_, capacity_, fin_) == NULL)
1103 return false;
1104
1105 check:
1106 if (data_[capacity_ - 1] != '\0') {
1107 size_ = strlen(data_);
1108 if (size_ == 0)
1109 goto start;
1110 if (data_[size_ - 1] == '\n') {
1111 --size_;
1112 goto newline;
1113 }
1114 } else if (data_[capacity_ - 2] == '\n') {
1115 size_ = capacity_ - 2;
1116 newline:
1117 data_[size_] = '\0';
1118 } else {
1119 size_t capacity(capacity_ * 2);
1120 char *data(reinterpret_cast<char *>(realloc(data_, capacity)));
1121 _assert(data != NULL);
1122 data_ = data;
1123 size_ = capacity_ - 1;
1124 capacity_ = capacity;
1125 fgets(data_ + size_, capacity_ - size_, fin_);
1126 goto check;
1127 }
1128
1129 return true;
1130 }
1131
1132 _finline void ScanRange(const CYRange &range) {
1133 while (range[data_[++offset_]]);
1134 }
1135
1136 CYToken *ParseToken(apr_pool_t *pool, const char *prompt) {
1137 char next;
1138
1139 for (;;) {
1140 if (offset_ == size_ && (prompt == NULL || !ReadLine(prompt)))
1141 return false;
1142 next = data_[offset_];
1143 if (next != ' ' && next != '\t')
1144 break;
1145 ++offset_;
1146 }
1147
1148 CYTokenType type;
1149 size_t index(offset_);
1150
1151 if (WordStartRange_[next]) {
1152 ScanRange(WordEndRange_);
1153 type = CYTokenWord;
1154 } else if (next == '.') {
1155 char after(data_[offset_ + 1]);
1156 if (after >= '0' && next <= '9')
1157 goto number;
1158 goto punctuation;
1159 } else if (next >= '0' && next <= '9') {
1160 number:
1161 ScanRange(NumberRange_);
1162 type = CYTokenLiteral;
1163 } else if (PunctuationRange_[next]) {
1164 punctuation:
1165 ScanRange(PunctuationRange_);
1166 type = CYTokenPunctuation;
1167 } else if (next == '"' || next == '\'') {
1168 for (;;) {
1169 char after(data_[++offset_]);
1170 if (after == '\\') {
1171 after = data_[offset_];
1172 _assert(after != '\0');
1173 if (after == 'u') {
1174 offset_ += 4;
1175 _assert(offset_ < size_);
1176 }
1177 } else if (after == next)
1178 break;
1179 }
1180
1181 ++offset_;
1182 type = CYTokenLiteral;
1183 } else if (next == '(' || next == '{' || next == '[') {
1184 ++offset_;
1185 type = CYTokenOpen;
1186 } else if (next == ')' || next == '}' || next == ']') {
1187 ++offset_;
1188 type = CYTokenClose;
1189 } else if (next == ';') {
1190 ++offset_;
1191 type = CYTokenSemiColon;
1192 } else {
1193 printf(":( %u\n", next);
1194 _assert(false);
1195 }
1196
1197 char *value(apr_pstrndup(pool, data_ + index, offset_ - index));
1198
1199 if (type == CYTokenWord && OperatorWords_.find(value) != OperatorWords_.end())
1200 type = CYTokenPunctuation;
1201
1202 CYToken *token(new(pool) CYToken());
1203 token->type_ = type;
1204 token->value_ = value;
1205 token->next_ = token;
1206 token->prev_ = &token->next_;
1207 return token;
1208 }
1209
1210 CYToken *ParseExpression(apr_pool_t *pool, const char *prompt) {
1211 CYToken *token(ParseToken(pool, prompt));
1212 return token;
1213 }
1214 };
1215
1216 void CYConsole(FILE *fin, FILE *fout, FILE *ferr) {
1217 CYParser parser(fin, fout);
1218
1219 for (;;) { _pooled
1220 CYPool pool;
1221 CYToken *token(parser.ParseExpression(pool, ">>>"));
1222 if (token == NULL)
1223 return;
1224 fputs("<", fout);
1225 CYToken *next(token);
1226 do {
1227 fputs(next->value_, fout);
1228 next = next->next_;
1229 fputs("|", fout);
1230 } while (next != token);
1231 fputs(">\n", fout);
1232 #if 0
1233 JSStringRef script(JSStringCreateWithUTF8CString(line.c_str()));
1234
1235 JSContextRef context(JSGetContext());
1236
1237 JSValueRef exception(NULL);
1238 JSValueRef result(JSEvaluateScript(context, script, NULL, NULL, 0, &exception));
1239 JSStringRelease(script);
1240
1241 if (exception != NULL)
1242 result = exception;
1243
1244 if (!JSValueIsUndefined(context, result)) {
1245 CFStringRef json;
1246
1247 @try { json:
1248 json = JSValueToJSONCopy(context, result);
1249 } @catch (id error) {
1250 CYThrow(context, error, &result);
1251 goto json;
1252 }
1253
1254 fputs([reinterpret_cast<const NSString *>(json) UTF8String], fout);
1255 CFRelease(json);
1256
1257 fputs("\n", fout);
1258 fflush(fout);
1259 }
1260 #endif
1261 }
1262 }
1263
1264 MSInitialize { _pooled
1265 apr_initialize();
1266
1267 NSCFBoolean_ = objc_getClass("NSCFBoolean");
1268
1269 pid_t pid(getpid());
1270
1271 struct sockaddr_in address;
1272 address.sin_len = sizeof(address);
1273 address.sin_family = AF_INET;
1274 address.sin_addr.s_addr = INADDR_ANY;
1275 address.sin_port = htons(10000 + pid);
1276
1277 CFDataRef data(CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8 *>(&address), sizeof(address)));
1278
1279 CFSocketSignature signature;
1280 signature.protocolFamily = AF_INET;
1281 signature.socketType = SOCK_STREAM;
1282 signature.protocol = IPPROTO_TCP;
1283 signature.address = data;
1284
1285 CFSocketRef socket(CFSocketCreateWithSocketSignature(kCFAllocatorDefault, &signature, kCFSocketAcceptCallBack, &OnAccept, NULL));
1286 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0), kCFRunLoopDefaultMode);
1287
1288 JSClassDefinition definition;
1289
1290 definition = kJSClassDefinitionEmpty;
1291 definition.className = "Pointer";
1292 definition.staticValues = Pointer_staticValues;
1293 definition.finalize = &Pointer_finalize;
1294 Pointer_ = JSClassCreate(&definition);
1295
1296 definition = kJSClassDefinitionEmpty;
1297 definition.className = "Functor";
1298 definition.parentClass = Pointer_;
1299 definition.callAsFunction = &ffi_callAsFunction;
1300 Functor_ = JSClassCreate(&definition);
1301
1302 definition = kJSClassDefinitionEmpty;
1303 definition.className = "Selector";
1304 definition.parentClass = Pointer_;
1305 Selector_ = JSClassCreate(&definition);
1306
1307 definition = kJSClassDefinitionEmpty;
1308 definition.className = "Instance_";
1309 definition.getProperty = &Instance_getProperty;
1310 definition.callAsConstructor = &Instance_callAsConstructor;
1311 definition.finalize = &Instance_finalize;
1312 Instance_ = JSClassCreate(&definition);
1313
1314 definition = kJSClassDefinitionEmpty;
1315 definition.getProperty = &Global_getProperty;
1316 JSClassRef Global(JSClassCreate(&definition));
1317
1318 JSContextRef context(JSGlobalContextCreate(Global));
1319 Context_ = context;
1320
1321 JSObjectRef global(JSContextGetGlobalObject(context));
1322
1323 CYSetProperty(context, global, "ffi", JSObjectMakeConstructor(context, Functor_, &ffi));
1324
1325 CYSetProperty(context, global, "objc_msgSend", JSObjectMakeFunctionWithCallback(context, CYString("objc_msgSend"), &$objc_msgSend));
1326
1327 Bridge_ = [[NSMutableDictionary dictionaryWithContentsOfFile:@"/usr/lib/libcycript.plist"] retain];
1328
1329 Tokens_.insert(TokenMap::value_type("break", CYTokenBreak));
1330 Tokens_.insert(TokenMap::value_type("case", CYTokenCase));
1331 Tokens_.insert(TokenMap::value_type("catch", CYTokenCatch));
1332 Tokens_.insert(TokenMap::value_type("continue", CYTokenContinue));
1333 Tokens_.insert(TokenMap::value_type("default", CYTokenDefault));
1334 Tokens_.insert(TokenMap::value_type("delete", CYTokenDelete));
1335 Tokens_.insert(TokenMap::value_type("do", CYTokenDo));
1336 Tokens_.insert(TokenMap::value_type("else", CYTokenElse));
1337 Tokens_.insert(TokenMap::value_type("finally", CYTokenFinally));
1338 Tokens_.insert(TokenMap::value_type("for", CYTokenFor));
1339 Tokens_.insert(TokenMap::value_type("function", CYTokenFunction));
1340 Tokens_.insert(TokenMap::value_type("if", CYTokenIf));
1341 Tokens_.insert(TokenMap::value_type("in", CYTokenIn));
1342 Tokens_.insert(TokenMap::value_type("instanceof", CYTokenInstanceOf));
1343 Tokens_.insert(TokenMap::value_type("new", CYTokenNew));
1344 Tokens_.insert(TokenMap::value_type("return", CYTokenReturn));
1345 Tokens_.insert(TokenMap::value_type("switch", CYTokenSwitch));
1346 Tokens_.insert(TokenMap::value_type("this", CYTokenThis));
1347 Tokens_.insert(TokenMap::value_type("throw", CYTokenThrow));
1348 Tokens_.insert(TokenMap::value_type("try", CYTokenTry));
1349 Tokens_.insert(TokenMap::value_type("typeof", CYTokenTypeOf));
1350 Tokens_.insert(TokenMap::value_type("var", CYTokenVar));
1351 Tokens_.insert(TokenMap::value_type("void", CYTokenVoid));
1352 Tokens_.insert(TokenMap::value_type("while", CYTokenWhile));
1353 Tokens_.insert(TokenMap::value_type("with", CYTokenWith));
1354
1355 Tokens_.insert(TokenMap::value_type("&", CYTokenAmpersand));
1356 Tokens_.insert(TokenMap::value_type("&&", CYTokenAmpersandAmpersand));
1357 Tokens_.insert(TokenMap::value_type("&=", CYTokenAmpersandEqual));
1358 Tokens_.insert(TokenMap::value_type("^", CYTokenCarrot));
1359 Tokens_.insert(TokenMap::value_type("^=", CYTokenCarrotEqual));
1360 Tokens_.insert(TokenMap::value_type(":", CYTokenColon));
1361 Tokens_.insert(TokenMap::value_type(",", CYTokenComma));
1362 Tokens_.insert(TokenMap::value_type("=", CYTokenEqual));
1363 Tokens_.insert(TokenMap::value_type("==", CYTokenEqualEqual));
1364 Tokens_.insert(TokenMap::value_type("===", CYTokenEqualEqualEqual));
1365 Tokens_.insert(TokenMap::value_type("!", CYTokenExclamation));
1366 Tokens_.insert(TokenMap::value_type("!=", CYTokenExclamationEqual));
1367 Tokens_.insert(TokenMap::value_type("!==", CYTokenExclamationEqualEqual));
1368 Tokens_.insert(TokenMap::value_type("-", CYTokenHyphen));
1369 Tokens_.insert(TokenMap::value_type("-=", CYTokenHyphenEqual));
1370 Tokens_.insert(TokenMap::value_type("--", CYTokenHyphenHyphen));
1371 Tokens_.insert(TokenMap::value_type("<", CYTokenLeft));
1372 Tokens_.insert(TokenMap::value_type("<=", CYTokenLeftEqual));
1373 Tokens_.insert(TokenMap::value_type("<<", CYTokenLeftLeft));
1374 Tokens_.insert(TokenMap::value_type("<<=", CYTokenLeftLeftEqual));
1375 Tokens_.insert(TokenMap::value_type("%", CYTokenPercent));
1376 Tokens_.insert(TokenMap::value_type("%=", CYTokenPercentEqual));
1377 Tokens_.insert(TokenMap::value_type(".", CYTokenPeriod));
1378 Tokens_.insert(TokenMap::value_type("|", CYTokenPipe));
1379 Tokens_.insert(TokenMap::value_type("|=", CYTokenPipeEqual));
1380 Tokens_.insert(TokenMap::value_type("||", CYTokenPipePipe));
1381 Tokens_.insert(TokenMap::value_type("+", CYTokenPlus));
1382 Tokens_.insert(TokenMap::value_type("+=", CYTokenPlusEqual));
1383 Tokens_.insert(TokenMap::value_type("++", CYTokenPlusPlus));
1384 Tokens_.insert(TokenMap::value_type("?", CYTokenQuestion));
1385 Tokens_.insert(TokenMap::value_type(">", CYTokenRight));
1386 Tokens_.insert(TokenMap::value_type(">=", CYTokenRightEqual));
1387 Tokens_.insert(TokenMap::value_type(">>", CYTokenRightRight));
1388 Tokens_.insert(TokenMap::value_type(">>=", CYTokenRightRightEqual));
1389 Tokens_.insert(TokenMap::value_type(">>>", CYTokenRightRightRight));
1390 Tokens_.insert(TokenMap::value_type(">>>=", CYTokenRightRightRightEqual));
1391 Tokens_.insert(TokenMap::value_type(";", CYTokenSemiColon));
1392 Tokens_.insert(TokenMap::value_type("/", CYTokenSlash));
1393 Tokens_.insert(TokenMap::value_type("/=", CYTokenSlashEqual));
1394 Tokens_.insert(TokenMap::value_type("*", CYTokenStar));
1395 Tokens_.insert(TokenMap::value_type("*=", CYTokenStarEqual));
1396 Tokens_.insert(TokenMap::value_type("~", CYTokenTilde));
1397
1398 name_ = JSStringCreateWithUTF8CString("name");
1399 message_ = JSStringCreateWithUTF8CString("message");
1400 length_ = JSStringCreateWithUTF8CString("length");
1401
1402 JSValueRef exception(NULL);
1403 JSValueRef value(JSObjectGetProperty(JSGetContext(), global, CYString("Array"), &exception));
1404 CYThrow(context, exception);
1405 Array_ = JSValueToObject(JSGetContext(), value, &exception);
1406 CYThrow(context, exception);
1407 }